web/satellite: add role column to project members table

A "Role" column has been added to the project members table to indicate
the roles of the members in the project.

Issue: https://github.com/storj/storj/issues/5743

Change-Id: I991b01e3d2cd792c21bd661feb7a225300d9a86b
This commit is contained in:
Wilfred Asomani 2023-05-10 12:17:41 +00:00
parent cf5ff537e3
commit 09311b22ca
6 changed files with 30 additions and 43 deletions

View File

@ -11,7 +11,7 @@
<v-table-checkbox v-if="!selectHidden" :disabled="selectDisabled || selectHidden" :value="selected" @selectClicked="selectClicked" /> <v-table-checkbox v-if="!selectHidden" :disabled="selectDisabled || selectHidden" :value="selected" @selectClicked="selectClicked" />
</th> </th>
<th <th
v-for="(val, _, index) in item" :key="index" class="align-left data" v-for="(val, keyVal, index) in item" :key="index" class="align-left data"
:class="{'overflow-visible': showBucketGuide(index)}" :class="{'overflow-visible': showBucketGuide(index)}"
> >
<div v-if="Array.isArray(val)" class="few-items"> <div v-if="Array.isArray(val)" class="few-items">
@ -21,8 +21,9 @@
<div v-if="icon && index === 0" class="item-icon file-background"> <div v-if="icon && index === 0" class="item-icon file-background">
<component :is="icon" /> <component :is="icon" />
</div> </div>
<p :class="{primary: index === 0}" :title="val" @click.stop="(e) => cellContentClicked(index, e)"> <p :class="{primary: ((!icon && index === 0) || (icon && index === 1))}" :title="val" @click.stop="(e) => cellContentClicked(index, e)">
<middle-truncate v-if="(itemType?.toLowerCase() === 'file')" :text="val" /> <middle-truncate v-if="(itemType?.toLowerCase() === 'file')" :text="val" />
<project-ownership-tag v-else-if="keyVal === 'owner'" no-icon :is-owner="val" />
<span v-else>{{ val }}</span> <span v-else>{{ val }}</span>
</p> </p>
<div v-if="showBucketGuide(index)" class="animation"> <div v-if="showBucketGuide(index)" class="animation">
@ -41,6 +42,7 @@ import { computed, Component } from 'vue';
import VTableCheckbox from '@/components/common/VTableCheckbox.vue'; import VTableCheckbox from '@/components/common/VTableCheckbox.vue';
import BucketGuide from '@/components/objects/BucketGuide.vue'; import BucketGuide from '@/components/objects/BucketGuide.vue';
import MiddleTruncate from '@/components/browser/MiddleTruncate.vue'; import MiddleTruncate from '@/components/browser/MiddleTruncate.vue';
import ProjectOwnershipTag from '@/components/project/ProjectOwnershipTag.vue';
import TableLockedIcon from '@/../static/images/browser/tableLocked.svg'; import TableLockedIcon from '@/../static/images/browser/tableLocked.svg';
import ColorFolderIcon from '@/../static/images/objects/colorFolder.svg'; import ColorFolderIcon from '@/../static/images/objects/colorFolder.svg';

View File

