@@ -16,14 +16,12 @@ import type { Revision, RevisionResult } from '../useRevision'
16
16
17
17
import Change from './Change'
18
18
import type { Dir , Order } from './Change'
19
+ import GridRow from './GridRow'
19
20
20
21
const useAddedStyles = M . makeStyles ( ( t ) => ( {
21
22
root : {
22
23
...t . typography . body2 ,
23
24
} ,
24
- cell : {
25
- padding : t . spacing ( 1.5 , 1 ) ,
26
- } ,
27
25
} ) )
28
26
29
27
interface AddedProps {
@@ -35,13 +33,9 @@ interface AddedProps {
35
33
function Added ( { className, dir, logicalKey } : AddedProps ) {
36
34
const classes = useAddedStyles ( )
37
35
return (
38
- < GridRow className = { cx ( classes . root , className ) } >
39
- < div className = { classes . cell } >
40
- < Change order = { dir === 'forward' ? 'former' : 'latter' } > { logicalKey } </ Change >
41
- </ div >
42
- < div className = { classes . cell } >
43
- < Change order = { dir === 'forward' ? 'latter' : 'former' } > { logicalKey } </ Change >
44
- </ div >
36
+ < GridRow className = { cx ( classes . root , className ) } divided >
37
+ < Change order = { dir === 'forward' ? 'former' : 'latter' } > { logicalKey } </ Change >
38
+ < Change order = { dir === 'forward' ? 'latter' : 'former' } > { logicalKey } </ Change >
45
39
</ GridRow >
46
40
)
47
41
}
@@ -50,10 +44,6 @@ const useUnmodifiedStyles = M.makeStyles((t) => ({
50
44
root : {
51
45
...t . typography . body2 ,
52
46
color : t . palette . text . secondary ,
53
- padding : t . spacing ( 1.5 , 1 ) ,
54
- } ,
55
- label : {
56
- paddingLeft : t . spacing ( 1 ) ,
57
47
} ,
58
48
} ) )
59
49
@@ -66,43 +56,90 @@ function Unmodified({ className, logicalKey }: UnmodifiedProps) {
66
56
const classes = useUnmodifiedStyles ( )
67
57
return (
68
58
< GridRow className = { cx ( classes . root , className ) } >
69
- < span > { logicalKey } </ span >
70
- < i className = { classes . label } > Unmodified</ i >
59
+ { logicalKey }
60
+ < i > Unmodified</ i >
71
61
</ GridRow >
72
62
)
73
63
}
74
64
75
- const useGridRowStyles = M . makeStyles ( {
76
- root : {
77
- display : 'grid' ,
78
- gridTemplateColumns : '1fr 1fr' ,
79
- } ,
80
- } )
65
+ type Modifications = Record < keyof Model . PackageEntry , boolean >
81
66
82
- interface GridRowProps {
67
+ function getEntryChanges (
68
+ entry : Model . PackageEntry ,
69
+ modified : Modifications ,
70
+ ) : Partial < Model . PackageEntry > {
71
+ return {
72
+ physicalKey : modified . physicalKey ? entry . physicalKey : undefined ,
73
+ hash : modified . hash ? entry . hash : undefined ,
74
+ size : modified . size ? entry . size : undefined ,
75
+ meta : modified . meta ? entry . meta : undefined ,
76
+ }
77
+ }
78
+
79
+ interface ModifiedProps {
80
+ className : string
81
+ logicalKey : string
82
+ dir : Dir
83
+ left : Model . PackageEntry
84
+ right : Model . PackageEntry
85
+ modified : Modifications
86
+ }
87
+
88
+ function Modified ( { className, dir, logicalKey, left, right, modified } : ModifiedProps ) {
89
+ const changes = React . useMemo (
90
+ ( ) => ( {
91
+ left : getEntryChanges ( left , modified ) ,
92
+ right : getEntryChanges ( right , modified ) ,
93
+ } ) ,
94
+ [ left , right , modified ] ,
95
+ )
96
+ return (
97
+ < GridRow className = { className } dense divided >
98
+ < EntrySide
99
+ logicalKey = { logicalKey }
100
+ order = { dir === 'forward' ? 'former' : 'latter' }
101
+ changes = { changes . left }
102
+ />
103
+ < EntrySide
104
+ logicalKey = { logicalKey }
105
+ order = { dir === 'forward' ? 'latter' : 'former' }
106
+ changes = { changes . right }
107
+ />
108
+ </ GridRow >
109
+ )
110
+ }
111
+
112
+ interface PhysicalKeyProps {
83
113
className ?: string
84
- children : React . ReactNode
114
+ url : string
85
115
}
86
116
87
- function GridRow ( { className, children } : GridRowProps ) {
88
- const classes = useGridRowStyles ( )
89
- return < div className = { cx ( className , classes . root ) } > { children } </ div >
117
+ function PhysicalKey ( { className, url } : PhysicalKeyProps ) {
118
+ const { urls } = NamedRoutes . use ( )
119
+ const to = React . useMemo ( ( ) => {
120
+ const { bucket, key, version } = s3paths . parseS3Url ( url )
121
+ return urls . bucketFile ( bucket , key , version )
122
+ } , [ url , urls ] )
123
+ return (
124
+ < StyledLink className = { className } to = { to } >
125
+ { url }
126
+ </ StyledLink >
127
+ )
90
128
}
91
129
92
130
type Changes =
93
- | { _tag : 'unmodified ' ; logicalKey : string }
94
- | { _tag : 'added' ; logicalKey : string ; entry : Model . PackageEntry ; dir : Dir }
131
+ | { _tag : 'added ' ; entry : Model . PackageEntry }
132
+ | { _tag : 'unmodified' }
95
133
| {
96
134
_tag : 'modified'
97
- logicalKey : string
98
- left : Partial < Model . PackageEntry >
99
- right : Partial < Model . PackageEntry >
135
+ modified : Modifications
136
+ left : Model . PackageEntry
137
+ right : Model . PackageEntry
100
138
}
101
139
102
140
const useEntrySideStyles = M . makeStyles ( ( t ) => ( {
103
141
root : {
104
- overflow : 'hidden' ,
105
- padding : t . spacing ( 1 ) ,
142
+ ...t . typography . body1 ,
106
143
} ,
107
144
hash : {
108
145
fontFamily : t . typography . monospace . fontFamily ,
@@ -111,7 +148,7 @@ const useEntrySideStyles = M.makeStyles((t) => ({
111
148
whiteSpace : 'nowrap' ,
112
149
display : 'flex' ,
113
150
alignItems : 'center' ,
114
- marginTop : t . spacing ( 1 ) ,
151
+ margin : t . spacing ( 1 , 0 , 0 ) ,
115
152
} ,
116
153
value : {
117
154
overflow : 'hidden' ,
@@ -130,39 +167,39 @@ interface EntrySideProps {
130
167
order : Order
131
168
}
132
169
133
- function EntrySide ( { className , changes, logicalKey, order } : EntrySideProps ) {
170
+ function EntrySide ( { changes, logicalKey, order } : EntrySideProps ) {
134
171
const classes = useEntrySideStyles ( )
135
172
return (
136
- < div className = { cx ( classes . root , className ) } >
173
+ < div className = { classes . root } >
137
174
< M . Typography variant = "subtitle2" color = "textSecondary" >
138
175
{ logicalKey }
139
176
</ M . Typography >
140
177
141
178
{ changes . physicalKey && (
142
- < M . Typography className = { classes . property } >
179
+ < p className = { classes . property } >
143
180
< Icons . LinkOutlined className = { classes . icon } fontSize = "small" />
144
181
< Change order = { order } className = { classes . value } >
145
182
< PhysicalKey url = { changes . physicalKey } />
146
183
</ Change >
147
- </ M . Typography >
184
+ </ p >
148
185
) }
149
186
150
187
{ changes . hash && (
151
- < M . Typography className = { classes . property } >
188
+ < p className = { classes . property } >
152
189
< Icons . LockOutlined className = { classes . icon } fontSize = "small" />
153
190
< Change order = { order } className = { cx ( classes . hash , classes . value ) } >
154
191
{ changes . hash . value }
155
192
</ Change >
156
- </ M . Typography >
193
+ </ p >
157
194
) }
158
195
159
196
{ changes . size && (
160
- < M . Typography variant = "body2" className = { classes . property } >
197
+ < p className = { classes . property } >
161
198
< Icons . InsertDriveFileOutlined className = { classes . icon } fontSize = "small" />
162
199
< Change order = { order } className = { classes . value } >
163
200
{ readableBytes ( changes . size ) }
164
201
</ Change >
165
- </ M . Typography >
202
+ </ p >
166
203
) }
167
204
168
205
{ changes . meta && (
@@ -175,85 +212,34 @@ function EntrySide({ className, changes, logicalKey, order }: EntrySideProps) {
175
212
)
176
213
}
177
214
178
- interface PhysicalKeyProps {
179
- className ?: string
180
- url : string
181
- }
182
-
183
- function PhysicalKey ( { className, url } : PhysicalKeyProps ) {
184
- const { urls } = NamedRoutes . use ( )
185
- const to = React . useMemo ( ( ) => {
186
- const { bucket, key, version } = s3paths . parseS3Url ( url )
187
- return urls . bucketFile ( bucket , key , version )
188
- } , [ url , urls ] )
189
- return (
190
- < StyledLink className = { className } to = { to } >
191
- { url }
192
- </ StyledLink >
193
- )
194
- }
195
-
196
- function getEntryChanges (
197
- entry : Model . PackageEntry ,
198
- modified : Record < keyof Model . PackageEntry , boolean > ,
199
- ) {
200
- return {
201
- physicalKey : modified . physicalKey ? entry . physicalKey : undefined ,
202
- hash : modified . hash ? entry . hash : undefined ,
203
- size : modified . size ? entry . size : undefined ,
204
- meta : modified . meta ? entry . meta : undefined ,
205
- }
206
- }
207
-
208
- function getChanges (
209
- dir : Dir ,
210
- logicalKey : string ,
211
- left ?: Model . PackageEntry ,
212
- right ?: Model . PackageEntry ,
213
- ) : Changes {
215
+ function getChanges ( left ?: Model . PackageEntry , right ?: Model . PackageEntry ) : Changes {
214
216
if ( ! left || ! right ) {
215
217
const entry = left || right
216
218
if ( ! entry ) {
217
219
throw new Error ( 'Must be at least one entry' )
218
220
}
219
- return { _tag : 'added' , logicalKey , entry, dir }
221
+ return { _tag : 'added' , entry }
220
222
}
221
223
222
224
const physicalKey = left . physicalKey !== right . physicalKey
223
225
const hash = left . hash . value !== right . hash . value
224
226
const size = left . size !== right . size
225
227
const meta = JSON . stringify ( left . meta ) !== JSON . stringify ( right . meta )
226
- if ( ! physicalKey && ! hash && ! size && ! meta ) return { _tag : 'unmodified' , logicalKey }
227
- const modified = { physicalKey, hash, size, meta }
228
- return {
229
- _tag : 'modified' ,
230
- logicalKey,
231
- left : getEntryChanges ( left , modified ) ,
232
- right : getEntryChanges ( right , modified ) ,
233
- }
234
- }
228
+ if ( ! physicalKey && ! hash && ! size && ! meta ) return { _tag : 'unmodified' }
235
229
236
- const useEntriesRowStyles = M . makeStyles ( ( t ) => ( {
237
- side : {
238
- borderLeft : `1px solid ${ t . palette . divider } ` ,
239
- } ,
240
- } ) )
230
+ return { _tag : 'modified' , modified : { physicalKey, hash, size, meta } , left, right }
231
+ }
241
232
242
- interface EntriesRowProps {
233
+ interface RowProps {
243
234
className : string
244
235
logicalKey : string
245
236
left ?: Model . PackageEntry
246
237
right ?: Model . PackageEntry
247
238
dir : Dir
248
239
}
249
240
250
- function EntriesRow ( { className, dir, logicalKey, left, right } : EntriesRowProps ) {
251
- const classes = useEntriesRowStyles ( )
252
-
253
- const changes = React . useMemo (
254
- ( ) => getChanges ( dir , logicalKey , left , right ) ,
255
- [ dir , logicalKey , left , right ] ,
256
- )
241
+ function Row ( { className, dir, logicalKey, left, right } : RowProps ) {
242
+ const changes = React . useMemo ( ( ) => getChanges ( left , right ) , [ left , right ] )
257
243
258
244
switch ( changes . _tag ) {
259
245
case 'unmodified' :
@@ -262,19 +248,14 @@ function EntriesRow({ className, dir, logicalKey, left, right }: EntriesRowProps
262
248
return < Added className = { className } dir = { dir } logicalKey = { logicalKey } />
263
249
case 'modified' :
264
250
return (
265
- < GridRow className = { className } >
266
- < EntrySide
267
- logicalKey = { logicalKey }
268
- order = { dir === 'forward' ? 'former' : 'latter' }
269
- changes = { changes . left }
270
- />
271
- < EntrySide
272
- className = { classes . side }
273
- logicalKey = { logicalKey }
274
- order = { dir === 'forward' ? 'latter' : 'former' }
275
- changes = { changes . right }
276
- />
277
- </ GridRow >
251
+ < Modified
252
+ className = { className }
253
+ dir = { dir }
254
+ logicalKey = { logicalKey }
255
+ left = { changes . left }
256
+ right = { changes . right }
257
+ modified = { changes . modified }
258
+ />
278
259
)
279
260
default :
280
261
assertNever ( changes )
@@ -284,14 +265,20 @@ function EntriesRow({ className, dir, logicalKey, left, right }: EntriesRowProps
284
265
const useStyles = M . makeStyles ( ( t ) => ( {
285
266
row : {
286
267
borderBottom : `1px solid ${ t . palette . divider } ` ,
268
+ '&:last-child' : {
269
+ borderBottom : 'none' ,
270
+ } ,
287
271
} ,
288
272
head : {
289
- overflow : 'hidden' ,
290
- padding : t . spacing ( 1 ) ,
291
273
background : t . palette . background . default ,
292
- '& + &' : {
293
- borderLeft : `1px solid ${ t . palette . divider } ` ,
294
- } ,
274
+ ...t . typography . caption ,
275
+ } ,
276
+ empty : {
277
+ ...t . typography . body2 ,
278
+ color : t . palette . text . secondary ,
279
+ fontStyle : 'italic' ,
280
+ textAlign : 'center' ,
281
+ padding : t . spacing ( 2 ) ,
295
282
} ,
296
283
} ) )
297
284
@@ -321,25 +308,17 @@ function EntriesDiff({ left, right }: EntriesDiffProps) {
321
308
)
322
309
323
310
if ( entries . keys . length === 0 ) {
324
- return (
325
- < M . Typography
326
- variant = "body2"
327
- color = "textSecondary"
328
- style = { { fontStyle : 'italic' , textAlign : 'center' , padding : 16 } }
329
- >
330
- No entries found
331
- </ M . Typography >
332
- )
311
+ return < div className = { classes . empty } > No entries found</ div >
333
312
}
334
313
335
314
return (
336
315
< div >
337
- < GridRow className = { classes . row } >
338
- < div className = { classes . head } > { left . hash } </ div >
339
- < div className = { classes . head } > { right . hash } </ div >
316
+ < GridRow className = { cx ( classes . row , classes . head ) } dense divided >
317
+ { left . hash }
318
+ { right . hash }
340
319
</ GridRow >
341
320
{ entries . keys . map ( ( logicalKey ) => (
342
- < EntriesRow
321
+ < Row
343
322
className = { classes . row }
344
323
key = { logicalKey }
345
324
logicalKey = { logicalKey }
0 commit comments