Skip to content

Commit

Permalink
refactor: remove hard-coded space roles, use permissions instead
Browse files Browse the repository at this point in the history
  • Loading branch information
Jannik Stehle committed Aug 15, 2024
1 parent 6e27d25 commit 463fa2e
Show file tree
Hide file tree
Showing 14 changed files with 158 additions and 189 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,58 +9,42 @@
<div v-if="!filteredSpaceMembers.length">
<h3 class="oc-text-bold oc-text-medium" v-text="$gettext('No members found')" />
</div>
<div
v-if="filteredSpaceManagers.length"
class="oc-mb-m"
data-testid="space-members-role-managers"
>
<h3 class="oc-text-bold oc-text-medium" v-text="$gettext('Managers')" />
<members-role-section :members="filteredSpaceManagers" />
<div v-for="(role, i) in availableRoles" :key="i" class="oc-mb-m">
<div v-if="getPermissionsForRole(role).length">
<h3 class="oc-text-bold oc-text-medium" v-text="role.label" />
<members-role-section :permissions="getPermissionsForRole(role)" />
</div>
</div>
<div
v-if="filteredSpaceEditors.length"
class="oc-mb-m"
data-testid="space-members-role-editors"
>
<h3 class="oc-text-bold oc-text-medium" v-text="$gettext('Editors')" />
<members-role-section :members="filteredSpaceEditors" />
</div>
<div
v-if="filteredSpaceViewers.length"
class="oc-mb-m"
data-testid="space-members-role-viewers"
>
<h3 class="oc-text-bold oc-text-medium" v-text="$gettext('Viewers')" />
<members-role-section :members="filteredSpaceViewers" />
</div>
<div
v-if="filteredSpaceSecureViewers.length"
class="oc-mb-m"
data-testid="space-members-role-secure-viewers"
>
<h3 class="oc-text-bold oc-text-medium" v-text="$gettext('Secure viewers')" />
<members-role-section :members="filteredSpaceSecureViewers" />
<div v-if="permissionsWithoutRole.length">
<h3 class="oc-text-bold oc-text-medium" v-text="$gettext('Custom role')" />
<members-role-section :permissions="permissionsWithoutRole" />
</div>
</div>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, inject, ref, watch, unref } from 'vue'
import { SpaceResource, SpaceRole } from '@ownclouders/web-client'
import { ShareRole, SpaceResource } from '@ownclouders/web-client'
import MembersRoleSection from './MembersRoleSection.vue'
import Fuse from 'fuse.js'
import Mark from 'mark.js'
import { defaultFuseOptions } from '@ownclouders/web-pkg'
import { defaultFuseOptions, useSharesStore } from '@ownclouders/web-pkg'
import { Permission } from '@ownclouders/web-client/graph/generated'
type SpaceMember = { displayName: string; permission: Permission }
export default defineComponent({
name: 'MembersPanel',
components: { MembersRoleSection },
setup() {
const sharesStore = useSharesStore()
const resource = inject<SpaceResource>('resource')
const filterTerm = ref('')
const markInstance = ref(null)
const membersListRef = ref(null)
const filterMembers = (collection: Array<SpaceRole & { roleType: string }>, term: string) => {
const filterMembers = (collection: SpaceMember[], term: string) => {
if (!(term || '').trim()) {
return collection
}
Expand All @@ -69,43 +53,35 @@ export default defineComponent({
return searchEngine.search(term).map((r) => r.item)
}
const spaceMembers = computed(() => {
return [
...unref(resource).spaceRoles.manager.map((r) => ({
...r,
roleType: 'manager'
})),
...unref(resource).spaceRoles.editor.map((r) => ({
...r,
roleType: 'editor'
})),
...unref(resource).spaceRoles.viewer.map((r) => ({
...r,
roleType: 'viewer'
})),
...unref(resource).spaceRoles['secure-viewer'].map((r) => ({
...r,
roleType: 'secure-viewer'
}))
].sort((a, b) => a.displayName.localeCompare(b.displayName))
const spaceMembers = computed<SpaceMember[]>(() => {
return unref(resource).spacePermissions.map((permission) => {
const identity = permission.grantedToV2.user || permission.grantedToV2.group
return { displayName: identity.displayName, permission }
})
})
const filteredSpaceMembers = computed(() => {
return filterMembers(unref(spaceMembers), unref(filterTerm))
})
const filteredSpaceManagers = computed(() => {
return unref(filteredSpaceMembers).filter((m) => m.roleType === 'manager')
})
const filteredSpaceEditors = computed(() => {
return unref(filteredSpaceMembers).filter((m) => m.roleType === 'editor')
})
const filteredSpaceViewers = computed(() => {
return unref(filteredSpaceMembers).filter((m) => m.roleType === 'viewer')
const availableRoles = computed<ShareRole[]>(() => {
const permissionsWithRole = unref(resource).spacePermissions.filter((p) => p.roles?.length)
const roleIds = [...new Set(permissionsWithRole.map((p) => p.roles[0]))]
return roleIds.filter((r) => sharesStore.graphRoles[r]).map((r) => sharesStore.graphRoles[r])
})
const filteredSpaceSecureViewers = computed(() => {
return unref(filteredSpaceMembers).filter((m) => m.roleType === 'secure-viewer')
const permissionsWithoutRole = computed(() => {
return unref(filteredSpaceMembers)
.filter(({ permission }) => !permission.roles || !permission.roles.length)
.map(({ permission }) => permission)
})
const getPermissionsForRole = (role: ShareRole) => {
return unref(filteredSpaceMembers)
.filter(({ permission }) => (permission.roles || []).includes(role.id))
.map(({ permission }) => permission)
}
watch(filterTerm, () => {
if (unref(membersListRef)) {
markInstance.value = new Mark(unref(membersListRef))
Expand All @@ -120,11 +96,10 @@ export default defineComponent({
return {
filterTerm,
filteredSpaceMembers,
filteredSpaceManagers,
filteredSpaceEditors,
filteredSpaceViewers,
filteredSpaceSecureViewers,
membersListRef
membersListRef,
availableRoles,
permissionsWithoutRole,
getPermissionsForRole
}
}
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<template>
<ul class="oc-list">
<li
v-for="(member, index) in members"
v-for="(p, index) in permissions"
:key="index"
class="oc-flex oc-flex-middle oc-mb-s"
data-testid="space-members-list"
>
<oc-avatar
v-if="member.kind === 'user'"
:user-name="member.displayName"
v-if="p.grantedToV2.user"
:user-name="p.grantedToV2.user.displayName"
:width="36"
class="oc-mr-s"
/><oc-avatar-item
Expand All @@ -19,20 +19,20 @@
name="group"
class="oc-mr-s"
/>
{{ member.displayName }}
{{ (p.grantedToV2.user || p.grantedToV2.group).displayName }}
</li>
</ul>
</template>
<script lang="ts">
import { computed, defineComponent, PropType } from 'vue'
import { ShareTypes } from '@ownclouders/web-client'
import { SpaceRole } from '@ownclouders/web-client'
import { Permission } from '@ownclouders/web-client/graph/generated'
export default defineComponent({
name: 'MembersRoleSection',
props: {
members: {
type: Array as PropType<SpaceRole[]>,
permissions: {
type: Array as PropType<Permission[]>,
required: true
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ import {
unref,
watch
} from 'vue'
import { SpaceResource } from '@ownclouders/web-client'
import { getSpaceManagers, SpaceResource } from '@ownclouders/web-client'
import Mark from 'mark.js'
import Fuse from 'fuse.js'
import { useGettext } from 'vue3-gettext'
Expand Down Expand Up @@ -352,9 +352,9 @@ export default defineComponent({
])
const getManagerNames = (space: SpaceResource) => {
const allManagers = space.spaceRoles.manager
const allManagers = getSpaceManagers(space)
const managers = allManagers.length > 2 ? allManagers.slice(0, 2) : allManagers
let managerStr = managers.map((m) => m.displayName).join(', ')
let managerStr = managers.map((m) => m.grantedToV2.user.displayName).join(', ')
if (allManagers.length > 2) {
managerStr += `... +${allManagers.length - 2}`
}
Expand Down Expand Up @@ -386,11 +386,7 @@ export default defineComponent({
return formatFileSize(space.spaceQuota.remaining, language.current)
}
const getMemberCount = (space: SpaceResource) => {
return (
space.spaceRoles.manager.length +
space.spaceRoles.editor.length +
space.spaceRoles.viewer.length
)
return space.spacePermissions.length
}
const getSelectSpaceLabel = (space: SpaceResource) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ import {
} from '@ownclouders/web-pkg'
import { isLocationSharesActive } from '@ownclouders/web-pkg'
import { textUtils } from '../../../helpers/textUtils'
import { ShareTypes } from '@ownclouders/web-client'
import { GraphSharePermission, ShareTypes } from '@ownclouders/web-client'
import InviteCollaboratorForm from './Collaborators/InviteCollaborator/InviteCollaboratorForm.vue'
import CollaboratorListItem from './Collaborators/ListItem.vue'
import {
Expand Down Expand Up @@ -437,8 +437,9 @@ export default defineComponent({
return false
}
if (isProjectSpaceResource(this.space) && !this.space.isManager(this.user)) {
return false
if (isProjectSpaceResource(this.space)) {
const member = this.spaceMembers.find((member) => member.sharedWith.id === this.user?.id)
return member?.permissions?.includes(GraphSharePermission.updatePermissions)
}
return true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ export default defineComponent({
)
const memberCount = computed(() => {
return Object.values(props.space.spaceRoles).flat().length
return props.space.spacePermissions.length
})
const memberCountString = computed(() => {
return $ngettext('%{count} member', '%{count} members', unref(memberCount), {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
useCapabilityStore
} from '@ownclouders/web-pkg'
import {
GraphSharePermission,
isPersonalSpaceResource,
isProjectSpaceResource,
isShareResource,
Expand Down Expand Up @@ -363,9 +364,7 @@ export const useSideBarPanels = (): SidebarPanelExtension<SpaceResource, Resourc
) {
return false
}
return [...items[0].spaceRoles.manager, ...items[0].spaceRoles.editor].some(
(role) => role.id === userStore.user.id
)
return true
}
}
},
Expand Down
5 changes: 2 additions & 3 deletions packages/web-app-files/src/views/spaces/GenericTrash.vue
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,8 @@ export default defineComponent({
showActions() {
return (
!isProjectSpaceResource(this.space) ||
this.space.isEditor(this.user) ||
this.space.isManager(this.user)
// FIXME: check
!isProjectSpaceResource(this.space) || this.space.canRemoveFromTrashbin({ user: this.user })
)
}
}
Expand Down
7 changes: 4 additions & 3 deletions packages/web-app-files/src/views/spaces/Projects.vue
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ import {
} from '@ownclouders/web-pkg'
import SpaceContextActions from '../../components/Spaces/SpaceContextActions.vue'
import {
getSpaceManagers,
isProjectSpaceResource,
ProjectSpaceResource,
SpaceResource
Expand Down Expand Up @@ -365,9 +366,9 @@ export default defineComponent({
useKeyboardTableActions(keyActions)
const getManagerNames = (space: SpaceResource) => {
const allManagers = space.spaceRoles.manager
const allManagers = getSpaceManagers(space)
const managers = allManagers.length > 2 ? allManagers.slice(0, 2) : allManagers
let managerStr = managers.map((m) => m.displayName).join(', ')
let managerStr = managers.map((m) => m.grantedToV2.user.displayName).join(', ')
if (allManagers.length > 2) {
managerStr += `... +${allManagers.length - 2}`
}
Expand All @@ -394,7 +395,7 @@ export default defineComponent({
return formatFileSize(space.spaceQuota.remaining, language.current)
}
const getMemberCount = (space: SpaceResource) => {
return Object.values(space.spaceRoles).flat().length
return space.spacePermissions.length
}
onMounted(async () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/web-client/src/graph/drives/drives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ export const DrivesFactory = ({ axiosClient, config }: GraphFactoryOptions): Gra
async listMyDrives(options, requestOptions) {
const {
data: { value }
} = await meDrivesApi.listMyDrives(options?.orderBy, options?.filter, requestOptions)
} = await meDrivesApi.listMyDrivesBeta(options?.orderBy, options?.filter, requestOptions)
return value.map((d) => buildSpace({ ...d, serverUrl: getServerUrlFromDrive(d) }))
},

async listAllDrives(options, requestOptions) {
const {
data: { value }
} = await allDrivesApi.listAllDrives(options?.orderBy, options?.filter, requestOptions)
} = await allDrivesApi.listAllDrivesBeta(options?.orderBy, options?.filter, requestOptions)
return value.map((d) => buildSpace({ ...d, serverUrl: getServerUrlFromDrive(d) }))
}
}
Expand Down
Loading

0 comments on commit 463fa2e

Please sign in to comment.