diff --git a/frontend/src/assets/main.scss b/frontend/src/assets/main.scss index 797ef5bb..235fa359 100644 --- a/frontend/src/assets/main.scss +++ b/frontend/src/assets/main.scss @@ -138,7 +138,7 @@ div:focus-visible { /* footer */ .gov-footer { - background-color: #003366 !important; + background-color: #003366; border-top: 2px solid #fcba19; padding-bottom: 3px; a { diff --git a/frontend/src/components/layout/Navbar.vue b/frontend/src/components/layout/Navbar.vue index 4b410d53..3582dcff 100644 --- a/frontend/src/components/layout/Navbar.vue +++ b/frontend/src/components/layout/Navbar.vue @@ -28,6 +28,17 @@ const { getIsAuthenticated } = storeToRefs(useAuthStore()); My Files +
  • + + Recycle Bin + +
  • { return props.hard ? (props.versionId ? 'Permanently delete version' : (props.ids.length > 1 ? - 'Permanently delete these files' : 'Permanently delete file')) : + 'Permanently delete selected files' : 'Permanently delete file')) : (props.versionId ? 'Delete version' : 'Delete file' ); }); diff --git a/frontend/src/components/object/ObjectFileDetails.vue b/frontend/src/components/object/ObjectFileDetails.vue index 498c2db4..0816553e 100644 --- a/frontend/src/components/object/ObjectFileDetails.vue +++ b/frontend/src/components/object/ObjectFileDetails.vue @@ -51,7 +51,12 @@ const versionStore = useVersionStore(); const { getUserId } = storeToRefs(useAuthStore()); const { getObject } = storeToRefs(objectStore); -const { getIsDeleted, getLatestVersionIdByObjectId, getVersionsByObjectId } = storeToRefs(versionStore); +const { + getIsDeleted, + getLatestVersionIdByObjectId, + getLatestNonDmVersionIdByObjectId, + getVersionsByObjectId +} = storeToRefs(versionStore); // State const object: Ref = ref(undefined); @@ -61,13 +66,14 @@ const permissionsVisible: Ref = ref(false); // version stuff const currentVersionId: Ref = ref(props.versionId); const latestVersionId = computed(() => getLatestVersionIdByObjectId.value(props.objectId)); +const allVersions = computed(() => getVersionsByObjectId.value(props.objectId)); +const latestNonDmVersionId = computed(() => getLatestNonDmVersionIdByObjectId.value(props.objectId)); + const isDeleted: Ref = computed(() => getIsDeleted.value(props.objectId)); async function onVersionsChanged(changedVersionId: string | undefined, isVersion: boolean, hardDelete: boolean) { - // if doing hard delete or no versions left, redirect to object list - const otherVersions = getVersionsByObjectId.value(props.objectId) - .filter(v=>v.id !== changedVersionId); - + // if doing hard delete or no versions left, redirect to parent folder + const otherVersions = allVersions.value.filter(v=>v.id !== changedVersionId); if (hardDelete || (isVersion && otherVersions.length === 0)) { router.push({ path: '/list/objects', query: { bucketId: bucketId.value }}); } @@ -78,7 +84,7 @@ async function onVersionsChanged(changedVersionId: string | undefined, isVersion metadataStore.fetchMetadata({ objectId: props.objectId }), tagStore.fetchTagging({ objectId: props.objectId }) ]).then(async () => { - currentVersionId.value = latestVersionId.value; + currentVersionId.value = latestNonDmVersionId.value; await Promise.all([ versionStore.fetchMetadata({ objectId: props.objectId }), versionStore.fetchTagging({ objectId: props.objectId }) diff --git a/frontend/src/components/object/ObjectList.vue b/frontend/src/components/object/ObjectList.vue index 6a5b3a5c..a79ab9af 100644 --- a/frontend/src/components/object/ObjectList.vue +++ b/frontend/src/components/object/ObjectList.vue @@ -11,7 +11,7 @@ import { } from '@/components/object'; import { Button } from '@/lib/primevue'; import { useAuthStore, useObjectStore, useNavStore, usePermissionStore } from '@/store'; -import { Permissions, RouteNames } from '@/utils/constants'; +import { Permissions } from '@/utils/constants'; import { ButtonMode } from '@/utils/enums'; import { onDialogHide } from '@/utils/utils'; @@ -131,9 +131,6 @@ const onDeletedSuccess = () => { /> - - Recycle Bin - diff --git a/frontend/src/components/object/ObjectListDeleted.vue b/frontend/src/components/object/ObjectListDeleted.vue index 08d99dd8..ad601163 100644 --- a/frontend/src/components/object/ObjectListDeleted.vue +++ b/frontend/src/components/object/ObjectListDeleted.vue @@ -6,22 +6,13 @@ import { DeleteObjectButton, ObjectSidebar, ObjectTableDeleted, + RestoreObjectButton } from '@/components/object'; import { useObjectStore } from '@/store'; -import { RouteNames } from '@/utils/constants'; import { ButtonMode } from '@/utils/enums'; import type { Ref } from 'vue'; -// Props -type Props = { - bucketId?: string; -}; - -const props = withDefaults(defineProps(), { - bucketId: undefined -}); - //const navStore = useNavStore(); const objectStore = useObjectStore(); @@ -46,11 +37,22 @@ const closeObjectInfo = () => { const onDeletedSuccess = () => { objectTableKey.value += 1; }; + +const onRestoredSuccess = () => { + objectTableKey.value += 1; +}; diff --git a/frontend/src/components/object/ObjectTableDeleted.vue b/frontend/src/components/object/ObjectTableDeleted.vue index 0def8fd0..1a81249d 100644 --- a/frontend/src/components/object/ObjectTableDeleted.vue +++ b/frontend/src/components/object/ObjectTableDeleted.vue @@ -6,10 +6,11 @@ import { Spinner } from '@/components/layout'; import { DeleteObjectButton, ObjectPermission, + RestoreObjectButton } from '@/components/object'; import { SyncButton } from '@/components/common'; import { Button, Column, DataTable, Dialog, InputText, useToast } from '@/lib/primevue'; -import { useAuthStore, useObjectStore, useNavStore, usePermissionStore } from '@/store'; +import { useAuthStore, useBucketStore, useObjectStore, useNavStore, usePermissionStore } from '@/store'; import { Permissions, RouteNames } from '@/utils/constants'; import { onDialogHide } from '@/utils/utils'; import { ButtonMode } from '@/utils/enums'; @@ -30,23 +31,15 @@ type DataTableObjectSource = { type DataTableFilter = { [key: string]: { value: any; matchMode: string }; }; -// Props -type Props = { - bucketId?: string; - objectInfoId?: string; -}; - -const props = withDefaults(defineProps(), { - bucketId: undefined, - objectInfoId: undefined -}); // Emits const emit = defineEmits(['show-object-info']); // Store +const bucketStore = useBucketStore(); const objectStore = useObjectStore(); const permissionStore = usePermissionStore(); +const { getBuckets } = storeToRefs(useBucketStore()); const { getUserId } = storeToRefs(useAuthStore()); const { focusedElement } = storeToRefs(useNavStore()); @@ -67,7 +60,11 @@ const filters: Ref = ref({ // Actions const toast = useToast(); const onDeletedSuccess = () => { - toast.success('File deleted'); + toast.success('File permanently deleted'); + loadLazyData(); +}; +const onRestoredSuccess = () => { + toast.success('File restored'); loadLazyData(); }; @@ -85,8 +82,10 @@ async function showPermissions(objectId: string) { focusedElement.value = document.activeElement; } -onMounted(() => { +onMounted( async () => { loading.value = true; + await bucketStore.fetchBuckets({ userId: getUserId.value, objectPerms: true }); + lazyParams.value = { first: 0, rows: lazyDataTable.value.rows, @@ -103,7 +102,6 @@ const loadLazyData = (event?: any) => { objectService .searchObjects( { - bucketId: props.bucketId ? [props.bucketId] : undefined, deleteMarker: true, latest: true, page: lazyParams.value?.page ? ++lazyParams.value.page : 1, @@ -114,10 +112,16 @@ const loadLazyData = (event?: any) => { } ) .then((r: any) => { - tableData.value = r.data.map((item: any) => ({ - ...item, - updatedAt: item.updatedAt === null ? item.createdAt : item.updatedAt - })); + // add full object url to table data + tableData.value = r.data.map((o: COMSObject) => { + const bucket = getBuckets.value.find((b) => b.bucketId === o.bucketId); + return { + ...o, + location: `${bucket?.endpoint}/${bucket?.bucket}/${o.path}`, + updatedAt: o.updatedAt === null ? o.createdAt : o.updatedAt + }; + }); + totalRecords.value = +r?.headers['x-total-rows']; // add objects to store objectStore.setObjects(r.data); @@ -221,7 +225,7 @@ onUnmounted(() => { v-if="!loading" class="flex justify-content-center" > -

    There are no deleted files in this folder

    +

    Nothing to see here

    - +