diff --git a/packages/nc-gui/components/account/UserList.vue b/packages/nc-gui/components/account/UserList.vue index 1a501e4c0d..b73f89c4d8 100644 --- a/packages/nc-gui/components/account/UserList.vue +++ b/packages/nc-gui/components/account/UserList.vue @@ -2,7 +2,16 @@ import { OrgUserRoles } from 'nocodb-sdk' import type { OrgUserReqType, RequestParams, UserType } from 'nocodb-sdk' import type { User } from '#imports' -import { extractSdkResponseErrorMsg, iconMap, useApi, useCopy, useDashboard, useDebounceFn, useNuxtApp } from '#imports' +import { + extractSdkResponseErrorMsg, + iconMap, + useApi, + useCopy, + useDashboard, + useDebounceFn, + useNuxtApp, + useUserSorts, +} from '#imports' const { api, isLoading } = useApi() @@ -19,8 +28,14 @@ const { user: loggedInUser } = useGlobal() const { copy } = useCopy() +const { sorts, sortDirection, loadSorts, saveOrUpdate, handleGetSortedData } = useUserSorts('Org') + const users = ref([]) +const sortedUsers = computed(() => { + return handleGetSortedData(users.value, sorts.value) as UserType[] +}) + const currentPage = ref(1) const currentLimit = ref(10) @@ -64,6 +79,7 @@ const loadUsers = useDebounceFn(async (page = currentPage.value, limit = current onMounted(() => { loadUsers() + loadSorts() }) const updateRole = async (userId: string, roles: string) => { @@ -73,6 +89,12 @@ const updateRole = async (userId: string, roles: string) => { } as OrgUserReqType) message.success(t('msg.success.roleUpdated')) + users.value.forEach((user) => { + if (user.id === userId) { + user.roles = roles + } + }) + $e('a:org-user:role-updated', { role: roles }) } catch (e: any) { message.error(await extractSdkResponseErrorMsg(e)) @@ -176,10 +198,21 @@ const openDeleteModal = (user: UserType) => {
-
- {{ $t('labels.email') }} +
+ + {{ $t('labels.email') }} + + +
+
+ + {{ $t('objects.role') }} + +
-
{{ $t('objects.role') }}
{{ $t('labels.action') }}
@@ -193,7 +226,7 @@ const openDeleteModal = (user: UserType) => {
+import { iconMap } from '#imports' +import type { UsersSortType } from '~/lib' + +const { field, direction, handleUserSort } = defineProps<{ + field: UsersSortType['field'] + direction: UsersSortType['direction'] + handleUserSort: Function +}>() + +const isOpen = ref(false) + +const sortUserBy = (direction?: UsersSortType['direction']) => { + handleUserSort({ + field, + direction, + }) + isOpen.value = false +} + + + + + diff --git a/packages/nc-gui/components/project/AccessSettings.vue b/packages/nc-gui/components/project/AccessSettings.vue index 4a8f7ac062..006c4e80f3 100644 --- a/packages/nc-gui/components/project/AccessSettings.vue +++ b/packages/nc-gui/components/project/AccessSettings.vue @@ -8,8 +8,8 @@ import { parseStringDateTime, timeAgo, } from 'nocodb-sdk' -import type { WorkspaceUserRoles } from 'nocodb-sdk' -import { isEeUI, storeToRefs } from '#imports' +import type { Roles, WorkspaceUserRoles } from 'nocodb-sdk' +import { isEeUI, storeToRefs, useUserSorts } from '#imports' const basesStore = useBases() const { getBaseUsers, createProjectUser, updateProjectUser, removeProjectUser } = basesStore @@ -17,6 +17,8 @@ const { activeProjectId } = storeToRefs(basesStore) const { orgRoles, baseRoles } = useRoles() +const { sorts, sortDirection, loadSorts, saveOrUpdate, handleGetSortedData } = useUserSorts('Project') + const isSuper = computed(() => orgRoles.value?.[OrgUserRoles.SUPER_ADMIN]) interface Collaborators { @@ -24,6 +26,7 @@ interface Collaborators { email: string main_roles: OrgUserRoles roles: ProjectRoles + base_roles: Roles workspace_roles: WorkspaceUserRoles created_at: string } @@ -35,6 +38,14 @@ const isLoading = ref(false) const isSearching = ref(false) const accessibleRoles = ref<(typeof ProjectRoles)[keyof typeof ProjectRoles][]>([]) +const filteredCollaborators = computed(() => + collaborators.value.filter((collab) => collab.email.toLowerCase().includes(userSearchText.value.toLowerCase())), +) + +const sortedCollaborators = computed(() => { + return handleGetSortedData(filteredCollaborators.value, sorts.value) +}) + const loadCollaborators = async () => { try { const { users, totalRows } = await getBaseUsers({ @@ -64,28 +75,32 @@ const loadCollaborators = async () => { } const updateCollaborator = async (collab: any, roles: ProjectRoles) => { + const currentCollaborator = collaborators.value.find((coll) => coll.id === collab.id)! + try { if ( !roles || (roles === ProjectRoles.NO_ACCESS && !isEeUI) || - (collab.workspace_roles && WorkspaceRolesToProjectRoles[collab.workspace_roles as WorkspaceUserRoles] === roles && isEeUI) + (currentCollaborator.workspace_roles && + WorkspaceRolesToProjectRoles[currentCollaborator.workspace_roles as WorkspaceUserRoles] === roles && + isEeUI) ) { await removeProjectUser(activeProjectId.value!, collab) if ( - collab.workspace_roles && - WorkspaceRolesToProjectRoles[collab.workspace_roles as WorkspaceUserRoles] === roles && + currentCollaborator.workspace_roles && + WorkspaceRolesToProjectRoles[currentCollaborator.workspace_roles as WorkspaceUserRoles] === roles && isEeUI ) { - collab.roles = WorkspaceRolesToProjectRoles[collab.workspace_roles as WorkspaceUserRoles] + currentCollaborator.roles = WorkspaceRolesToProjectRoles[currentCollaborator.workspace_roles as WorkspaceUserRoles] } else { - collab.roles = ProjectRoles.NO_ACCESS + currentCollaborator.roles = ProjectRoles.NO_ACCESS } - } else if (collab.base_roles) { - collab.roles = roles + } else if (currentCollaborator.base_roles) { + currentCollaborator.roles = roles await updateProjectUser(activeProjectId.value!, collab) } else { - collab.roles = roles - collab.base_roles = roles + currentCollaborator.roles = roles + currentCollaborator.base_roles = roles await createProjectUser(activeProjectId.value!, collab) } } catch (e: any) { @@ -106,16 +121,13 @@ onMounted(async () => { } else if (currentRoleIndex !== -1) { accessibleRoles.value = OrderedProjectRoles.slice(currentRoleIndex + 1) } + loadSorts() } catch (e: any) { message.error(await extractSdkResponseErrorMsg(e)) } finally { isLoading.value = false } }) - -const filteredCollaborators = computed(() => - collaborators.value.filter((collab) => collab.email.toLowerCase().includes(userSearchText.value.toLowerCase())), -)