1
1
import {
2
2
Badge ,
3
3
Button ,
4
+ Center ,
5
+ Checkbox ,
6
+ Divider ,
7
+ Flex ,
8
+ Grid ,
9
+ GridItem ,
4
10
Heading ,
11
+ HStack ,
5
12
Progress ,
6
13
ProgressIndicator ,
7
- Stack ,
8
- Text ,
9
- useColorModeValue ,
14
+ Spacer ,
10
15
VStack ,
11
16
} from "@hope-ui/solid"
12
- import { createSignal , Show } from "solid-js"
17
+ import { createSignal , For , Show } from "solid-js"
13
18
import { useT , useFetch } from "~/hooks"
14
19
import { PEmptyResp , TaskInfo } from "~/types"
15
20
import { handleResp , notify , r } from "~/utils"
16
21
import { TasksProps } from "./Tasks"
22
+ import { me } from "~/store"
17
23
18
24
enum TaskStateEnum {
19
25
Pending ,
@@ -47,7 +53,18 @@ const StateMap: Record<
47
53
const Creator = ( props : { name : string ; role : number } ) => {
48
54
if ( props . role < 0 ) return null
49
55
const roleColors = [ "info" , "neutral" , "accent" ]
50
- return < Badge colorScheme = { roleColors [ props . role ] as any } > { props . name } </ Badge >
56
+ return (
57
+ < Badge
58
+ colorScheme = { roleColors [ props . role ] as any }
59
+ css = { {
60
+ overflow : "hidden" ,
61
+ whiteSpace : "nowrap" ,
62
+ textOverflow : "ellipsis" ,
63
+ } }
64
+ >
65
+ { props . name }
66
+ </ Badge >
67
+ )
51
68
}
52
69
53
70
export const TaskState = ( props : { state : number } ) => {
@@ -59,7 +76,32 @@ export const TaskState = (props: { state: number }) => {
59
76
)
60
77
}
61
78
62
- export const Task = ( props : TaskInfo & TasksProps ) => {
79
+ export type TaskOrderBy = "name" | "creator" | "state" | "progress"
80
+
81
+ export interface TaskCol {
82
+ name : TaskOrderBy | "operation"
83
+ textAlign : "left" | "right" | "center"
84
+ w : any
85
+ }
86
+
87
+ export interface TaskControlCallback {
88
+ setSelected : ( id : string , v : boolean ) => void
89
+ setExpanded : ( id : string , v : boolean ) => void
90
+ }
91
+
92
+ export const cols : TaskCol [ ] = [
93
+ {
94
+ name : "name" ,
95
+ textAlign : "left" ,
96
+ w : me ( ) . role === 2 ? "calc(100% - 660px)" : "calc(100% - 540px)" ,
97
+ } ,
98
+ { name : "creator" , textAlign : "center" , w : me ( ) . role === 2 ? "120px" : "0" } ,
99
+ { name : "state" , textAlign : "center" , w : "100px" } ,
100
+ { name : "progress" , textAlign : "left" , w : "160px" } ,
101
+ { name : "operation" , textAlign : "right" , w : "280px" } ,
102
+ ]
103
+
104
+ export const Task = ( props : TaskInfo & TasksProps & TaskControlCallback ) => {
63
105
const t = useT ( )
64
106
const operateName = props . done === "undone" ? "cancel" : "delete"
65
107
const canRetry = props . done === "done" && props . state === TaskStateEnum . Failed
@@ -71,58 +113,56 @@ export const Task = (props: TaskInfo & TasksProps) => {
71
113
( ) : PEmptyResp => r . post ( `/task/${ props . type } /retry?tid=${ props . id } ` ) ,
72
114
)
73
115
const [ deleted , setDeleted ] = createSignal ( false )
116
+ const matches : RegExpMatchArray | null = props . name . match (
117
+ props . nameAnalyzer . regex ,
118
+ )
119
+ const title =
120
+ matches === null ? props . name : props . nameAnalyzer . title ( matches )
74
121
return (
75
122
< Show when = { ! deleted ( ) } >
76
- < Stack
77
- bgColor = { useColorModeValue ( "$background" , "$neutral3" ) ( ) }
78
- w = "$full"
79
- overflowX = "auto"
80
- shadow = "$md"
81
- rounded = "$lg"
82
- p = "$2"
83
- direction = { { "@initial" : "column" , "@xl" : "row" } }
84
- spacing = "$2"
85
- >
86
- < VStack w = "$full" alignItems = "start" spacing = "$1" >
123
+ < HStack w = "$full" p = "$2" >
124
+ < HStack w = { cols [ 0 ] . w } spacing = "$1" >
125
+ < Checkbox
126
+ // colorScheme="neutral"
127
+ on :click = { ( e : MouseEvent ) => {
128
+ e . stopPropagation ( )
129
+ } }
130
+ checked = { props . selected }
131
+ onChange = { ( e : any ) => {
132
+ props . setSelected ( props . id , e . target . checked as boolean )
133
+ } }
134
+ />
87
135
< Heading
88
136
size = "sm"
89
137
css = { {
90
- wordBreak : "break-all" ,
138
+ whiteSpace : "nowrap" ,
139
+ overflow : "hidden" ,
140
+ textOverflow : "ellipsis" ,
91
141
} }
92
142
>
93
- { props . name }
143
+ { title }
94
144
</ Heading >
95
- < Creator name = { props . creator } role = { props . creator_role } />
145
+ </ HStack >
146
+ < Show when = { me ( ) . role === 2 } >
147
+ < Center w = { cols [ 1 ] . w } >
148
+ < Creator name = { props . creator } role = { props . creator_role } />
149
+ </ Center >
150
+ </ Show >
151
+ < Center w = { cols [ 2 ] . w } >
96
152
< TaskState state = { props . state } />
97
- < Text
98
- css = { {
99
- wordBreak : "break-all" ,
100
- } }
101
- >
102
- { props . status }
103
- </ Text >
104
- < Show when = { props . error } >
105
- < Text color = "$danger9" css = { { wordBreak : "break-all" } } >
106
- { props . error }
107
- </ Text >
108
- </ Show >
109
- < Progress
110
- w = "$full"
111
- trackColor = "$info3"
112
- rounded = "$full"
113
- size = "sm"
114
- value = { props . progress }
115
- >
116
- < ProgressIndicator color = "$info8" rounded = "$md" />
117
- { /* <ProgressLabel /> */ }
118
- </ Progress >
119
- </ VStack >
120
-
121
- < Stack
122
- direction = { { "@initial" : "row" , "@xl" : "column" } }
123
- justifyContent = { { "@xl" : "center" } }
124
- spacing = "$1"
153
+ </ Center >
154
+ < Progress
155
+ w = { cols [ 3 ] . w }
156
+ trackColor = "$info3"
157
+ rounded = "$full"
158
+ size = "sm"
159
+ value = { props . progress }
125
160
>
161
+ < ProgressIndicator color = "$info8" rounded = "$md" />
162
+ { /* <ProgressLabel /> */ }
163
+ </ Progress >
164
+ < Flex w = { cols [ 4 ] . w } gap = "$1" >
165
+ < Spacer />
126
166
< Show when = { props . canRetry } >
127
167
< Button
128
168
disabled = { ! canRetry }
@@ -152,8 +192,69 @@ export const Task = (props: TaskInfo & TasksProps) => {
152
192
>
153
193
{ t ( `global.${ operateName } ` ) }
154
194
</ Button >
155
- </ Stack >
156
- </ Stack >
195
+ < Button
196
+ colorScheme = "neutral"
197
+ onClick = { ( ) => {
198
+ props . setExpanded ( props . id , ! props . expanded )
199
+ } }
200
+ >
201
+ { props . expanded ? t ( `tasks.fold` ) : t ( `tasks.expand` ) }
202
+ </ Button >
203
+ </ Flex >
204
+ </ HStack >
205
+ < Show when = { props . expanded } >
206
+ < VStack
207
+ css = { { wordBreak : "break-all" , fontSize : "0.8em" } }
208
+ w = "$full"
209
+ pl = "$2"
210
+ pr = "$2"
211
+ >
212
+ < Grid
213
+ templateColumns = "min-content 1fr"
214
+ w = "$full"
215
+ columnGap = "$4"
216
+ mb = "$2"
217
+ >
218
+ < Show when = { matches !== null } >
219
+ < For each = { Object . entries ( props . nameAnalyzer . attrs ) } >
220
+ { ( entry ) => (
221
+ < >
222
+ < GridItem
223
+ color = "$neutral9"
224
+ textAlign = "right"
225
+ css = { { whiteSpace : "nowrap" } }
226
+ >
227
+ { entry [ 0 ] }
228
+ </ GridItem >
229
+ < GridItem color = "$neutral9" >
230
+ { entry [ 1 ] ( matches as RegExpMatchArray ) }
231
+ </ GridItem >
232
+ </ >
233
+ ) }
234
+ </ For >
235
+ </ Show >
236
+ < GridItem
237
+ color = "$neutral9"
238
+ textAlign = "right"
239
+ css = { { whiteSpace : "nowrap" } }
240
+ >
241
+ { t ( `tasks.attr.status` ) }
242
+ </ GridItem >
243
+ < GridItem color = "$neutral9" > { props . status } </ GridItem >
244
+ < Show when = { props . error } >
245
+ < GridItem
246
+ color = "$danger9"
247
+ textAlign = "right"
248
+ css = { { whiteSpace : "nowrap" } }
249
+ >
250
+ { t ( `tasks.attr.err` ) }
251
+ </ GridItem >
252
+ < GridItem color = "$danger9" > { props . error } </ GridItem >
253
+ </ Show >
254
+ </ Grid >
255
+ < Divider />
256
+ </ VStack >
257
+ </ Show >
157
258
</ Show >
158
259
)
159
260
}
0 commit comments