admin/fs: ux: select items with single click, multiselect only through checkboxes

Massimo Melina committed Mar 15, 2022 at 14:58 UTC e54fe2c033b2cbb92361a547341554ffb330fbe8
1 file changed +50 -43
admin/src/FilePicker.ts
+50 -43
@@ -49,16 +49,8 @@ export default function FilePicker({ onSelect }: { onSelect:(v:string[])=>void }
49 return spinner()
50 const pathDelimiter = /[:\\]/.test(cwd) ? '\\' : '/'
51 const cwdPostfixed = enforceFinal(pathDelimiter, cwd)
52 - return h(Box, { display: 'flex', flexDirection: 'column', gap: 2 },
52 + return h(Box, { display: 'flex', flexDirection: 'column' },
53 h(Box, { display:'flex', gap: 1 },
54 - h(Button, {
55 - variant: 'contained',
56 - disabled: !sel.length,
57 - sx: { minWidth: 'max-content' },
58 - onClick() {
59 - onSelect(sel.map(x => cwdPostfixed + x))
60 - }
61 - }, `Select (${sel.length})`),
54 h(Button, {
55 onClick() {
56 setCwd( isWindowsDrive(cwd) ? '' : cwd.slice(0, cwd.lastIndexOf(pathDelimiter)) )
@@ -69,46 +61,61 @@ export default function FilePicker({ onSelect }: { onSelect:(v:string[])=>void }
61 setCwd('')
62 }
63 }, h(Home)),
72 - h(TextField, {
73 - value: filter,
74 - label: 'Filter results',
75 - onChange(ev) {
76 - setFilterBounced(ev.target.value)
77 - },
78 - sx: { minWidth: '20em' },
79 - fullWidth: true,
64 + h(StringField, {
65 + label: 'Current path',
66 + value: cwd,
67 + onChange: setCwd
68 }),
69 ),
82 - h(StringField, {
83 - label: 'Current path',
84 - value: cwd,
85 - onChange: setCwd
86 - }),
70 error ? h(Alert, { severity:'error' }, String(error))
71 : !list.length ? h(Typography, { p:1 }, 'No elements in this folder')
89 - : h(MenuList, { sx:{ maxHeight: 'calc(100vh - 24em)', overflow:'auto' } },
90 - list.map((it:DirEntry) =>
91 - h(MenuItem, {
92 - key: it.n,
93 - sx: { display: filterMatch(it.n) ? undefined : 'none' },
94 - onClick(){
95 - const id = it.n
96 - const removed = sel.filter(x => x !== id)
97 - setSel(removed.length < sel.length ? removed : [...sel, id])
72 + : h(Box, {},
73 + h(MenuList, { sx:{ maxHeight: 'calc(100vh - 24em)', overflow:'auto' } },
74 + list.map((it:DirEntry) =>
75 + h(MenuItem, {
76 + key: it.n,
77 + sx: { display: filterMatch(it.n) ? undefined : 'none' },
78 + onClick(){
79 + if (it.k === 'd')
80 + setCwd( cwdPostfixed + it.n )
81 + else
82 + onSelect([ cwdPostfixed + it.n ])
83 + }
84 },
99 - onDoubleClick(){
100 - if (it.k === 'd')
101 - setCwd( cwdPostfixed + it.n )
102 - else
103 - onSelect([ cwdPostfixed + it.n ])
104 - }
105 - },
106 - h(Checkbox, { checked: sel.includes(it.n) }),
107 - h(ListItemIcon, {}, h(it.k ? FolderIcon : FileIcon)),
108 - h(ListItemText, {}, it.n),
109 - it.k !== 'd' && it.s !== undefined && h(Typography, { variant:'body2', color:'text.secondary', ml:4 }, formatBytes(it.s) )
85 + h(Checkbox, {
86 + checked: sel.includes(it.n),
87 + onClick(ev){
88 + const id = it.n
89 + const removed = sel.filter(x => x !== id)
90 + setSel(removed.length < sel.length ? removed : [...sel, id])
91 + ev.stopPropagation()
92 + },
93 + }),
94 + h(ListItemIcon, {}, h(it.k ? FolderIcon : FileIcon)),
95 + h(ListItemText, {}, it.n),
96 + it.k !== 'd' && it.s !== undefined && h(Typography, { variant:'body2', color:'text.secondary', ml:4 }, formatBytes(it.s) )
97 + )
98 )
111 - )
99 + ),
100 + h(Box, { display:'flex', gap: 1 },
101 + h(Button, {
102 + variant: 'contained',
103 + disabled: !sel.length,
104 + sx: { minWidth: 'max-content' },
105 + onClick() {
106 + onSelect(sel.map(x => cwdPostfixed + x))
107 + }
108 + }, `Select (${sel.length})`),
109 + h(TextField, {
110 + value: filter,
111 + label: 'Filter results',
112 + onChange(ev) {
113 + setFilterBounced(ev.target.value)
114 + },
115 + sx: { minWidth: '20em' },
116 + fullWidth: true,
117 + }),
118 + ),
119 )
120 )
121 }