1
1
import Button from "@material-ui/core/Button"
2
2
import Link from "@material-ui/core/Link"
3
- import { makeStyles , Theme } from "@material-ui/core/styles"
3
+ import { makeStyles } from "@material-ui/core/styles"
4
4
import Table from "@material-ui/core/Table"
5
5
import TableBody from "@material-ui/core/TableBody"
6
6
import TableCell from "@material-ui/core/TableCell"
7
7
import TableContainer from "@material-ui/core/TableContainer"
8
8
import TableHead from "@material-ui/core/TableHead"
9
9
import TableRow from "@material-ui/core/TableRow"
10
- import KeyboardArrowRight from "@material-ui/icons/KeyboardArrowRight"
11
10
import AddIcon from "@material-ui/icons/AddOutlined"
12
- import useTheme from "@material-ui/styles/useTheme"
13
11
import { AlertBanner } from "components/AlertBanner/AlertBanner"
14
12
import { ChooseOne , Cond } from "components/Conditionals/ChooseOne"
15
13
import { Maybe } from "components/Conditionals/Maybe"
@@ -28,7 +26,6 @@ import {
28
26
PageHeaderTitle ,
29
27
} from "../../components/PageHeader/PageHeader"
30
28
import { Stack } from "../../components/Stack/Stack"
31
- import { TableCellLink } from "../../components/TableCellLink/TableCellLink"
32
29
import { TableLoader } from "../../components/TableLoader/TableLoader"
33
30
import {
34
31
HelpTooltip ,
@@ -39,6 +36,11 @@ import {
39
36
} from "../../components/Tooltips/HelpTooltip/HelpTooltip"
40
37
import { EmptyTemplates } from "./EmptyTemplates"
41
38
import { TemplatesContext } from "xServices/templates/templatesXService"
39
+ import { useClickableTableRow } from "hooks/useClickableTableRow"
40
+ import { Template } from "api/typesGenerated"
41
+ import { combineClasses } from "util/combineClasses"
42
+ import { colors } from "theme/colors"
43
+ import ArrowForwardOutlined from "@material-ui/icons/ArrowForwardOutlined"
42
44
43
45
export const Language = {
44
46
developerCount : ( activeCount : number ) : string => {
@@ -54,7 +56,6 @@ export const Language = {
54
56
templateTooltipText :
55
57
"With templates you can create a common configuration for your workspaces using Terraform." ,
56
58
templateTooltipLink : "Manage templates" ,
57
- createdByLabel : "Created by" ,
58
59
}
59
60
60
61
const TemplateHelpTooltip : React . FC = ( ) => {
@@ -71,16 +72,80 @@ const TemplateHelpTooltip: React.FC = () => {
71
72
)
72
73
}
73
74
75
+ const TemplateRow : FC < { template : Template } > = ( { template } ) => {
76
+ const templatePageLink = `/templates/${ template . name } `
77
+ const hasIcon = template . icon && template . icon !== ""
78
+ const navigate = useNavigate ( )
79
+ const styles = useStyles ( )
80
+ const { className : clickableClassName , ...clickableRow } =
81
+ useClickableTableRow ( ( ) => {
82
+ navigate ( templatePageLink )
83
+ } )
84
+
85
+ return (
86
+ < TableRow
87
+ key = { template . id }
88
+ data-testid = { `template-${ template . id } ` }
89
+ { ...clickableRow }
90
+ className = { combineClasses ( [ clickableClassName , styles . tableRow ] ) }
91
+ >
92
+ < TableCell >
93
+ < AvatarData
94
+ title = {
95
+ template . display_name . length > 0
96
+ ? template . display_name
97
+ : template . name
98
+ }
99
+ subtitle = { template . description }
100
+ highlightTitle
101
+ avatar = {
102
+ hasIcon && (
103
+ < div className = { styles . templateIconWrapper } >
104
+ < img alt = "" src = { template . icon } />
105
+ </ div >
106
+ )
107
+ }
108
+ />
109
+ </ TableCell >
110
+
111
+ < TableCell className = { styles . secondary } >
112
+ { Language . developerCount ( template . active_user_count ) }
113
+ </ TableCell >
114
+
115
+ < TableCell className = { styles . secondary } >
116
+ { formatTemplateBuildTime ( template . build_time_stats . start . P50 ) }
117
+ </ TableCell >
118
+
119
+ < TableCell data-chromatic = "ignore" className = { styles . secondary } >
120
+ { createDayString ( template . updated_at ) }
121
+ </ TableCell >
122
+
123
+ < TableCell className = { styles . actionCell } >
124
+ < Button
125
+ variant = "outlined"
126
+ size = "small"
127
+ className = { styles . actionButton }
128
+ startIcon = { < ArrowForwardOutlined /> }
129
+ title = { `Create a workspace using the ${ template . display_name } template` }
130
+ onClick = { ( e ) => {
131
+ e . stopPropagation ( )
132
+ navigate ( `/templates/${ template . name } /workspace` )
133
+ } }
134
+ >
135
+ Use template
136
+ </ Button >
137
+ </ TableCell >
138
+ </ TableRow >
139
+ )
140
+ }
141
+
74
142
export interface TemplatesPageViewProps {
75
143
context : TemplatesContext
76
144
}
77
145
78
146
export const TemplatesPageView : FC <
79
147
React . PropsWithChildren < TemplatesPageViewProps >
80
148
> = ( { context } ) => {
81
- const styles = useStyles ( )
82
- const navigate = useNavigate ( )
83
- const theme : Theme = useTheme ( )
84
149
const { templates, error, examples, permissions } = context
85
150
const isLoading = ! templates
86
151
const isEmpty = Boolean ( templates && templates . length === 0 )
@@ -136,11 +201,10 @@ export const TemplatesPageView: FC<
136
201
< Table >
137
202
< TableHead >
138
203
< TableRow >
139
- < TableCell width = "34%" > { Language . nameLabel } </ TableCell >
140
- < TableCell width = "16%" > { Language . usedByLabel } </ TableCell >
141
- < TableCell width = "16%" > { Language . buildTimeLabel } </ TableCell >
142
- < TableCell width = "16%" > { Language . lastUpdatedLabel } </ TableCell >
143
- < TableCell width = "16%" > { Language . createdByLabel } </ TableCell >
204
+ < TableCell width = "35%" > { Language . nameLabel } </ TableCell >
205
+ < TableCell width = "15%" > { Language . usedByLabel } </ TableCell >
206
+ < TableCell width = "10%" > { Language . buildTimeLabel } </ TableCell >
207
+ < TableCell width = "15%" > { Language . lastUpdatedLabel } </ TableCell >
144
208
< TableCell width = "1%" > </ TableCell >
145
209
</ TableRow >
146
210
</ TableHead >
@@ -158,91 +222,9 @@ export const TemplatesPageView: FC<
158
222
</ Cond >
159
223
160
224
< Cond >
161
- { templates ?. map ( ( template ) => {
162
- const templatePageLink = `/templates/${ template . name } `
163
- const hasIcon = template . icon && template . icon !== ""
164
-
165
- return (
166
- < TableRow
167
- key = { template . id }
168
- hover
169
- data-testid = { `template-${ template . id } ` }
170
- tabIndex = { 0 }
171
- onKeyDown = { ( event ) => {
172
- if ( event . key === "Enter" ) {
173
- navigate ( templatePageLink )
174
- }
175
- } }
176
- className = { styles . clickableTableRow }
177
- >
178
- < TableCellLink to = { templatePageLink } >
179
- < AvatarData
180
- title = {
181
- template . display_name . length > 0
182
- ? template . display_name
183
- : template . name
184
- }
185
- subtitle = { template . description }
186
- highlightTitle
187
- avatar = {
188
- hasIcon && (
189
- < div className = { styles . templateIconWrapper } >
190
- < img alt = "" src = { template . icon } />
191
- </ div >
192
- )
193
- }
194
- />
195
- </ TableCellLink >
196
-
197
- < TableCellLink to = { templatePageLink } >
198
- < span
199
- style = { { color : theme . palette . text . secondary } }
200
- >
201
- { Language . developerCount (
202
- template . active_user_count ,
203
- ) }
204
- </ span >
205
- </ TableCellLink >
206
-
207
- < TableCellLink to = { templatePageLink } >
208
- < span
209
- style = { { color : theme . palette . text . secondary } }
210
- >
211
- { formatTemplateBuildTime (
212
- template . build_time_stats . start . P50 ,
213
- ) }
214
- </ span >
215
- </ TableCellLink >
216
-
217
- < TableCellLink
218
- data-chromatic = "ignore"
219
- to = { templatePageLink }
220
- >
221
- < span
222
- style = { { color : theme . palette . text . secondary } }
223
- >
224
- { createDayString ( template . updated_at ) }
225
- </ span >
226
- </ TableCellLink >
227
-
228
- < TableCellLink to = { templatePageLink } >
229
- < span
230
- style = { { color : theme . palette . text . secondary } }
231
- >
232
- { template . created_by_name }
233
- </ span >
234
- </ TableCellLink >
235
-
236
- < TableCellLink to = { templatePageLink } >
237
- < div className = { styles . arrowCell } >
238
- < KeyboardArrowRight
239
- className = { styles . arrowRight }
240
- />
241
- </ div >
242
- </ TableCellLink >
243
- </ TableRow >
244
- )
245
- } ) }
225
+ { templates ?. map ( ( template ) => (
226
+ < TemplateRow key = { template . id } template = { template } />
227
+ ) ) }
246
228
</ Cond >
247
229
</ ChooseOne >
248
230
</ TableBody >
@@ -255,27 +237,6 @@ export const TemplatesPageView: FC<
255
237
}
256
238
257
239
const useStyles = makeStyles ( ( theme ) => ( {
258
- clickableTableRow : {
259
- "&:hover td" : {
260
- backgroundColor : theme . palette . action . hover ,
261
- } ,
262
-
263
- "&:focus" : {
264
- outline : `1px solid ${ theme . palette . secondary . dark } ` ,
265
- } ,
266
-
267
- "& .MuiTableCell-root:last-child" : {
268
- paddingRight : theme . spacing ( 2 ) ,
269
- } ,
270
- } ,
271
- arrowRight : {
272
- color : theme . palette . text . secondary ,
273
- width : 20 ,
274
- height : 20 ,
275
- } ,
276
- arrowCell : {
277
- display : "flex" ,
278
- } ,
279
240
templateIconWrapper : {
280
241
// Same size then the avatar component
281
242
width : 36 ,
@@ -286,4 +247,23 @@ const useStyles = makeStyles((theme) => ({
286
247
width : "100%" ,
287
248
} ,
288
249
} ,
250
+ actionCell : {
251
+ whiteSpace : "nowrap" ,
252
+ } ,
253
+ secondary : {
254
+ color : theme . palette . text . secondary ,
255
+ } ,
256
+ tableRow : {
257
+ "&:hover $actionButton" : {
258
+ color : theme . palette . text . primary ,
259
+ borderColor : colors . gray [ 11 ] ,
260
+ "&:hover" : {
261
+ borderColor : theme . palette . text . primary ,
262
+ } ,
263
+ } ,
264
+ } ,
265
+ actionButton : {
266
+ color : theme . palette . text . secondary ,
267
+ transition : "none" ,
268
+ } ,
289
269
} ) )
0 commit comments