@ -2,41 +2,24 @@
// See LICENSE for copying information. // See LICENSE for copying information.
<template> <template>
<div v-if="project" class="tag" :class="{member: !isOwner}"> <div class="tag" :class="{member: !isOwner}">
<box-icon class="tag__icon" /> <box-icon v-if="!noIcon" class="tag__icon" />
<span class="tag__text"> {{ isOwner ? 'Owner': 'Member' }} </span> <span class="tag__text"> {{ isOwner ? 'Owner': 'Member' }} </span>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue';
import { Project } from '@/types/projects';
import { User } from '@/types/users';
import { useUsersStore } from '@/store/modules/usersStore';
import BoxIcon from '@/../static/images/allDashboard/box.svg'; import BoxIcon from '@/../static/images/allDashboard/box.svg';
const usersStore = useUsersStore(); const props = withDefaults(defineProps<{
isOwner: boolean,
const props = defineProps<{ noIcon?: boolean,
project?: Project, }>(), {
}>(); isOwner: false,
noIcon: false,
/**
* Returns user entity from store.
*/
const user = computed((): User => {
return usersStore.state.user;
}); });
/**
* Returns projects list from store.
*/
const isOwner = computed((): boolean => {
return props.project?.ownerId === user.value.id;
});
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@ -5,7 +5,7 @@
<div class="project-dashboard"> <div class="project-dashboard">
<div class="project-dashboard__heading"> <div class="project-dashboard__heading">
<h1 class="project-dashboard__heading__title" aria-roledescription="title">{{ selectedProject.name }}</h1> <h1 class="project-dashboard__heading__title" aria-roledescription="title">{{ selectedProject.name }}</h1>
<project-ownership-tag :project="selectedProject" /> <project-ownership-tag :is-owner="selectedProject.ownerId === user.id" />
</div> </div>
<p class="project-dashboard__message"> <p class="project-dashboard__message">
@ -191,6 +191,7 @@ import { useConfigStore } from '@/store/modules/configStore';
import { useProjectMembersStore } from '@/store/modules/projectMembersStore'; import { useProjectMembersStore } from '@/store/modules/projectMembersStore';
import { useAccessGrantsStore } from '@/store/modules/accessGrantsStore'; import { useAccessGrantsStore } from '@/store/modules/accessGrantsStore';
import { centsToDollars } from '@/utils/strings'; import { centsToDollars } from '@/utils/strings';
import { User } from '@/types/users';
import VLoader from '@/components/common/VLoader.vue'; import VLoader from '@/components/common/VLoader.vue';
import InfoContainer from '@/components/project/dashboard/InfoContainer.vue'; import InfoContainer from '@/components/project/dashboard/InfoContainer.vue';
@ -328,6 +329,13 @@ const bucketWasCreated = computed((): boolean => {
return false; return false;
}); });
/**
* Returns user entity from store.
*/
const user = computed((): User => {
return usersStore.state.user;
});
/** /**
* Get selected project from store. * Get selected project from store.
*/ */

View File

@ -35,25 +35,18 @@ const isProjectOwner = computed((): boolean => {
return props.itemData.user.id === projectsStore.state.selectedProject.ownerId; return props.itemData.user.id === projectsStore.state.selectedProject.ownerId;
}); });
const itemToRender = computed((): { [key: string]: string | string[] } => { const itemToRender = computed((): { [key: string]: unknown | string[] } => {
if (!isMobile.value && !isTablet.value) return { name: props.itemData.name, date: props.itemData.localDate(), email: props.itemData.email }; if (!isMobile.value && !isTablet.value) return { name: props.itemData.name, email: props.itemData.email, owner: isProjectOwner.value, date: props.itemData.localDate() };
if (isTablet.value) {
return { name: props.itemData.name, email: props.itemData.email, owner: isProjectOwner.value };
}
// TODO: change after adding actions button to list item // TODO: change after adding actions button to list item
return { name: props.itemData.name, email: props.itemData.email }; return { name: props.itemData.name, email: props.itemData.email };
}); });
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.owner {
cursor: not-allowed;
& > :deep(th:nth-child(2):after) {
content: 'Project Owner';
font-size: 13px;
color: #afb7c1;
}
}
:deep(.primary) { :deep(.primary) {
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;

View File

@ -29,8 +29,9 @@
> >
<template #head> <template #head>
<th class="align-left">Name</th> <th class="align-left">Name</th>
<th class="align-left date-added">Date Added</th>
<th class="align-left">Email</th> <th class="align-left">Email</th>
<th class="align-left">Role</th>
<th class="align-left date-added">Date Added</th>
</template> </template>
<template #body> <template #body>
<ProjectMemberListItem <ProjectMemberListItem

View File

@ -4,7 +4,7 @@
<template> <template>
<div v-if="project.id" class="project-item"> <div v-if="project.id" class="project-item">
<div class="project-item__header"> <div class="project-item__header">
<project-ownership-tag :project="project" /> <project-ownership-tag :is-owner="isOwner" />
<a <a
v-click-outside="closeDropDown" href="" class="project-item__header__menu" v-click-outside="closeDropDown" href="" class="project-item__header__menu"
@ -101,7 +101,7 @@ const user = computed((): User => {
}); });
/** /**
* Returns projects list from store. * Returns if the current user is the owner of this project.
*/ */
const isOwner = computed((): boolean => { const isOwner = computed((): boolean => {
return props.project.ownerId === user.value.id; return props.project.ownerId === user.value.id;