@ -5,6 +5,7 @@ import Modal from '@app/components/Common/Modal';
import PageTitle from '@app/components/Common/PageTitle' ;
import PageTitle from '@app/components/Common/PageTitle' ;
import Table from '@app/components/Common/Table' ;
import Table from '@app/components/Common/Table' ;
import Tooltip from '@app/components/Common/Tooltip' ;
import Tooltip from '@app/components/Common/Tooltip' ;
import useDebouncedState from '@app/hooks/useDebouncedState' ;
import { useUpdateQueryParams } from '@app/hooks/useUpdateQueryParams' ;
import { useUpdateQueryParams } from '@app/hooks/useUpdateQueryParams' ;
import globalMessages from '@app/i18n/globalMessages' ;
import globalMessages from '@app/i18n/globalMessages' ;
import Error from '@app/pages/_error' ;
import Error from '@app/pages/_error' ;
@ -17,6 +18,7 @@ import {
FilterIcon ,
FilterIcon ,
PauseIcon ,
PauseIcon ,
PlayIcon ,
PlayIcon ,
SearchIcon ,
} from '@heroicons/react/solid' ;
} from '@heroicons/react/solid' ;
import type {
import type {
LogMessage ,
LogMessage ,
@ -59,6 +61,8 @@ const SettingsLogs = () => {
const { addToast } = useToasts ( ) ;
const { addToast } = useToasts ( ) ;
const [ currentFilter , setCurrentFilter ] = useState < Filter > ( 'debug' ) ;
const [ currentFilter , setCurrentFilter ] = useState < Filter > ( 'debug' ) ;
const [ currentPageSize , setCurrentPageSize ] = useState ( 25 ) ;
const [ currentPageSize , setCurrentPageSize ] = useState ( 25 ) ;
const [ searchFilter , debouncedSearchFilter , setSearchFilter ] =
useDebouncedState ( '' ) ;
const [ refreshInterval , setRefreshInterval ] = useState ( 5000 ) ;
const [ refreshInterval , setRefreshInterval ] = useState ( 5000 ) ;
const [ activeLog , setActiveLog ] = useState < {
const [ activeLog , setActiveLog ] = useState < {
isOpen : boolean ;
isOpen : boolean ;
@ -76,7 +80,9 @@ const SettingsLogs = () => {
const { data , error } = useSWR < LogsResultsResponse > (
const { data , error } = useSWR < LogsResultsResponse > (
` /api/v1/settings/logs?take= ${ currentPageSize } &skip= ${
` /api/v1/settings/logs?take= ${ currentPageSize } &skip= ${
pageIndex * currentPageSize
pageIndex * currentPageSize
} & filter = $ { currentFilter } ` ,
} & filter = $ { currentFilter } $ {
debouncedSearchFilter ? ` &search= ${ debouncedSearchFilter } ` : ''
} ` ,
{
{
refreshInterval : refreshInterval ,
refreshInterval : refreshInterval ,
revalidateOnFocus : false ,
revalidateOnFocus : false ,
@ -118,15 +124,13 @@ const SettingsLogs = () => {
} ) ;
} ) ;
} ;
} ;
if ( ! data && ! error ) {
// check if there's no data and no errors in the table
return < LoadingSpinner / > ;
// so as to show a spinner inside the table and not refresh the whole component
}
if ( ! data && error ) {
if ( ! data ) {
return < Error statusCode = { 500 } / > ;
return < Error statusCode = { 500 } / > ;
}
}
const hasNextPage = data . pageInfo . pages > pageIndex + 1 ;
const hasNextPage = data ? . pageInfo . pages ? ? 0 > pageIndex + 1 ;
const hasPrevPage = pageIndex > 0 ;
const hasPrevPage = pageIndex > 0 ;
return (
return (
@ -245,10 +249,21 @@ const SettingsLogs = () => {
appDataPath : appData ? appData . appDataPath : '/app/config' ,
appDataPath : appData ? appData . appDataPath : '/app/config' ,
} ) }
} ) }
< / p >
< / p >
< div className = "mt-2 flex flex-grow flex-row sm:flex-grow-0 sm:justify-end" >
< div className = "mt-2 flex flex-grow flex-col sm:flex-grow-0 sm:flex-row sm:justify-end" >
< div className = "mb-2 flex flex-grow sm:mb-0 sm:mr-2 md:flex-grow-0" >
< span className = "inline-flex cursor-default items-center rounded-l-md border border-r-0 border-gray-500 bg-gray-800 px-3 text-sm text-gray-100" >
< SearchIcon className = "h-6 w-6" / >
< / span >
< input
type = "text"
className = "rounded-r-only"
value = { searchFilter }
onChange = { ( e ) = > setSearchFilter ( e . target . value as string ) }
/ >
< / div >
< div className = "mb-2 flex flex-1 flex-row justify-between sm:mb-0 sm:flex-none" >
< div className = "mb-2 flex flex-1 flex-row justify-between sm:mb-0 sm:flex-none" >
< Button
< Button
className = "mr-2 w-full flex-grow"
className = "mr-2 flex flex-grow"
buttonType = { refreshInterval ? 'default' : 'primary' }
buttonType = { refreshInterval ? 'default' : 'primary' }
onClick = { ( ) = > toggleLogs ( ) }
onClick = { ( ) = > toggleLogs ( ) }
>
>
@ -259,8 +274,7 @@ const SettingsLogs = () => {
) }
) }
< / span >
< / span >
< / Button >
< / Button >
< / div >
< div className = "flex flex-grow" >
< div className = "mb-2 flex flex-1 sm:mb-0 sm:flex-none" >
< span className = "inline-flex cursor-default items-center rounded-l-md border border-r-0 border-gray-500 bg-gray-800 px-3 text-sm text-gray-100" >
< span className = "inline-flex cursor-default items-center rounded-l-md border border-r-0 border-gray-500 bg-gray-800 px-3 text-sm text-gray-100" >
< FilterIcon className = "h-6 w-6" / >
< FilterIcon className = "h-6 w-6" / >
< / span >
< / span >
@ -289,6 +303,7 @@ const SettingsLogs = () => {
< / select >
< / select >
< / div >
< / div >
< / div >
< / div >
< / div >
< Table >
< Table >
< thead >
< thead >
< tr >
< tr >
@ -300,7 +315,14 @@ const SettingsLogs = () => {
< / tr >
< / tr >
< / thead >
< / thead >
< Table.TBody >
< Table.TBody >
{ data . results . map ( ( row : LogMessage , index : number ) = > {
{ ! data ? (
< tr >
< Table.TD colSpan = { 5 } noPadding >
< LoadingSpinner / >
< / Table.TD >
< / tr >
) : (
data . results . map ( ( row : LogMessage , index : number ) = > {
return (
return (
< tr key = { ` log-list- ${ index } ` } >
< tr key = { ` log-list- ${ index } ` } >
< Table.TD className = "text-gray-300" >
< Table.TD className = "text-gray-300" >
@ -338,8 +360,8 @@ const SettingsLogs = () => {
content = { intl . formatMessage ( messages . viewdetails ) }
content = { intl . formatMessage ( messages . viewdetails ) }
>
>
< Button
< Button
buttonType = "primary"
buttonSize = "sm"
buttonSize = "sm"
buttonType = "primary"
onClick = { ( ) = >
onClick = { ( ) = >
setActiveLog ( { log : row , isOpen : true } )
setActiveLog ( { log : row , isOpen : true } )
}
}
@ -364,9 +386,10 @@ const SettingsLogs = () => {
< / Table.TD >
< / Table.TD >
< / tr >
< / tr >
) ;
) ;
} ) }
} )
) }
{ data . results . length === 0 && (
{ data ? . results . length === 0 && (
< tr className = "relative h-24 p-2 text-white" >
< tr className = "relative h-24 p-2 text-white" >
< Table.TD colSpan = { 5 } noPadding >
< Table.TD colSpan = { 5 } noPadding >
< div className = "flex w-screen flex-col items-center justify-center p-6 md:w-full" >
< div className = "flex w-screen flex-col items-center justify-center p-6 md:w-full" >
@ -396,15 +419,15 @@ const SettingsLogs = () => {
>
>
< div className = "hidden lg:flex lg:flex-1" >
< div className = "hidden lg:flex lg:flex-1" >
< p className = "text-sm" >
< p className = "text-sm" >
{ data . results . length > 0 &&
{ ( data ? . results . length ? ? 0 ) > 0 &&
intl . formatMessage ( globalMessages . showingresults , {
intl . formatMessage ( globalMessages . showingresults , {
from : pageIndex * currentPageSize + 1 ,
from : pageIndex * currentPageSize + 1 ,
to :
to :
data . results . length < currentPageSize
data ? . results . length ? ? 0 < currentPageSize
? pageIndex * currentPageSize +
? pageIndex * currentPageSize +
data . results . length
( data ? . results . length ? ? 0 )
: ( pageIndex + 1 ) * currentPageSize ,
: ( pageIndex + 1 ) * currentPageSize ,
total : data .pageInfo.results,
total : data ? .pageInfo.results ? ? 0 ,
strong : ( msg : React.ReactNode ) = > (
strong : ( msg : React.ReactNode ) = > (
< span className = "font-medium" > { msg } < / span >
< span className = "font-medium" > { msg } < / span >
) ,
) ,