Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add missing information to object details screens #35

Merged
merged 3 commits into from
Feb 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions frontend/src/components/form/GridRow.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<script setup lang="ts">
defineProps({
label: {
type: String,
default: undefined
},
value: {
type: String,
default: undefined
},
link: {
type: Object,
default: undefined
}
});
</script>

<template>
<div
v-if="value && label"
class="col-3"
>
{{ label }}:
</div>
<div
v-if="value && link"
class="col-9"
>
<router-link
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i like the way you made GriDRow re-usable.
you might be able to make this more compact:

<div v-if="value && label" class="grid-row">
  <div class="col-3">{{ label }}</div>
  <div class="col-9">
    <router-link v-if="link" :to="link">{{ value }}</router-link>
    <span v-else>{{value }}</span>
  </div>
</div>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with you here, but unfortunately nested div's break the formatting for some reason I wasn't able to figure out.

:to="link"
>
{{ value }}
</router-link>
</div>
<div
v-if="value && !link"
class="col-9"
>
{{ value }}
</div>
</template>
13 changes: 5 additions & 8 deletions frontend/src/components/object/DeleteObjectButton.vue
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
<script setup lang="ts">
// Types
import { ButtonMode } from '@/interfaces/common/enums';
import { ref, type PropType } from 'vue';
// PrimeVue / Fonts / etc
import Button from 'primevue/button';
import { useConfirm } from 'primevue/useconfirm';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import Button from 'primevue/button';
import Dialog from 'primevue/dialog';
import { useConfirm } from 'primevue/useconfirm';
import { useToast } from 'primevue/usetoast';
// State
import { ButtonMode } from '@/interfaces/common/enums';
import { useObjectStore } from '@/store/objectStore';
const objectStore = useObjectStore();
const confirm = useConfirm();
const objectStore = useObjectStore();
const toast = useToast();
// Props
Expand Down
9 changes: 3 additions & 6 deletions frontend/src/components/object/DownloadObjectButton.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
<script setup lang="ts">
// Types
import { ButtonMode } from '@/interfaces/common/enums';
import { ref, type PropType } from 'vue';

// PrimeVue/Font
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import Button from 'primevue/button';
import Dialog from 'primevue/dialog';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
// State

import { ButtonMode } from '@/interfaces/common/enums';
import { useObjectStore } from '@/store';

