diff --git a/frontend/src/components/bucket/BucketConfigForm.vue b/frontend/src/components/bucket/BucketConfigForm.vue index d368e3de..3b66f5e4 100644 --- a/frontend/src/components/bucket/BucketConfigForm.vue +++ b/frontend/src/components/bucket/BucketConfigForm.vue @@ -78,10 +78,13 @@ const onSubmit = async (values: any) => { const bucketChanges = differential(formBucket, initialValues); - props.bucket + const bucketModel = props.bucket ? await bucketStore.updateBucket(props.bucket?.bucketId, bucketChanges) : await bucketStore.createBucket(formBucket); + // if successfully added a new configuration, do a recursive sync of this bucket + if(!props.bucket) await bucketStore.syncBucket(bucketModel.bucketId, true); + // refresh bucket list await bucketStore.fetchBuckets({ userId: getUserId.value, objectPerms: true }); // trim trailing "//", if present diff --git a/frontend/src/components/bucket/BucketTable.vue b/frontend/src/components/bucket/BucketTable.vue index 57282822..a292b950 100644 --- a/frontend/src/components/bucket/BucketTable.vue +++ b/frontend/src/components/bucket/BucketTable.vue @@ -69,19 +69,19 @@ const confirmDeleteBucket = (bucketId: string) => { confirm.require({ message: 'Are you sure you want to delete this folder in BCBox? \ - This will drop all related objects and permissions from BCBox, \ + This will drop all sub-folders and related objects and permissions from BCBox, \ but the files will still remain in the actual source storage location.', header: 'Delete folder', acceptLabel: 'Confirm', rejectLabel: 'Cancel', - accept: () => deleteBucket(bucketId), + accept: () => deleteBucket(bucketId, true), onHide: () => onDialogHide(), reject: () => onDialogHide() }); }; -async function deleteBucket(bucketId: string) { - await bucketStore.deleteBucket(bucketId); +async function deleteBucket(bucketId: string, recursive=true) { + await bucketStore.deleteBucket(bucketId, recursive); await bucketStore.fetchBuckets({ userId: getUserId.value, objectPerms: true }); } @@ -240,8 +240,7 @@ watch(getBuckets, () => { } } - // Expand all nodes and set tree state - bucketTreeNodeMap.forEach((_v, k) => (expandedKeys.value[k] = true)); + //set tree state treeData.value = tree; }); diff --git a/frontend/src/components/common/SyncButton.vue b/frontend/src/components/common/SyncButton.vue index a3597731..953410a1 100644 --- a/frontend/src/components/common/SyncButton.vue +++ b/frontend/src/components/common/SyncButton.vue @@ -41,7 +41,7 @@ const onSubmit = () => { if (props.objectId) { objectStore.syncObject(props.objectId); } else if (props.bucketId) { - bucketStore.syncBucket(props.bucketId); + bucketStore.syncBucket(props.bucketId, false); } else { toast.error('', 'Unable to synchronize'); } diff --git a/frontend/src/components/object/ObjectVersion.vue b/frontend/src/components/object/ObjectVersion.vue index dfceb7b9..f1886edb 100644 --- a/frontend/src/components/object/ObjectVersion.vue +++ b/frontend/src/components/object/ObjectVersion.vue @@ -47,12 +47,14 @@ const isDeleted: Ref = computed(() => getIsDeleted.value(props.objectId const tableData: Ref> = computed(() => { return versions.value .filter(v => !v.deleteMarker) + .sort((a, b) => { + return new Date(a.lastModifiedDate) < new Date(b.lastModifiedDate) ? 1 : -1; + }) .map((v: Version, index, arr) => ({ ...v, createdByName: getUser.value(v.createdBy)?.fullName, versionNumber: arr.length - index, isDeleted: isDeleted.value, - })); }); // Highlight row for currently selected version diff --git a/frontend/src/services/bucketService.ts b/frontend/src/services/bucketService.ts index 6ae6f723..f4c784e0 100644 --- a/frontend/src/services/bucketService.ts +++ b/frontend/src/services/bucketService.ts @@ -39,13 +39,17 @@ export default { /** * @function deleteBucket - * Deletes a bucket - * This is a COMS DB delete only. The S3 bucket remains intact + * Deletes a bucket and optionally sub-folders + * This is a COMS DB delete only. The S3 bucket(s) remains intact * @param {string} bucketId Bucket ID for the bucket to delete * @returns {Promise} An axios response */ - deleteBucket(bucketId: string) { - return comsAxios().delete(`${BUCKET_PATH}/${bucketId}`); + deleteBucket(bucketId: string, recursive: boolean ) { + return comsAxios().delete(`${BUCKET_PATH}/${bucketId}`, { + params: { + recursive: recursive, + } + }); }, /** @@ -64,7 +68,11 @@ export default { * @param {string} bucketId Bucket ID for the bucket to synchronize * @returns {Promise} An axios response */ - syncBucket(bucketId: string) { - return comsAxios().get(`${BUCKET_PATH}/${bucketId}/sync`); + syncBucket(bucketId: string, recursive: boolean ) { + return comsAxios().get(`${BUCKET_PATH}/${bucketId}/sync`, { + params: { + recursive: recursive, + } + }); } }; diff --git a/frontend/src/store/bucketStore.ts b/frontend/src/store/bucketStore.ts index a29db228..d65f5d01 100644 --- a/frontend/src/store/bucketStore.ts +++ b/frontend/src/store/bucketStore.ts @@ -51,11 +51,11 @@ export const useBucketStore = defineStore('bucket', () => { } } - async function deleteBucket(bucketId: string) { + async function deleteBucket(bucketId: string, recursive: boolean){ try { appStore.beginIndeterminateLoading(); - await bucketService.deleteBucket(bucketId); + await bucketService.deleteBucket(bucketId, recursive ); } finally { appStore.endIndeterminateLoading(); } @@ -112,11 +112,11 @@ export const useBucketStore = defineStore('bucket', () => { } } - async function syncBucket(bucketId: string) { + async function syncBucket(bucketId: string, recursive: boolean) { try { appStore.beginIndeterminateLoading(); - await bucketService.syncBucket(bucketId); + await bucketService.syncBucket(bucketId, recursive ); toast.success('', 'Sync is in queue and will begin soon'); } catch (error: any) { toast.error('Unable to sync', error); diff --git a/frontend/src/types/Version.ts b/frontend/src/types/Version.ts index 0194a366..0c5d8bc7 100644 --- a/frontend/src/types/Version.ts +++ b/frontend/src/types/Version.ts @@ -8,4 +8,5 @@ export type Version = { mimeType: string; objectId: string; s3VersionId: string; + lastModifiedDate: string; } & IAudit; diff --git a/frontend/tests/unit/store/versionStore.spec.ts b/frontend/tests/unit/store/versionStore.spec.ts index 1004b8b2..4dbaaf23 100644 --- a/frontend/tests/unit/store/versionStore.spec.ts +++ b/frontend/tests/unit/store/versionStore.spec.ts @@ -31,7 +31,8 @@ const version: Version = { objectId: '000', s3VersionId: 's3123', isLatest: true, - createdAt: '2023-05-01T22:18:12.553Z' + createdAt: '2023-05-01T22:18:12.553Z', + lastModifiedDate: '2023-05-01T22:18:12.553Z', }; const versionOld: Version = { @@ -41,7 +42,8 @@ const versionOld: Version = { objectId: '000', s3VersionId: 's2000', isLatest: false, - createdAt: '2022-05-01T18:25:42.462Z' + createdAt: '2022-05-01T18:25:42.462Z', + lastModifiedDate: '2023-05-01T22:18:12.553Z', }; const mockToast = vi.fn();