@onehat/ui 0.4.78 → 0.4.79
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1277,7 +1277,7 @@ function GridComponent(props) {
|
|
|
1277
1277
|
applySelectorSelected();
|
|
1278
1278
|
Repository.resumeEvents();
|
|
1279
1279
|
|
|
1280
|
-
if (((Repository.isRemote && !Repository.isLoaded) || forceLoadOnRender) && !disableLoadOnRender) { // default remote repositories to load on render, optionally force or disable load on render
|
|
1280
|
+
if (((Repository.isRemote && !Repository.isLoaded && !Repository.isLoading) || forceLoadOnRender) && !disableLoadOnRender) { // default remote repositories to load on render, optionally force or disable load on render
|
|
1281
1281
|
Repository.load();
|
|
1282
1282
|
}
|
|
1283
1283
|
|
|
@@ -45,6 +45,7 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
45
45
|
editorType,
|
|
46
46
|
onAdd,
|
|
47
47
|
onChange, // any kind of crud change
|
|
48
|
+
onBeforeDelete,
|
|
48
49
|
onDelete,
|
|
49
50
|
onSave, // this could also be called 'onEdit'
|
|
50
51
|
onEditorClose,
|
|
@@ -289,7 +290,15 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
289
290
|
if (_.isEmpty(selection) || (_.isArray(selection) && (selection.length > 1 || selection[0]?.isDestroyed))) {
|
|
290
291
|
return;
|
|
291
292
|
}
|
|
293
|
+
if (onBeforeDelete) {
|
|
294
|
+
// This listener is set by parent components using a prop
|
|
295
|
+
const listenerResult = await onBeforeDelete(selection);
|
|
296
|
+
if (listenerResult === false) {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
292
300
|
if (getListeners().onBeforeDelete) {
|
|
301
|
+
// This listener is set by child components using setWithEditListeners()
|
|
293
302
|
const listenerResult = await getListeners().onBeforeDelete();
|
|
294
303
|
if (listenerResult === false) {
|
|
295
304
|
return;
|
|
@@ -345,7 +354,15 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
345
354
|
return;
|
|
346
355
|
}
|
|
347
356
|
const selection = getSelection();
|
|
357
|
+
if (onBeforeDelete) {
|
|
358
|
+
// This listener is set by parent components using a prop
|
|
359
|
+
const listenerResult = await onBeforeDelete(selection);
|
|
360
|
+
if (listenerResult === false) {
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
348
364
|
if (getListeners().onBeforeDelete) {
|
|
365
|
+
// This listener is set by child components using setWithEditListeners()
|
|
349
366
|
const listenerResult = await getListeners().onBeforeDelete(selection);
|
|
350
367
|
if (listenerResult === false) {
|
|
351
368
|
return;
|
|
@@ -609,7 +609,7 @@ function TreeComponent(props) {
|
|
|
609
609
|
let nodes = [];
|
|
610
610
|
if (Repository) {
|
|
611
611
|
if (!Repository.isDestroyed) {
|
|
612
|
-
if (!Repository.
|
|
612
|
+
if (!Repository.isLoaded) {
|
|
613
613
|
nodes = await Repository.loadRootNodes(1);
|
|
614
614
|
} else {
|
|
615
615
|
nodes = Repository.getRootNodes();
|
|
@@ -58,8 +58,9 @@ import getSaved from '../../Functions/getSaved.js';
|
|
|
58
58
|
import setSaved from '../../Functions/setSaved.js';
|
|
59
59
|
import Folder from '../../Components/Icons/Folder.js';
|
|
60
60
|
import Plus from '../../Components/Icons/Plus.js';
|
|
61
|
-
import
|
|
61
|
+
import Trash from '../../Components/Icons/Trash.js';
|
|
62
62
|
import Edit from '../../Components/Icons/Edit.js';
|
|
63
|
+
import Rotate from '../../Components/Icons/Rotate.js';
|
|
63
64
|
import delay from '../../Functions/delay.js';
|
|
64
65
|
import _ from 'lodash';
|
|
65
66
|
|
|
@@ -86,17 +87,29 @@ function FileCardCustom(props) {
|
|
|
86
87
|
isDownloading = uploadStatus && inArray(uploadStatus, ['preparing', 'uploading', 'success']),
|
|
87
88
|
isPdf = mimetype === 'application/pdf';
|
|
88
89
|
|
|
89
|
-
let cardContent =
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
<
|
|
98
|
-
|
|
99
|
-
|
|
90
|
+
let cardContent =
|
|
91
|
+
<Pressable
|
|
92
|
+
onPress={() => {
|
|
93
|
+
downloadInBackground(downloadUrl);
|
|
94
|
+
}}
|
|
95
|
+
className="Pressable px-3 py-1 items-center flex-row rounded-[5px] border border-primary.700"
|
|
96
|
+
>
|
|
97
|
+
{isDownloading &&
|
|
98
|
+
<Spinner className="mr-2" />}
|
|
99
|
+
{onSee && isPdf &&
|
|
100
|
+
<IconButton
|
|
101
|
+
className="mr-1"
|
|
102
|
+
icon={Eye}
|
|
103
|
+
onPress={() => onSee(id)}
|
|
104
|
+
/>}
|
|
105
|
+
<Text>{filename}</Text>
|
|
106
|
+
{onDelete &&
|
|
107
|
+
<IconButton
|
|
108
|
+
className="ml-1"
|
|
109
|
+
icon={Xmark}
|
|
110
|
+
onPress={() => onDelete(id)}
|
|
111
|
+
/>}
|
|
112
|
+
</Pressable>;
|
|
100
113
|
|
|
101
114
|
// Wrap with drag source if needed
|
|
102
115
|
if (isDragSource) {
|
|
@@ -211,7 +224,7 @@ function AttachmentsElement(props) {
|
|
|
211
224
|
selectorSelectedField = 'id',
|
|
212
225
|
|
|
213
226
|
// withData
|
|
214
|
-
Repository,
|
|
227
|
+
Repository: Attachments,
|
|
215
228
|
|
|
216
229
|
// withAlert
|
|
217
230
|
showModal,
|
|
@@ -260,7 +273,7 @@ function AttachmentsElement(props) {
|
|
|
260
273
|
return setFilesRaw.current;
|
|
261
274
|
},
|
|
262
275
|
buildFiles = () => {
|
|
263
|
-
const files = _.map(
|
|
276
|
+
const files = _.map(Attachments.entities, (entity) => {
|
|
264
277
|
return {
|
|
265
278
|
id: entity.id, // string | number The identifier of the file
|
|
266
279
|
// file: null, // File The file object obtained from client drop or selection
|
|
@@ -301,11 +314,11 @@ function AttachmentsElement(props) {
|
|
|
301
314
|
doDelete = (id) => {
|
|
302
315
|
const
|
|
303
316
|
files = getFiles(),
|
|
304
|
-
file =
|
|
317
|
+
file = Attachments.getById(id);
|
|
305
318
|
if (file) {
|
|
306
319
|
// if the file exists in the repository, delete it there
|
|
307
|
-
|
|
308
|
-
|
|
320
|
+
Attachments.deleteById(id);
|
|
321
|
+
Attachments.save();
|
|
309
322
|
|
|
310
323
|
} else {
|
|
311
324
|
// simply remove it from the files array
|
|
@@ -388,7 +401,7 @@ function AttachmentsElement(props) {
|
|
|
388
401
|
});
|
|
389
402
|
if (!isError) {
|
|
390
403
|
setIsUploading(false);
|
|
391
|
-
|
|
404
|
+
Attachments.reload();
|
|
392
405
|
if (onUpload) {
|
|
393
406
|
onUpload(files);
|
|
394
407
|
}
|
|
@@ -397,77 +410,23 @@ function AttachmentsElement(props) {
|
|
|
397
410
|
},
|
|
398
411
|
|
|
399
412
|
// Lightbox
|
|
400
|
-
findFile = (id) => {
|
|
401
|
-
const files = getFiles();
|
|
402
|
-
if (useFileMosaic) {
|
|
403
|
-
return _.find(files, (file) => file.id === id);
|
|
404
|
-
}
|
|
405
|
-
return _.find(files, { id });
|
|
406
|
-
},
|
|
407
|
-
findPrevFile = (id) => {
|
|
408
|
-
const
|
|
409
|
-
files = getFiles(),
|
|
410
|
-
currentFile = findFile(id),
|
|
411
|
-
currentIx = _.findIndex(files, currentFile);
|
|
412
|
-
if (currentIx > 0) {
|
|
413
|
-
return files[currentIx - 1];
|
|
414
|
-
}
|
|
415
|
-
return null;
|
|
416
|
-
}
|
|
417
|
-
findNextFile = (url, id) => {
|
|
418
|
-
const
|
|
419
|
-
files = getFiles(),
|
|
420
|
-
currentFile = findFile(id),
|
|
421
|
-
currentIx = _.findIndex(files, currentFile);
|
|
422
|
-
if (currentIx < files.length - 1) {
|
|
423
|
-
return files[currentIx + 1];
|
|
424
|
-
}
|
|
425
|
-
return null;
|
|
426
|
-
},
|
|
427
413
|
buildModalBody = (id) => {
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
updateModalBody(buildModalBody(prevFile.id));
|
|
445
|
-
};
|
|
446
|
-
onNext = () => {
|
|
447
|
-
updateModalBody(buildModalBody(nextFile.id));
|
|
448
|
-
};
|
|
449
|
-
url = currentFile.imageUrl;
|
|
450
|
-
isPdf = url?.match(/\.pdf$/);
|
|
451
|
-
break;
|
|
452
|
-
}
|
|
453
|
-
case ATTACHMENTS_VIEW_MODES__LIST: {
|
|
454
|
-
const
|
|
455
|
-
currentFile = Repository.getById(id),
|
|
456
|
-
currentIx = Repository.getIxById(id),
|
|
457
|
-
prevFile = Repository.getByIx(currentIx - 1),
|
|
458
|
-
nextFile = Repository.getByIx(currentIx + 1);
|
|
459
|
-
isPrevDisabled = !prevFile;
|
|
460
|
-
isNextDisabled = !nextFile;
|
|
461
|
-
onPrev = () => {
|
|
462
|
-
updateModalBody(buildModalBody(prevFile.id));
|
|
463
|
-
};
|
|
464
|
-
onNext = () => {
|
|
465
|
-
updateModalBody(buildModalBody(nextFile.id));
|
|
466
|
-
};
|
|
467
|
-
url = currentFile.attachments__uri;
|
|
468
|
-
isPdf = currentFile.attachments__mimetype === 'application/pdf';
|
|
469
|
-
}
|
|
470
|
-
}
|
|
414
|
+
const
|
|
415
|
+
currentFile = Attachments.getById(id),
|
|
416
|
+
currentIx = Attachments.getIxById(id),
|
|
417
|
+
prevFile = Attachments.getByIx(currentIx - 1),
|
|
418
|
+
nextFile = Attachments.getByIx(currentIx + 1),
|
|
419
|
+
isPrevDisabled = !prevFile,
|
|
420
|
+
isNextDisabled = !nextFile,
|
|
421
|
+
onPrev = () => {
|
|
422
|
+
updateModalBody(buildModalBody(prevFile.id));
|
|
423
|
+
},
|
|
424
|
+
onNext = () => {
|
|
425
|
+
updateModalBody(buildModalBody(nextFile.id));
|
|
426
|
+
},
|
|
427
|
+
url = currentFile.attachments__uri,
|
|
428
|
+
isPdf = currentFile.attachments__mimetype === 'application/pdf';
|
|
429
|
+
let body = null;
|
|
471
430
|
if (isPdf) {
|
|
472
431
|
body = <iframe
|
|
473
432
|
src={url}
|
|
@@ -555,9 +514,54 @@ function AttachmentsElement(props) {
|
|
|
555
514
|
});
|
|
556
515
|
},
|
|
557
516
|
onDeleteDirectory = async () => {
|
|
558
|
-
|
|
517
|
+
|
|
518
|
+
const
|
|
519
|
+
attachmentDirectory = getTreeSelection()[0],
|
|
520
|
+
isRoot = attachmentDirectory.isRoot;
|
|
521
|
+
if (isRoot) {
|
|
522
|
+
alert('Cannot delete the root directory.');
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
// check if there are any attachments in this directory or its subdirectories
|
|
528
|
+
const
|
|
529
|
+
url = AttachmentDirectories.api.baseURL + 'AttachmentDirectories/hasAttachments',
|
|
530
|
+
data = {
|
|
531
|
+
attachment_directory_id: treeSelection[0].id,
|
|
532
|
+
},
|
|
533
|
+
result = await AttachmentDirectories._send('POST', url, data);
|
|
534
|
+
|
|
535
|
+
const {
|
|
536
|
+
root,
|
|
537
|
+
success,
|
|
538
|
+
total,
|
|
539
|
+
message
|
|
540
|
+
} = AttachmentDirectories._processServerResponse(result);
|
|
541
|
+
|
|
542
|
+
if (!success) {
|
|
543
|
+
alert(message);
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
if (root.hasAttachments) {
|
|
548
|
+
alert('Cannot delete a directory that contains attachments somewhere down its hierarchy. Please move or delete the attachments first.');
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
// transfer selection to the parent node
|
|
554
|
+
const
|
|
555
|
+
parentNode = attachmentDirectory.getParent(),
|
|
556
|
+
newSelection = [parentNode];
|
|
557
|
+
setTreeSelection(newSelection);
|
|
558
|
+
self.children.tree.setSelection(newSelection);
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
// now delete it
|
|
559
562
|
await attachmentDirectory.delete();
|
|
560
563
|
self.children.tree.buildAndSetTreeNodeData();
|
|
564
|
+
|
|
561
565
|
},
|
|
562
566
|
onRenameDirectory = () => {
|
|
563
567
|
const attachmentDirectory = getTreeSelection()[0];
|
|
@@ -606,6 +610,14 @@ function AttachmentsElement(props) {
|
|
|
606
610
|
}}
|
|
607
611
|
/>,
|
|
608
612
|
});
|
|
613
|
+
},
|
|
614
|
+
onReloadDirectories = async () => {
|
|
615
|
+
await AttachmentDirectories.loadRootNodes(2);
|
|
616
|
+
const rootNodes = AttachmentDirectories.getRootNodes();
|
|
617
|
+
if (rootNodes) {
|
|
618
|
+
setTreeSelection(rootNodes);
|
|
619
|
+
self.children.tree.setSelection(rootNodes);
|
|
620
|
+
}
|
|
609
621
|
};
|
|
610
622
|
|
|
611
623
|
if (!_.isEqual(modelidCalc, modelid.current)) {
|
|
@@ -624,9 +636,9 @@ function AttachmentsElement(props) {
|
|
|
624
636
|
setDirectoriesTrue = () => setIsDirectoriesLoading(true),
|
|
625
637
|
setDirectoriesFalse = () => setIsDirectoriesLoading(false);
|
|
626
638
|
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
639
|
+
Attachments.on('beforeLoad', setTrue);
|
|
640
|
+
Attachments.on('load', setFalse);
|
|
641
|
+
Attachments.on('load', buildFiles);
|
|
630
642
|
if (usesDirectories) {
|
|
631
643
|
AttachmentDirectories.on('beforeLoad', setDirectoriesTrue);
|
|
632
644
|
AttachmentDirectories.on('loadRootNodes', setDirectoriesFalse);
|
|
@@ -636,12 +648,12 @@ function AttachmentsElement(props) {
|
|
|
636
648
|
|
|
637
649
|
if (modelid.current && !_.isArray(modelid.current)) {
|
|
638
650
|
const
|
|
639
|
-
currentConditions =
|
|
651
|
+
currentConditions = Attachments.getParamConditions() || {},
|
|
640
652
|
newConditions = {
|
|
641
653
|
'conditions[Attachments.model]': model,
|
|
642
654
|
'conditions[Attachments.modelid]': modelid.current,
|
|
643
655
|
},
|
|
644
|
-
currentPageSize =
|
|
656
|
+
currentPageSize = Attachments.pageSize,
|
|
645
657
|
newPageSize = showAll ? expandedMax : collapsedMax;
|
|
646
658
|
|
|
647
659
|
// figure out conditions
|
|
@@ -666,34 +678,34 @@ function AttachmentsElement(props) {
|
|
|
666
678
|
}
|
|
667
679
|
let doReload = false;
|
|
668
680
|
if (!_.isEqual(currentConditions, newConditions)) {
|
|
669
|
-
|
|
681
|
+
Attachments.setParams(newConditions);
|
|
670
682
|
doReload = true;
|
|
671
683
|
}
|
|
672
684
|
|
|
673
685
|
// figure out pageSize
|
|
674
686
|
if (!_.isEqual(currentPageSize, newPageSize)) {
|
|
675
|
-
|
|
687
|
+
Attachments.setPageSize(newPageSize);
|
|
676
688
|
doReload = true;
|
|
677
689
|
}
|
|
678
690
|
if (doReload) {
|
|
679
|
-
await
|
|
691
|
+
await Attachments.load();
|
|
680
692
|
}
|
|
681
693
|
if (usesDirectories) {
|
|
682
694
|
const
|
|
683
695
|
wasAlreadyLoaded = AttachmentDirectories.areRootNodesLoaded,
|
|
684
|
-
currentConditions = AttachmentDirectories.
|
|
696
|
+
currentConditions = AttachmentDirectories.getParamConditions() || {},
|
|
685
697
|
newConditions = {
|
|
686
698
|
'conditions[AttachmentDirectories.model]': selectorSelected.repository.name,
|
|
687
699
|
'conditions[AttachmentDirectories.modelid]': selectorSelected[selectorSelectedField],
|
|
688
700
|
};
|
|
689
701
|
let doReload = false;
|
|
690
702
|
if (!_.isEqual(currentConditions, newConditions)) {
|
|
691
|
-
AttachmentDirectories.
|
|
703
|
+
AttachmentDirectories.setParams(newConditions);
|
|
692
704
|
doReload = true;
|
|
693
705
|
}
|
|
694
706
|
if (doReload) {
|
|
695
707
|
// setTreeSelection([]); // clear it; otherwise we get stale nodes after reloading AttachmentDirectories
|
|
696
|
-
await AttachmentDirectories.
|
|
708
|
+
await AttachmentDirectories.loadRootNodes(2);
|
|
697
709
|
if (wasAlreadyLoaded) {
|
|
698
710
|
const rootNodes = AttachmentDirectories.getRootNodes();
|
|
699
711
|
if (rootNodes) {
|
|
@@ -705,7 +717,7 @@ function AttachmentsElement(props) {
|
|
|
705
717
|
|
|
706
718
|
buildFiles();
|
|
707
719
|
} else {
|
|
708
|
-
|
|
720
|
+
Attachments.clear();
|
|
709
721
|
if (usesDirectories) {
|
|
710
722
|
AttachmentDirectories.clear();
|
|
711
723
|
}
|
|
@@ -728,9 +740,9 @@ function AttachmentsElement(props) {
|
|
|
728
740
|
})();
|
|
729
741
|
|
|
730
742
|
return () => {
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
743
|
+
Attachments.off('beforeLoad', setTrue);
|
|
744
|
+
Attachments.off('load', setFalse);
|
|
745
|
+
Attachments.off('load', buildFiles);
|
|
734
746
|
if (usesDirectories) {
|
|
735
747
|
AttachmentDirectories.off('beforeLoad', setDirectoriesTrue);
|
|
736
748
|
AttachmentDirectories.off('loadRootNodes', setDirectoriesFalse);
|
|
@@ -754,7 +766,7 @@ function AttachmentsElement(props) {
|
|
|
754
766
|
const files = getFiles();
|
|
755
767
|
let content = null;
|
|
756
768
|
// icon or list view
|
|
757
|
-
if (viewMode === ATTACHMENTS_VIEW_MODES__ICON) {
|
|
769
|
+
if (viewMode === ATTACHMENTS_VIEW_MODES__ICON || isUploading) {
|
|
758
770
|
content = <VStack
|
|
759
771
|
className={clsx(
|
|
760
772
|
'AttachmentsElement-icon-VStack1',
|
|
@@ -771,13 +783,14 @@ function AttachmentsElement(props) {
|
|
|
771
783
|
<HStack
|
|
772
784
|
className={clsx(
|
|
773
785
|
'AttachmentsElement-HStack',
|
|
774
|
-
'
|
|
775
|
-
'flex-1',
|
|
786
|
+
'gap-2',
|
|
776
787
|
'flex-wrap',
|
|
788
|
+
'items-start',
|
|
777
789
|
files.length === 0 ? [
|
|
778
790
|
// So the 'No files' text is centered
|
|
779
791
|
'justify-center',
|
|
780
792
|
'items-center',
|
|
793
|
+
'h-full',
|
|
781
794
|
] : null,
|
|
782
795
|
)}
|
|
783
796
|
>
|
|
@@ -786,28 +799,30 @@ function AttachmentsElement(props) {
|
|
|
786
799
|
let eyeProps = {};
|
|
787
800
|
if (file.type && (file.type.match(/^image\//) || file.type === 'application/pdf')) {
|
|
788
801
|
eyeProps = {
|
|
789
|
-
onSee:
|
|
802
|
+
onSee: () => {
|
|
803
|
+
onViewLightbox(file.id);
|
|
804
|
+
},
|
|
790
805
|
};
|
|
791
806
|
}
|
|
792
807
|
|
|
793
808
|
// Create drag source item for this file
|
|
794
|
-
const
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
809
|
+
const
|
|
810
|
+
fileEntity = Attachments.getById(file.id),
|
|
811
|
+
dragSourceItem = {
|
|
812
|
+
item: fileEntity, // Get the actual entity
|
|
813
|
+
sourceComponentRef: null, // Could be set to a ref if needed
|
|
814
|
+
getDragProxy: () => {
|
|
815
|
+
// Custom drag preview for file items
|
|
816
|
+
return <VStack className="bg-white border border-gray-300 rounded-lg p-3 shadow-lg max-w-[200px]">
|
|
817
|
+
<Text className="font-semibold text-gray-800">{file.name}</Text>
|
|
818
|
+
<Text className="text-sm text-gray-600">File</Text>
|
|
819
|
+
</VStack>;
|
|
820
|
+
}
|
|
821
|
+
};
|
|
807
822
|
|
|
808
823
|
return <Box
|
|
809
824
|
key={file.id}
|
|
810
|
-
className="mr-2"
|
|
825
|
+
className="BoxHERE mr-2"
|
|
811
826
|
>
|
|
812
827
|
{useFileMosaic &&
|
|
813
828
|
<DraggableFileMosaic
|
|
@@ -835,7 +850,7 @@ function AttachmentsElement(props) {
|
|
|
835
850
|
isDragSource={canCrud && usesDirectories}
|
|
836
851
|
dragSourceType="Attachments"
|
|
837
852
|
dragSourceItem={dragSourceItem}
|
|
838
|
-
item={
|
|
853
|
+
item={Attachments.getById(file.id)}
|
|
839
854
|
onDragStart={() => {
|
|
840
855
|
setTimeout(() => setIsDragging(true), 50); // Delay to avoid interfering with drag initialization
|
|
841
856
|
}}
|
|
@@ -846,11 +861,11 @@ function AttachmentsElement(props) {
|
|
|
846
861
|
</Box>;
|
|
847
862
|
})}
|
|
848
863
|
</HStack>
|
|
849
|
-
{
|
|
864
|
+
{Attachments.total <= collapsedMax ? null :
|
|
850
865
|
<Button
|
|
851
866
|
onPress={toggleShowAll}
|
|
852
867
|
className="AttachmentsElement-toggleShowAll mt-2"
|
|
853
|
-
text={'Show ' + (showAll ? ' Less' : ' All ' +
|
|
868
|
+
text={'Show ' + (showAll ? ' Less' : ' All ' + Attachments.total)}
|
|
854
869
|
_text={{
|
|
855
870
|
className: `
|
|
856
871
|
text-grey-600
|
|
@@ -864,7 +879,7 @@ function AttachmentsElement(props) {
|
|
|
864
879
|
</VStack>;
|
|
865
880
|
} else if (viewMode === ATTACHMENTS_VIEW_MODES__LIST) {
|
|
866
881
|
content = <AttachmentsGridEditor
|
|
867
|
-
Repository={
|
|
882
|
+
Repository={Attachments}
|
|
868
883
|
selectionMode={SELECTION_MODE_MULTI}
|
|
869
884
|
showSelectHandle={false}
|
|
870
885
|
disableAdd={true}
|
|
@@ -884,7 +899,7 @@ function AttachmentsElement(props) {
|
|
|
884
899
|
{
|
|
885
900
|
id: 'view',
|
|
886
901
|
header: 'View',
|
|
887
|
-
w:
|
|
902
|
+
w: 60,
|
|
888
903
|
isSortable: false,
|
|
889
904
|
isEditable: false,
|
|
890
905
|
isReorderable: false,
|
|
@@ -892,7 +907,7 @@ function AttachmentsElement(props) {
|
|
|
892
907
|
isHidable: false,
|
|
893
908
|
renderer: (item) => {
|
|
894
909
|
return <IconButton
|
|
895
|
-
className="w-[
|
|
910
|
+
className="w-[60px]"
|
|
896
911
|
icon={Eye}
|
|
897
912
|
_icon={{
|
|
898
913
|
size: 'xl',
|
|
@@ -902,6 +917,27 @@ function AttachmentsElement(props) {
|
|
|
902
917
|
/>;
|
|
903
918
|
},
|
|
904
919
|
},
|
|
920
|
+
{
|
|
921
|
+
id: 'download',
|
|
922
|
+
header: 'Get',
|
|
923
|
+
w: 60,
|
|
924
|
+
isSortable: false,
|
|
925
|
+
isEditable: false,
|
|
926
|
+
isReorderable: false,
|
|
927
|
+
isResizable: false,
|
|
928
|
+
isHidable: false,
|
|
929
|
+
renderer: (item) => {
|
|
930
|
+
return <IconButton
|
|
931
|
+
className="w-[60px]"
|
|
932
|
+
icon={Download}
|
|
933
|
+
_icon={{
|
|
934
|
+
size: 'xl',
|
|
935
|
+
}}
|
|
936
|
+
onPress={() => onDownload(item.id)}
|
|
937
|
+
tooltip="Download"
|
|
938
|
+
/>;
|
|
939
|
+
},
|
|
940
|
+
},
|
|
905
941
|
{
|
|
906
942
|
"id": "attachments__filename",
|
|
907
943
|
"header": "Filename",
|
|
@@ -910,7 +946,7 @@ function AttachmentsElement(props) {
|
|
|
910
946
|
"isEditable": true,
|
|
911
947
|
"isReorderable": true,
|
|
912
948
|
"isResizable": true,
|
|
913
|
-
"w":
|
|
949
|
+
"w": 250
|
|
914
950
|
},
|
|
915
951
|
{
|
|
916
952
|
"id": "attachments__size_formatted",
|
|
@@ -920,7 +956,7 @@ function AttachmentsElement(props) {
|
|
|
920
956
|
"isEditable": false,
|
|
921
957
|
"isReorderable": true,
|
|
922
958
|
"isResizable": true,
|
|
923
|
-
"w":
|
|
959
|
+
"w": 100
|
|
924
960
|
},
|
|
925
961
|
]}
|
|
926
962
|
areRowsDragSource={canCrud}
|
|
@@ -997,9 +1033,9 @@ function AttachmentsElement(props) {
|
|
|
997
1033
|
maxFileSize={styles.ATTACHMENTS_MAX_FILESIZE}
|
|
998
1034
|
autoClean={true}
|
|
999
1035
|
uploadConfig={{
|
|
1000
|
-
url:
|
|
1036
|
+
url: Attachments.api.baseURL + Attachments.schema.name + '/uploadAttachment',
|
|
1001
1037
|
method: 'POST',
|
|
1002
|
-
headers:
|
|
1038
|
+
headers: Attachments.headers,
|
|
1003
1039
|
autoUpload,
|
|
1004
1040
|
}}
|
|
1005
1041
|
headerConfig={{
|
|
@@ -1122,12 +1158,18 @@ function AttachmentsElement(props) {
|
|
|
1122
1158
|
isDisabled: !treeSelection.length, // disabled if no selection
|
|
1123
1159
|
},
|
|
1124
1160
|
{
|
|
1125
|
-
key: '
|
|
1161
|
+
key: 'Trash',
|
|
1126
1162
|
text: 'Delete Directory',
|
|
1127
1163
|
handler: onDeleteDirectory,
|
|
1128
|
-
icon:
|
|
1164
|
+
icon: Trash,
|
|
1129
1165
|
isDisabled: !treeSelection.length || !treeSelection[0].parentId, // disabled if selection is root or none
|
|
1130
1166
|
},
|
|
1167
|
+
{
|
|
1168
|
+
key: 'Reload',
|
|
1169
|
+
text: 'Reload Directories',
|
|
1170
|
+
handler: onReloadDirectories,
|
|
1171
|
+
icon: Rotate,
|
|
1172
|
+
},
|
|
1131
1173
|
] : [],
|
|
1132
1174
|
}}
|
|
1133
1175
|
/>
|
|
@@ -1158,13 +1200,27 @@ function withAdditionalProps(WrappedComponent) {
|
|
|
1158
1200
|
const {
|
|
1159
1201
|
usesDirectories = false,
|
|
1160
1202
|
} = props,
|
|
1161
|
-
|
|
1203
|
+
[isReady, setIsReady] = useState(false),
|
|
1204
|
+
[AttachmentDirectories] = useState(() => (usesDirectories ? oneHatData.getRepository('AttachmentDirectories', true) : null)), // lazy instantiator, so getRepository is called only once (it's unique, so otherwise, every time this renders, we'd get a new Repository!)
|
|
1205
|
+
[Attachments] = useState(() => oneHatData.getRepository('Attachments', true)); // same
|
|
1162
1206
|
|
|
1207
|
+
useEffect(() => {
|
|
1208
|
+
(async () => {
|
|
1209
|
+
Attachments.setBaseParams(props.baseParams || {}); // have to add the baseParams here, because we're bypassing withData
|
|
1210
|
+
if (!isReady) {
|
|
1211
|
+
setIsReady(true);
|
|
1212
|
+
}
|
|
1213
|
+
})();
|
|
1214
|
+
}, []);
|
|
1215
|
+
|
|
1216
|
+
if (!isReady) {
|
|
1217
|
+
return null;
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1163
1220
|
return <WrappedComponent
|
|
1164
|
-
model="Attachments"
|
|
1165
|
-
uniqueRepository={true}
|
|
1166
1221
|
reference="attachments"
|
|
1167
1222
|
{...props}
|
|
1223
|
+
Repository={Attachments}
|
|
1168
1224
|
AttachmentDirectories={AttachmentDirectories}
|
|
1169
1225
|
/>;
|
|
1170
1226
|
};
|