Skip to content

Commit

Permalink
Merge pull request #177 from bcgov/computed
Browse files Browse the repository at this point in the history
Refactor File Details page
  • Loading branch information
jujaga authored Mar 12, 2024
2 parents 6ace7fe + 4eefcb4 commit b7749a4
Show file tree
Hide file tree
Showing 30 changed files with 273 additions and 476 deletions.
2 changes: 1 addition & 1 deletion frontend/src/components/bucket/BucketList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const bucketToUpdate: Ref<Bucket | undefined> = ref(undefined);
// Actions
const showSidebarInfo = async (bucketId: string) => {
sidebarInfo.value = bucketStore.findBucketById(bucketId);
sidebarInfo.value = bucketStore.getBucket(bucketId);
};
const closeSidebarInfo = () => {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/bucket/BucketSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ async function load() {
if (uniqueIds.length) {
await userStore.fetchUsers({ userId: uniqueIds });
managedBy.value = userStore
.findUsersById(uniqueIds)
.getUsers(uniqueIds)
.map((x) => x.fullName)
.join(', ');
}
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/components/common/SyncButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type Props = {
const props = withDefaults(defineProps<Props>(), {
bucketId: '',
objectId: '',
labelText:''
labelText: ''
});
// State
Expand Down Expand Up @@ -47,9 +47,9 @@ const onSubmit = () => {
const onClick = () => {
displaySyncDialog.value = true;
if (props.bucketId) {
name.value = bucketStore.findBucketById(props.bucketId)?.bucketName ?? '';
name.value = bucketStore.getBucket(props.bucketId)?.bucketName ?? '';
} else if (props.objectId) {
name.value = objectStore.findObjectById(props.objectId)?.name ?? '';
name.value = objectStore.getObject(props.objectId)?.name ?? '';
}
};
</script>
Expand Down
22 changes: 7 additions & 15 deletions frontend/src/components/object/ObjectAccess.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<script setup lang="ts">
import { storeToRefs } from 'pinia';
import { onMounted, ref, watch } from 'vue';
import { onMounted, ref } from 'vue';
import { usePermissionStore, useUserStore } from '@/store';
import { Permissions } from '@/utils/constants';
import type { Ref } from 'vue';
import type { COMSObjectPermission } from '@/types';
import type { COMSObjectPermission, User } from '@/types';
// Props
type Props = {
Expand All @@ -20,12 +20,12 @@ const permissionStore = usePermissionStore();
const userStore = useUserStore();
const { getObjectPermissions } = storeToRefs(permissionStore);
const { getUsers } = storeToRefs(userStore);
// State
const managedBy: Ref<string | undefined> = ref();
// Actions
async function load() {
onMounted(async () => {
await permissionStore.fetchObjectPermissions({ objectId: props.objectId });
const uniqueIds = [
Expand All @@ -38,19 +38,11 @@ async function load() {
if (uniqueIds.length) {
await userStore.fetchUsers({ userId: uniqueIds });
managedBy.value = userStore
.findUsersById(uniqueIds)
.map((x) => x.fullName)
managedBy.value = getUsers
.value(uniqueIds)
.map((x: User) => x.fullName)
.join(', ');
}
}
onMounted(() => {
load();
});
watch(props, () => {
load();
});
</script>

Expand Down
192 changes: 77 additions & 115 deletions frontend/src/components/object/ObjectFileDetails.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { storeToRefs } from 'pinia';
import { onBeforeMount, ref, watch } from 'vue';
import { computed, onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
import {
Expand All @@ -18,6 +18,7 @@ import { ShareObjectButton } from '@/components/object/share';
import { Button, Dialog, Divider } from '@/lib/primevue';
import {
useAuthStore,
useBucketStore,
useMetadataStore,
useObjectStore,
usePermissionStore,
Expand All @@ -28,116 +29,81 @@ import { Permissions, RouteNames } from '@/utils/constants';
import { ButtonMode } from '@/utils/enums';
import type { Ref } from 'vue';
import type { COMSObject, Version } from '@/types';
import type { COMSObject } from '@/types';
// Props
type Props = {
objectId: string;
versionId?: string;
versionId: string;
};
const props = withDefaults(defineProps<Props>(), {
versionId: undefined
});
const props = withDefaults(defineProps<Props>(), {});
const router = useRouter();
// Store
const bucketStore = useBucketStore();
const metadataStore = useMetadataStore();
const objectStore = useObjectStore();
const permissionStore = usePermissionStore();
const tagStore = useTagStore();
const versionStore = useVersionStore();
const { getObjects } = storeToRefs(objectStore);
const { getUserId } = storeToRefs(useAuthStore());
const { getObject } = storeToRefs(objectStore);
const { getVersionsByObjectId, getLatestVersionIdByObjectId } = storeToRefs(versionStore);
// State
const object: Ref<COMSObject | undefined> = ref(undefined);
const bucketId: Ref<string> = ref('');
const latestVersionId: Ref<string | undefined> = ref(undefined);
const obj: Ref<COMSObject | undefined> = ref(undefined);
const permissionsVisible: Ref<boolean> = ref(false);
const permissionsObjectId: Ref<string> = ref('');
const permissionsObjectName: Ref<string | undefined> = ref('');
const version: Ref<Version | undefined> = ref(undefined);
// Actions
const router = useRouter();
const showPermissions = async (objectId: string) => {
permissionsVisible.value = true;
permissionsObjectId.value = objectId;
permissionsObjectName.value = obj.value?.name;
};
async function onDeletedSuccess(versionId: string) {
await Promise.all([
objectStore.fetchObjects({ objectId: props.objectId, userId: getUserId.value, bucketPerms: true }),
versionStore.fetchVersions({ objectId: props.objectId })
]);
// Navigate to new latest version if deleting active version
if (props.versionId === versionId) {
router.push({
name: RouteNames.DETAIL_OBJECTS,
query: {
objectId: props.objectId,
versionId: versionStore.findLatestVersionIdByObjectId(props.objectId)
}
});
}
}
const currentVersionId: Ref<string | undefined> = ref(props.versionId);
const latestVersionId = computed(() => getLatestVersionIdByObjectId.value(props.objectId));
const permissionsVisible: Ref<boolean> = ref(false);
async function onFileUploaded() {
async function onVersionsChanged() {
await Promise.all([
objectStore.fetchObjects({ objectId: props.objectId, userId: getUserId.value, bucketPerms: true }),
versionStore.fetchVersions({ objectId: props.objectId })
]);
// Obtaining the version id and passing it to the route forces a destruct/construct of the component
// Easier approach than attempting to in-place refresh all the data
router.push({
name: RouteNames.DETAIL_OBJECTS,
query: {
objectId: props.objectId,
versionId: versionStore.findLatestVersionIdByObjectId(props.objectId)
}
versionStore.fetchVersions({ objectId: props.objectId }),
metadataStore.fetchMetadata({ objectId: props.objectId }),
tagStore.fetchTagging({ objectId: props.objectId })
]).then(async () => {
currentVersionId.value = latestVersionId.value;
await Promise.all([
versionStore.fetchMetadata({ objectId: props.objectId }),
versionStore.fetchTagging({ objectId: props.objectId })
]);
});
}
onBeforeMount(async () => {
if (props.objectId) {
const head = await objectStore.headObject(props.objectId);
let isPublic = head?.status === 204;
await permissionStore.fetchBucketPermissions({ userId: getUserId.value, objectPerms: true });
await objectStore.fetchObjects({ objectId: props.objectId, userId: getUserId.value, bucketPerms: true });
obj.value = objectStore.findObjectById(props.objectId);
const bucketId = obj.value?.bucketId;
if (
!isPublic &&
(!obj.value || !permissionStore.isObjectActionAllowed(obj.value.id, getUserId.value, Permissions.READ, bucketId))
) {
router.replace({ name: RouteNames.FORBIDDEN });
}
}
});
watch([props, getObjects], async () => {
await metadataStore.fetchMetadata({ objectId: props.objectId });
tagStore.fetchTagging({ objectId: props.objectId });
obj.value = objectStore.findObjectById(props.objectId);
bucketId.value = obj.value?.bucketId || '';
latestVersionId.value = versionStore.findLatestVersionIdByObjectId(props.objectId);
if (props.versionId) {
await versionStore.fetchMetadata({ versionId: props.versionId });
versionStore.fetchTagging({ versionId: props.versionId });
version.value = versionStore.findVersionById(props.versionId);
onMounted(async () => {
const head = await objectStore.headObject(props.objectId);
await permissionStore.fetchBucketPermissions({ userId: getUserId.value, objectPerms: true });
await objectStore.fetchObjects({ objectId: props.objectId, userId: getUserId.value, bucketPerms: true });
object.value = getObject.value(props.objectId);
const bucketId = object.value?.bucketId;
if (
head?.status !== 204 &&
(!object.value ||
!permissionStore.isObjectActionAllowed(object.value.id, getUserId.value, Permissions.READ, object.value.bucketId))
) {
router.replace({ name: RouteNames.FORBIDDEN });
}
// fetch data for child components
await Promise.all([
bucketStore.fetchBuckets({ bucketId: bucketId }),
versionStore.fetchVersions({ objectId: props.objectId }),
metadataStore.fetchMetadata({ objectId: props.objectId }),
tagStore.fetchTagging({ objectId: props.objectId }),
versionStore.fetchTagging({ objectId: props.objectId }),
versionStore.fetchMetadata({ objectId: props.objectId })
]);
});
</script>

<template>
<div v-if="obj">
<div v-if="object">
<div class="grid grid-nogutter">
<div class="col-12">
<h1 class="heading">File details</h1>
Expand All @@ -149,36 +115,36 @@ watch([props, getObjects], async () => {
class="text-3xl pr-3"
/>
<h2 class="">
{{ obj.name }}
{{ object.name }}
</h2>
</div>

<div class="action-buttons">
<ShareObjectButton :id="props.objectId" />
<ShareObjectButton :id="object.id" />
<DownloadObjectButton
v-if="
obj.public || permissionStore.isObjectActionAllowed(props.objectId, getUserId, Permissions.READ, bucketId)
object.public || permissionStore.isObjectActionAllowed(object.id, getUserId, Permissions.READ, bucketId)
"
:mode="ButtonMode.ICON"
:ids="[props.objectId]"
:version-id="props.versionId"
:ids="[object.id]"
:version-id="currentVersionId"
/>
<Button
v-if="permissionStore.isObjectActionAllowed(props.objectId, getUserId, Permissions.MANAGE, bucketId)"
v-if="permissionStore.isObjectActionAllowed(object.id, getUserId, Permissions.MANAGE, bucketId)"
v-tooltip.bottom="'Object permissions'"
class="p-button-lg p-button-text"
aria-label="Object permissions"
@click="showPermissions(props.objectId)"
@click="permissionsVisible = true"
>
<font-awesome-icon icon="fa-solid fa-users" />
</Button>
<DeleteObjectButton
v-if="permissionStore.isObjectActionAllowed(props.objectId, getUserId, Permissions.DELETE, bucketId)"
v-if="permissionStore.isObjectActionAllowed(object.id, getUserId, Permissions.DELETE, bucketId)"
:mode="ButtonMode.ICON"
:ids="[props.objectId]"
:version-id="props.versionId"
:disabled="versionStore.findVersionsByObjectId(props.objectId).length === 1"
@on-deleted-success="onDeletedSuccess"
:ids="[object.id]"
:version-id="currentVersionId"
:disabled="getVersionsByObjectId(object.id).length === 1"
@on-deleted-success="onVersionsChanged"
/>
</div>
</div>
Expand All @@ -187,51 +153,47 @@ watch([props, getObjects], async () => {
<div class="flex flex-row">
<div class="flex flex-column w-6 gap-3 py-5">
<ObjectProperties
:object-id="props.objectId"
:version-id="props.versionId"
:object-id="object.id"
:full-view="true"
/>
<ObjectAccess :object-id="props.objectId" />
<ObjectAccess :object-id="object.id" />
<ObjectMetadata
:editable="props.versionId === latestVersionId"
:object-id="props.objectId"
:version-id="props.versionId"
@on-file-uploaded="onFileUploaded"
v-model:version-id="currentVersionId"
:editable="currentVersionId === latestVersionId"
:object-id="object.id"
@on-metadata-success="onVersionsChanged"
/>
</div>
<Divider layout="vertical" />
<div class="flex flex-column w-6 gap-4 xl:pl-3 py-5">
<div class="flex flex-row-reverse">
<ObjectUploadBasic
v-if="permissionStore.isObjectActionAllowed(props.objectId, getUserId, Permissions.UPDATE, bucketId)"
v-if="permissionStore.isObjectActionAllowed(object.id, getUserId, Permissions.UPDATE, object.bucketId)"
:bucket-id="bucketId"
:object-id="props.objectId"
@on-file-uploaded="onFileUploaded"
:object-id="object.id"
@on-file-uploaded="onVersionsChanged"
/>
</div>
<ObjectVersion
v-if="props.versionId"
v-model:version-id="currentVersionId"
:bucket-id="bucketId"
:object-id="props.objectId"
:version-id="props.versionId"
:object-id="object.id"
@on-deleted-success="onVersionsChanged"
/>
<ObjectTag
:object-id="props.objectId"
:version-id="props.versionId"
@on-file-uploaded="onFileUploaded"
v-model:version-id="currentVersionId"
:object-id="object.id"
/>
</div>
</div>
</div>

<!-- eslint-disable vue/no-v-model-argument -->
<Dialog
v-model:visible="permissionsVisible"
:draggable="false"
:modal="true"
class="bcbox-info-dialog"
>
<!-- eslint-enable vue/no-v-model-argument -->
<template #header>
<font-awesome-icon
icon="fas fa-users"
Expand All @@ -241,10 +203,10 @@ watch([props, getObjects], async () => {
</template>

<h3 class="bcbox-info-dialog-subhead">
{{ permissionsObjectName }}
{{ object?.name }}
</h3>

<ObjectPermission :object-id="permissionsObjectId" />
<ObjectPermission :object-id="props.objectId" />
</Dialog>
</template>

Expand Down
Loading

0 comments on commit b7749a4

Please sign in to comment.