1
1
import { Suspense , useState } from "react" ;
2
- import { Spinner , Select } from "@fluentui/react-components" ;
2
+ import {
3
+ Spinner ,
4
+ Select ,
5
+ makeStyles ,
6
+ mergeClasses ,
7
+ tokens ,
8
+ } from "@fluentui/react-components" ;
3
9
import { useSuspenseQuery } from "@tanstack/react-query" ;
4
10
5
11
import { LOG_LEVELS , type ClientIdType } from "../../api/urbackupserver" ;
6
12
import { urbackupServer } from "../../App" ;
7
13
import { SelectClientCombobox } from "../../components/SelectClientCombobox" ;
8
14
import { LogsTable } from "./LogsTable" ;
9
15
import { TableWrapper } from "../../components/TableWrapper" ;
16
+ import { LiveLog } from "./LiveLog" ;
17
+ import { LogReports } from "./LogReports" ;
10
18
11
19
const FORMATTED_LOG_LEVELS = {
12
20
INFO : "All" ,
13
21
WARNING : "Warnings" ,
14
22
ERROR : "Errors" ,
15
23
} as const ;
16
24
25
+ const useStyles = makeStyles ( {
26
+ root : {
27
+ display : "grid" ,
28
+ gap : tokens . spacingVerticalXXL ,
29
+ gridTemplateColumns : "1fr 320px" ,
30
+ alignItems : "start" ,
31
+ // Adjust height to match client log tables with breadcrumbs
32
+ marginBlockStart : "-7px" ,
33
+ } ,
34
+ reports : {
35
+ display : "flex" ,
36
+ flexDirection : "column" ,
37
+ background : tokens . colorNeutralCardBackground ,
38
+ padding : tokens . spacingHorizontalL ,
39
+ borderRadius : tokens . borderRadiusLarge ,
40
+ height : "min-content" ,
41
+ } ,
42
+ } ) ;
43
+
17
44
export function ClientLogs ( ) {
18
45
const [ selectedClientId , setSelectedClientId ] = useState <
19
46
ClientIdType | undefined
@@ -23,6 +50,8 @@ export function ClientLogs() {
23
50
( typeof LOG_LEVELS ) [ keyof typeof LOG_LEVELS ]
24
51
> ( LOG_LEVELS . ERROR ) ;
25
52
53
+ const classes = useStyles ( ) ;
54
+
26
55
// Used for fetching clients list for logs
27
56
const logsResult = useSuspenseQuery ( {
28
57
queryKey : [ "logs" ] ,
@@ -32,31 +61,45 @@ export function ClientLogs() {
32
61
const { clients } = logsResult . data ;
33
62
34
63
return (
35
- < TableWrapper >
36
- < h3 > Logs</ h3 >
37
- < div className = "cluster" >
38
- < SelectClientCombobox
39
- clients = { clients }
40
- onSelect = { ( id ) => setSelectedClientId ( Number ( id ) ) }
41
- />
42
- < div className = "cluster" data-spacing = "s" >
43
- Filter
44
- < Select
45
- id = "log-level"
46
- defaultValue = { logLevel }
47
- onChange = { ( _ , data ) => setLogLevel ( + data . value as typeof logLevel ) }
48
- >
49
- { Object . entries ( LOG_LEVELS ) . map ( ( [ k , v ] ) => (
50
- < option key = { k } value = { v } >
51
- { FORMATTED_LOG_LEVELS [ k as keyof typeof LOG_LEVELS ] }
52
- </ option >
53
- ) ) }
54
- </ Select >
64
+ < div className = { classes . root } >
65
+ < TableWrapper >
66
+ < div className = "repel" >
67
+ < h3 > Logs</ h3 >
68
+ < LiveLog clients = { clients } > Open Live Log</ LiveLog >
69
+ </ div >
70
+ < div className = "cluster" >
71
+ < SelectClientCombobox
72
+ clients = { clients }
73
+ onSelect = { ( id ) => setSelectedClientId ( Number ( id ) ) }
74
+ />
75
+ < div className = "cluster" data-spacing = "s" >
76
+ Filter
77
+ < Select
78
+ id = "log-level"
79
+ defaultValue = { logLevel }
80
+ onChange = { ( _ , data ) =>
81
+ setLogLevel ( + data . value as typeof logLevel )
82
+ }
83
+ >
84
+ { Object . entries ( LOG_LEVELS ) . map ( ( [ k , v ] ) => (
85
+ < option key = { k } value = { v } >
86
+ { FORMATTED_LOG_LEVELS [ k as keyof typeof LOG_LEVELS ] }
87
+ </ option >
88
+ ) ) }
89
+ </ Select >
90
+ </ div >
55
91
</ div >
92
+ < Suspense fallback = { < Spinner /> } >
93
+ < LogsTable selectedClientId = { selectedClientId } logLevel = { logLevel } />
94
+ </ Suspense >
95
+ </ TableWrapper >
96
+ < div className = { mergeClasses ( classes . reports , "flow" ) } >
97
+ < h4 > Reports</ h4 >
98
+ < p > Automatically send reports to emails.</ p >
99
+ < Suspense fallback = { < Spinner /> } >
100
+ < LogReports />
101
+ </ Suspense >
56
102
</ div >
57
- < Suspense fallback = { < Spinner /> } >
58
- < LogsTable selectedClientId = { selectedClientId } logLevel = { logLevel } />
59
- </ Suspense >
60
- </ TableWrapper >
103
+ </ div >
61
104
) ;
62
105
}
0 commit comments