@@ -6,190 +6,169 @@ import { Chart as ChartJS, ArcElement, Tooltip, Legend, Title } from "chart.js";
6
6
ChartJS . register ( ArcElement , Tooltip , Legend , Title ) ;
7
7
8
8
const JobStatusPieChart = ( { data } ) => {
9
- if ( ! data || ! Array . isArray ( data ) ) {
10
- return (
11
- < Box sx = { { height : 300 , width : "100%" , position : "relative" } } >
12
- < Typography > No data available</ Typography >
13
- </ Box >
14
- ) ;
15
- }
16
-
17
- const statusCounts = data . reduce (
18
- ( acc , job ) => {
19
- const status = job . status ;
20
- if ( status ?. succeeded ) {
21
- acc . Completed ++ ;
22
- } else if (
23
- status ?. state ?. phase === "Running" ||
24
- status ?. state ?. phase === "Pending"
25
- ) {
26
- acc . Running ++ ;
27
- } else if ( status ?. state ?. phase === "Failed" ) {
28
- acc . Failed ++ ;
29
- }
30
- return acc ;
31
- } ,
32
- {
33
- Completed : 0 ,
34
- Running : 0 ,
35
- Failed : 0 ,
9
+ if ( ! data || ! Array . isArray ( data ) ) {
10
+ return (
11
+ < Box sx = { { height : 300 , width : "100%" , position : "relative" } } >
12
+ < Typography > No data available</ Typography >
13
+ </ Box >
14
+ ) ;
36
15
}
37
- ) ;
38
16
39
- const total = Object . values ( statusCounts ) . reduce ( ( a , b ) => a + b , 0 ) ;
40
- const colors = {
41
- Completed : "#4caf50" ,
42
- Running : "#2196f3" ,
43
- Failed : "#f44336" ,
44
- } ;
17
+ const statusCounts = data . reduce (
18
+ ( acc , job ) => {
19
+ const status = job . status ;
20
+ if ( status ?. succeeded ) {
21
+ acc . Completed ++ ;
22
+ } else if (
23
+ status ?. state ?. phase === "Running" ||
24
+ status ?. state ?. phase === "Pending"
25
+ ) {
26
+ acc . Running ++ ;
27
+ } else if ( status ?. state ?. phase === "Failed" ) {
28
+ acc . Failed ++ ;
29
+ }
30
+ return acc ;
31
+ } ,
32
+ {
33
+ Completed : 0 ,
34
+ Running : 0 ,
35
+ Failed : 0 ,
36
+ }
37
+ ) ;
45
38
46
- const chartData = {
47
- labels : Object . keys ( statusCounts ) ,
48
- datasets : [
49
- {
50
- data : Object . values ( statusCounts ) ,
51
- backgroundColor : Object . values ( colors ) ,
52
- borderColor : "white" ,
53
- borderWidth : 2 ,
54
- hoverBorderColor : "white" ,
55
- hoverBorderWidth : 3 ,
56
- } ,
57
- ] ,
58
- } ;
39
+ const total = Object . values ( statusCounts ) . reduce ( ( a , b ) => a + b , 0 ) ;
40
+ const colors = {
41
+ Completed : "#4caf50" ,
42
+ Running : "#2196f3" ,
43
+ Failed : "#f44336" ,
44
+ } ;
59
45
60
- const options = {
61
- responsive : true ,
62
- maintainAspectRatio : false ,
63
- cutout : "70%" ,
64
- plugins : {
65
- legend : {
66
- display : false ,
67
- } ,
68
- tooltip : {
69
- enabled : false ,
70
- } ,
71
- } ,
72
- } ;
46
+ const chartData = {
47
+ labels : Object . keys ( statusCounts ) ,
48
+ datasets : [
49
+ {
50
+ data : Object . values ( statusCounts ) ,
51
+ backgroundColor : Object . values ( colors ) ,
52
+ borderColor : "white" ,
53
+ borderWidth : 2 ,
54
+ hoverBorderColor : "white" ,
55
+ hoverBorderWidth : 3 ,
56
+ } ,
57
+ ] ,
58
+ } ;
73
59
74
- const CustomLegend = ( ) => (
75
- < Box sx = { { pl : 2 } } >
76
- { Object . entries ( statusCounts ) . map ( ( [ status , count ] ) => (
77
- < Box
78
- key = { status }
79
- sx = { {
80
- display : "flex" ,
81
- alignItems : "center" ,
82
- mb : 1.5 ,
83
- } }
84
- >
85
- < Box
86
- sx = { {
87
- width : 12 ,
88
- height : 12 ,
89
- borderRadius : "50%" ,
90
- backgroundColor : colors [ status ] ,
91
- mr : 1 ,
92
- } }
93
- />
94
- < Typography variant = "body2" sx = { { mr : 2 } } >
95
- { status }
96
- </ Typography >
97
- < Typography variant = "body2" color = "text.secondary" >
98
- { count } ({ total > 0 ? ( ( count / total ) * 100 ) . toFixed ( 1 ) : 0 } %)
99
- </ Typography >
100
- </ Box >
101
- ) ) }
102
- </ Box >
103
- ) ;
60
+ const options = {
61
+ responsive : true ,
62
+ maintainAspectRatio : false ,
63
+ cutout : "70%" ,
64
+ plugins : {
65
+ legend : {
66
+ display : false ,
67
+ } ,
68
+ tooltip : {
69
+ enabled : false ,
70
+ } ,
71
+ } ,
72
+ } ;
104
73
105
- const hasData = Object . values ( statusCounts ) . some ( ( count ) => count > 0 ) ;
74
+ const hasData = Object . values ( statusCounts ) . some ( ( count ) => count > 0 ) ;
106
75
107
- return (
108
- < Box
109
- sx = { {
110
- height : "100%" ,
111
- display : "flex" ,
112
- flexDirection : "column" ,
113
- } }
114
- >
115
- < Typography variant = "h6" align = "center" sx = { { mb : 1 } } >
116
- Jobs Status
117
- </ Typography >
118
-
119
- < Grid container spacing = { 2 } sx = { { flex : 1 } } >
120
- < Grid item xs = { 8 } >
121
- < Box
76
+ return (
77
+ < Box
122
78
sx = { {
123
- height : "75%" , // 增加饼图高度至卡片的约2/3
124
- position : "relative" ,
125
- display : "flex" ,
126
- alignItems : "center" ,
127
- justifyContent : "center" ,
128
- mt : 2 , // 向下微调位置
79
+ height : "100%" ,
80
+ display : "flex" ,
81
+ flexDirection : "column" ,
129
82
} }
130
- >
131
- < Doughnut
132
- data = { chartData }
133
- options = { {
134
- ...options ,
135
- maintainAspectRatio : false ,
136
- } }
137
- />
138
- < Typography
139
- variant = "h4"
140
- sx = { {
141
- position : "absolute" ,
142
- top : "50%" ,
143
- left : "50%" ,
144
- transform : "translate(-50%, -50%)" ,
145
- textAlign : "center" ,
146
- } }
147
- >
148
- { total }
83
+ >
84
+ < Typography variant = "h6" align = "center" sx = { { mb : 1 } } >
85
+ Jobs Status
149
86
</ Typography >
150
- </ Box >
151
- </ Grid >
152
- < Grid item xs = { 4 } >
153
- < Box
154
- sx = { {
155
- display : "flex" ,
156
- flexDirection : "column" ,
157
- justifyContent : "flex-start" , // 将图例向上对齐
158
- mt : 4 , // 向上移动图例
159
- } }
160
- >
161
- { Object . entries ( statusCounts ) . map ( ( [ status , count ] ) => (
162
- < Box
163
- key = { status }
87
+
88
+ < Box
164
89
sx = { {
165
- display : "flex" ,
166
- alignItems : "center" ,
167
- mb : 1.5 ,
90
+ display : "flex" ,
91
+ flexDirection : "row" ,
92
+ justifyContent : "space-between" ,
93
+ alignItems : "flex-start" ,
94
+ flexWrap : "wrap" , // 使内容在屏幕较窄时自动换行
95
+ gap : 2 , // 适当的间距
96
+ width : "100%" ,
168
97
} }
169
- >
98
+ >
99
+ < Box
100
+ sx = { {
101
+ flex : 1 ,
102
+ minWidth : "250px" , // 保证图表不会过小
103
+ height : "300px" , // 固定高度,以便适应各种屏幕
104
+ position : "relative" ,
105
+ display : "flex" ,
106
+ alignItems : "center" ,
107
+ justifyContent : "center" ,
108
+ } }
109
+ >
110
+ < Doughnut
111
+ data = { chartData }
112
+ options = { {
113
+ ...options ,
114
+ maintainAspectRatio : false ,
115
+ } }
116
+ />
117
+ < Typography
118
+ variant = "h4"
119
+ sx = { {
120
+ position : "absolute" ,
121
+ top : "50%" ,
122
+ left : "50%" ,
123
+ transform : "translate(-50%, -50%)" ,
124
+ textAlign : "center" ,
125
+ } }
126
+ >
127
+ { total }
128
+ </ Typography >
129
+ </ Box >
130
+
170
131
< Box
171
- sx = { {
172
- width : 12 ,
173
- height : 12 ,
174
- borderRadius : "50%" ,
175
- backgroundColor : colors [ status ] ,
176
- mr : 1 ,
177
- } }
178
- />
179
- < Typography variant = "body2" sx = { { mr : 2 } } >
180
- { status }
181
- </ Typography >
182
- < Typography variant = "body2" color = "text.secondary" >
183
- { count } ({ total > 0 ? ( ( count / total ) * 100 ) . toFixed ( 1 ) : 0 }
184
- %)
185
- </ Typography >
186
- </ Box >
187
- ) ) }
188
- </ Box >
189
- </ Grid >
190
- </ Grid >
191
- </ Box >
192
- ) ;
132
+ sx = { {
133
+ flex : 1 ,
134
+ minWidth : "250px" , // 保证图例不会过小
135
+ display : "flex" ,
136
+ flexDirection : "column" ,
137
+ justifyContent : "flex-start" , // 图例顶部对齐
138
+ alignItems : "flex-start" , // 左对齐
139
+ textAlign : "left" ,
140
+ } }
141
+ >
142
+ { Object . entries ( statusCounts ) . map ( ( [ status , count ] ) => (
143
+ < Box
144
+ key = { status }
145
+ sx = { {
146
+ display : "flex" ,
147
+ alignItems : "center" ,
148
+ mb : 1.5 ,
149
+ } }
150
+ >
151
+ < Box
152
+ sx = { {
153
+ width : 12 ,
154
+ height : 12 ,
155
+ borderRadius : "50%" ,
156
+ backgroundColor : colors [ status ] ,
157
+ mr : 1 ,
158
+ } }
159
+ />
160
+ < Typography variant = "body2" sx = { { mr : 2 , minWidth : 70 } } >
161
+ { status }
162
+ </ Typography >
163
+ < Typography variant = "body2" color = "text.secondary" >
164
+ { count } ({ total > 0 ? ( ( count / total ) * 100 ) . toFixed ( 1 ) : 0 } %)
165
+ </ Typography >
166
+ </ Box >
167
+ ) ) }
168
+ </ Box >
169
+ </ Box >
170
+ </ Box >
171
+ ) ;
193
172
} ;
194
173
195
174
export default JobStatusPieChart ;
0 commit comments