const objectStore = useObjectStore();
Expand Down
39 changes: 34 additions & 5 deletions frontend/src/components/object/ObjectAccess.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,41 @@
<!-- <script setup lang="ts">
<script setup lang="ts">
import { onMounted, ref, watch } from 'vue';
import { storeToRefs } from 'pinia';
import { useUserStore } from '@/store';
import { Permissions } from '@/utils/constants';
defineProps({
objectAccess: {
import type { Ref } from 'vue';
import type { Permission } from '@/interfaces';
const userStore = useUserStore();
const { userSearch } = storeToRefs(userStore);
const props = defineProps({
objectInfo: {
type: Object,
default: undefined
}
});
const managedBy: Ref<string | undefined> = ref();
async function getUserData() {
const uniqueIds = [...new Set(props.objectInfo?.permissions
.filter( (x: Permission) => x.permCode === Permissions.MANAGE )
.map( (x: Permission) => x.userId) )];
await userStore.searchUsers({userId: uniqueIds} );
managedBy.value = userSearch.value.map( x => x.fullName ).join( ', ');
}
onMounted(() => {
getUserData();
});
watch( props, () => {
getUserData();
});
</script>

<template>
Expand All @@ -20,7 +49,7 @@ defineProps({
Managed by:
</div>
<div class="col-9">
{{ objectAccess?.managedBy }}
{{ managedBy }}
</div>
</div>
</template> -->
</template>
121 changes: 97 additions & 24 deletions frontend/src/components/object/ObjectFileDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,42 @@
import { onMounted, ref } from 'vue';
import { useRoute } from 'vue-router';
import { storeToRefs } from 'pinia';
import Button from 'primevue/button';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style: We'll want to reorder the imports so that the pinia one comes before the vue one.

import Dialog from 'primevue/dialog';
import { useToast } from 'primevue/usetoast';

import ObjectAccess from '@/components/object/ObjectAccess.vue';
import ObjectMetadata from '@/components/object/ObjectMetadata.vue';
import ObjectProperties from '@/components/object/ObjectProperties.vue';
import ObjectTag from '@/components/object/ObjectTag.vue';
import { useObjectStore } from '@/store';
import {
DeleteObjectButton,
DownloadObjectButton,
ObjectAccess,
ObjectMetadata,
ObjectPermission,
ObjectProperties,
ObjectTag
} from '@/components/object';

import { useObjectStore, useUserStore } from '@/store';
import { Permissions } from '@/utils/constants';

import type { Ref } from 'vue';
import type { COMSObject } from '@/interfaces';
import { ButtonMode } from '@/interfaces/common/enums';

const objectStore = useObjectStore();
const toast = useToast();
const route = useRoute();

const { objectList } = storeToRefs(objectStore);
const { currentUser } = storeToRefs(useUserStore());

const objectInfo: Ref<COMSObject> = ref({} as COMSObject);
const isInfoLoaded: Ref<Boolean> = ref(false);
const { objectList } = storeToRefs(useObjectStore());

const getObjectInfo = async (objId: string) => {
const permissionsVisible: Ref<boolean> = ref(false);
const permissionsObjectId: Ref<string> = ref('');
const permissionsObjectName: Ref<string> = ref('');

const getObjectInfo = (objId: string) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not suggesting we do it now, by personally i would find some code comments useful. or jsdoc or whatever.
// gets details, perms for a single object from objectList state in objectStore.
the toast summary on line 45 could be changed to 'unable to load object (singular)'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

separate note. Does this component call the objectStore.listObjects(objId) method.. in case someone navigates straight to this page. Rather than just checking the existing objectList.value.
maybe Luke was going to take a look at this.. or it;s for another ticket

Copy link
Contributor

@loneil loneil Feb 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a fix for that almost to go, but this ticket will merge conflict the heck out of that
https://apps.nrs.gov.bc.ca/int/jira/browse/SHOWCASE-3049

So would leave this and once this is merged in I'll sort it for 3049

try {
objectInfo.value = (objectList.value.find((x: COMSObject) => x.id === objId) as COMSObject);
isInfoLoaded.value = true;
Expand All @@ -29,32 +46,88 @@ const getObjectInfo = async (objId: string) => {
}
};

const showPermissions = async (objectId: string, objectName: string) => {
permissionsVisible.value = true;
permissionsObjectId.value = objectId;
permissionsObjectName.value = objectName;
};

onMounted(() => {
getObjectInfo(route.query.objId as string);
});
</script>

<template>
<div class="flex justify-content-start">
<div class="flex col align-items-center pl-0">
<font-awesome-icon
icon="fa-solid fa-circle-info"
style="font-size: 2rem"
/>
<h1 class="pl-1 font-bold">
File details
</h1>
<div>
<div class="flex justify-content-start">
<div class="flex col align-items-center pl-0">
<font-awesome-icon
icon="fa-solid fa-circle-info"
style="font-size: 2rem"
/>
<h1 class="pl-1 font-bold">
File details
</h1>
</div>
<div class="action-buttons">
<Button class="p-button-lg p-button-text">
<font-awesome-icon icon="fa-solid fa-share-nodes" />
</Button>
<DownloadObjectButton
v-if="objectStore.isActionAllowed(objectInfo.permissions, Permissions.READ, currentUser?.userId)"
:mode="ButtonMode.ICON"
:ids="[objectInfo.id]"
/>
<Button
v-if="objectStore.isActionAllowed(objectInfo.permissions, Permissions.MANAGE, currentUser?.userId)"
class="p-button-lg p-button-text"
@click="showPermissions(objectInfo.id, objectInfo.name)"
>
<font-awesome-icon icon="fa-solid fa-users" />
</Button>
<DeleteObjectButton
v-if="objectStore.isActionAllowed(objectInfo.permissions, Permissions.DELETE, currentUser?.userId)"
:mode="ButtonMode.ICON"
:ids="[objectInfo.id]"
/>
</div>
</div>

<div
v-if="isInfoLoaded"
class="pl-2"
>
<ObjectProperties :object-info="objectInfo" />
<ObjectAccess :object-info="objectInfo" />
<ObjectMetadata :object-metadata="objectInfo.metadata" />
<ObjectTag :object-tag="objectInfo.tag" />
</div>
</div>
<div
v-if="isInfoLoaded"
class="pl-2"

<!-- eslint-disable vue/no-v-model-argument -->
<Dialog
v-model:visible="permissionsVisible"
:draggable="false"
:modal="true"
class="permissions-modal"
>
<ObjectProperties :object-properties="objectInfo" />
<ObjectAccess :object-access="objectInfo" />
<ObjectMetadata :object-metadata="objectInfo.metadata" />
<ObjectTag :object-tag="objectInfo.tag" />
</div>
<!-- eslint-enable vue/no-v-model-argument -->
<template #header>
<div class="flex">
<font-awesome-icon
icon="fa-solid fa-users"
class="pr-3 pt-2"
style="font-size: 2rem"
/>
<div>
<h1>Object Permissions</h1>
<h3>{{ permissionsObjectName }}</h3>
</div>
</div>
</template>

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

<style lang="scss" scoped>
Expand Down
12 changes: 7 additions & 5 deletions frontend/src/components/object/ObjectList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import { storeToRefs } from 'pinia';
import Button from 'primevue/button';
import { useToast } from 'primevue/usetoast';

import DeleteObjectButton from '@/components/object/DeleteObjectButton.vue';
import DownloadObjectButton from '@/components/object/DownloadObjectButton.vue';
import ObjectSidebar from '@/components/object/ObjectSidebar.vue';
import ObjectTable from '@/components/object/ObjectTable.vue';
import ObjectUpload from '@/components/object/ObjectUpload.vue';
import {
DeleteObjectButton,
DownloadObjectButton,
ObjectSidebar,
ObjectTable,
ObjectUpload
} from '@/components/object';
import { ButtonMode } from '@/interfaces/common/enums';
import { useBucketStore, useObjectStore } from '@/store';

Expand Down
Loading