Feat: Add base for rendering workspaces items in the settings sidebar (#2558)

This commit is contained in:
Mike
2024-08-01 17:00:56 +02:00
committed by GitHub
parent b7c281961c
commit 99cd8a2da5
5 changed files with 96 additions and 8 deletions
@@ -23,8 +23,7 @@
:key="key"
:label="sidebarMenuItem.title"
:class="{
'bg-highlight-2 hover:!bg-highlight-2':
selectedMenuItem?.title === sidebarMenuItem.title
'bg-highlight-2 hover:!bg-highlight-2': targetMenuItem === key
}"
@click="targetMenuItem = `${key}`"
/>
@@ -38,12 +37,36 @@
:key="key"
:label="sidebarMenuItem.title"
:class="{
'bg-highlight-2 hover:!bg-highlight-2':
selectedMenuItem?.title === sidebarMenuItem.title
'bg-highlight-2 hover:!bg-highlight-2': targetMenuItem === key
}"
@click="targetMenuItem = `${key}`"
/>
</LayoutSidebarMenuGroup>
<LayoutSidebarMenuGroup
v-if="isWorkspacesEnabled && hasWorkspaceItems"
title="Workspace settings"
>
<template #title-icon>
<ServerStackIcon class="h-5 w-5" />
</template>
<LayoutSidebarMenuGroup
v-for="(workspaceItem, key) in workspaceItems"
:key="key"
:title="workspaceItem.name"
collapsible
>
<LayoutSidebarMenuGroupItem
v-for="(workspaceMenuItem, itemKey) in menuItemConfig.workspace"
:key="`${key}-${itemKey}`"
:label="workspaceMenuItem.title"
:class="{
'bg-highlight-2 hover:!bg-highlight-2':
targetMenuItem === itemKey && targetWorkspaceId === workspaceItem.id
}"
@click="onWorkspaceMenuItemClick(workspaceItem.id, `${itemKey}`)"
/>
</LayoutSidebarMenuGroup>
</LayoutSidebarMenuGroup>
</LayoutSidebarMenu>
</LayoutSidebar>
<component
@@ -79,6 +102,8 @@ import {
LayoutSidebarMenuGroup
} from '@speckle/ui-components'
import { Roles } from '@speckle/shared'
import { useQuery } from '@vue/apollo-composable'
import { settingsSidebarWorkspacesQuery } from '~/lib/settings/graphql/queries'
type MenuItem = {
title: string
@@ -87,7 +112,13 @@ type MenuItem = {
const { activeUser: user } = useActiveUser()
const breakpoints = useBreakpoints(TailwindBreakpoints)
const isWorkspacesEnabled = useIsWorkspacesEnabled()
const { result: workspaceResult } = useQuery(settingsSidebarWorkspacesQuery, null, {
enabled: isWorkspacesEnabled.value
})
const isMobile = breakpoints.smaller('md')
const targetWorkspaceId = ref<string | null>(null)
const menuItemConfig = shallowRef<{ [key: string]: { [key: string]: MenuItem } }>({
user: {
@@ -121,15 +152,28 @@ const menuItemConfig = shallowRef<{ [key: string]: { [key: string]: MenuItem } }
title: 'Pending invitations',
component: SettingsServerPendingInvitations
}
},
workspace: {
// Workspace menu items will be added here, general, members and projects
}
})
const isOpen = defineModel<boolean>('open', { required: true })
const targetMenuItem = defineModel<string | null>('targetMenuItem', { required: true })
const workspaceItems = computed(() =>
workspaceResult.value?.activeUser
? workspaceResult.value.activeUser.workspaces.items
: []
)
const hasWorkspaceItems = computed(() => workspaceItems.value.length > 0)
const isAdmin = computed(() => user.value?.role === Roles.Server.Admin)
const selectedMenuItem = computed((): MenuItem | null => {
const categories = [menuItemConfig.value.user, menuItemConfig.value.server]
const categories = [
menuItemConfig.value.user,
menuItemConfig.value.server,
menuItemConfig.value.workspace
]
for (const category of categories) {
if (targetMenuItem.value && targetMenuItem.value in category) {
return category[targetMenuItem.value]
@@ -146,6 +190,12 @@ const selectedMenuItem = computed((): MenuItem | null => {
return null
})
// Keep track of the selected workspace ID, to open the page for the correct workspace
const onWorkspaceMenuItemClick = (id: string, target: string) => {
targetWorkspaceId.value = id
targetMenuItem.value = target
}
watch(
() => user.value,
(newVal) => {
@@ -10,6 +10,14 @@ export const useIsAutomateModuleEnabled = () => {
return ref(FF_AUTOMATE_MODULE_ENABLED)
}
export const useIsWorkspacesEnabled = () => {
const {
public: { FF_WORKSPACES_MODULE_ENABLED }
} = useRuntimeConfig()
return ref(FF_WORKSPACES_MODULE_ENABLED)
}
export const useIsGendoModuleEnabled = () => {
const {
public: { FF_GENDOAI_MODULE_ENABLED }
@@ -206,6 +206,7 @@ const documents = {
"\n query AdminPanelProjectsList(\n $query: String\n $orderBy: String\n $limit: Int!\n $visibility: String\n $cursor: String\n ) {\n admin {\n projectList(\n query: $query\n orderBy: $orderBy\n limit: $limit\n visibility: $visibility\n cursor: $cursor\n ) {\n cursor\n items {\n id\n name\n visibility\n createdAt\n updatedAt\n models {\n totalCount\n }\n versions {\n totalCount\n }\n team {\n id\n user {\n name\n id\n avatar\n }\n }\n }\n totalCount\n cursor\n }\n }\n }\n": types.AdminPanelProjectsListDocument,
"\n query AdminPanelInvitesList($limit: Int!, $cursor: String, $query: String) {\n admin {\n inviteList(limit: $limit, cursor: $cursor, query: $query) {\n cursor\n items {\n email\n id\n invitedBy {\n id\n name\n }\n }\n totalCount\n }\n }\n }\n": types.AdminPanelInvitesListDocument,
"\n mutation InviteServerUser($input: [ServerInviteCreateInput!]!) {\n serverInviteBatchCreate(input: $input)\n }\n": types.InviteServerUserDocument,
"\n query SettingsSidebarWorkspaces {\n activeUser {\n workspaces {\n items {\n id\n name\n }\n }\n }\n }\n": types.SettingsSidebarWorkspacesDocument,
"\n fragment AppAuthorAvatar on AppAuthor {\n id\n name\n avatar\n }\n": types.AppAuthorAvatarFragmentDoc,
"\n fragment LimitedUserAvatar on LimitedUser {\n id\n name\n avatar\n }\n": types.LimitedUserAvatarFragmentDoc,
"\n fragment ActiveUserAvatar on User {\n id\n name\n avatar\n }\n": types.ActiveUserAvatarFragmentDoc,
@@ -1029,6 +1030,10 @@ export function graphql(source: "\n query AdminPanelInvitesList($limit: Int!, $
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n mutation InviteServerUser($input: [ServerInviteCreateInput!]!) {\n serverInviteBatchCreate(input: $input)\n }\n"): (typeof documents)["\n mutation InviteServerUser($input: [ServerInviteCreateInput!]!) {\n serverInviteBatchCreate(input: $input)\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n query SettingsSidebarWorkspaces {\n activeUser {\n workspaces {\n items {\n id\n name\n }\n }\n }\n }\n"): (typeof documents)["\n query SettingsSidebarWorkspaces {\n activeUser {\n workspaces {\n items {\n id\n name\n }\n }\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
@@ -2930,7 +2930,6 @@ export type StreamCreateInput = {
name?: InputMaybe<Scalars['String']['input']>;
/** Optionally specify user IDs of users that you want to invite to be contributors to this stream */
withContributors?: InputMaybe<Array<Scalars['String']['input']>>;
workspaceId?: InputMaybe<Scalars['String']['input']>;
};
export type StreamInviteCreateInput = {
@@ -3730,6 +3729,8 @@ export type Workspace = {
id: Scalars['ID']['output'];
/** Only available to workspace owners */
invitedTeam?: Maybe<Array<PendingWorkspaceCollaborator>>;
/** Optional url for workspace logo image */
logoUrl?: Maybe<Scalars['String']['output']>;
name: Scalars['String']['output'];
projects: ProjectCollection;
/** Active user's role for this workspace. `null` if request is not authenticated, or the workspace is not explicitly shared with you. */
@@ -3741,7 +3742,7 @@ export type Workspace = {
export type WorkspaceProjectsArgs = {
cursor?: InputMaybe<Scalars['String']['input']>;
filter?: InputMaybe<UserProjectsFilter>;
filter?: InputMaybe<WorkspaceProjectsFilter>;
limit?: Scalars['Int']['input'];
};
@@ -3761,7 +3762,6 @@ export type WorkspaceCollection = {
export type WorkspaceCreateInput = {
description?: InputMaybe<Scalars['String']['input']>;
logoUrl?: InputMaybe<Scalars['String']['input']>;
name: Scalars['String']['input'];
};
@@ -3846,6 +3846,11 @@ export type WorkspaceMutationsUpdateRoleArgs = {
input: WorkspaceRoleUpdateInput;
};
export type WorkspaceProjectsFilter = {
/** Filter out projects by name */
search?: InputMaybe<Scalars['String']['input']>;
};
export enum WorkspaceRole {
Admin = 'ADMIN',
Guest = 'GUEST',
@@ -4812,6 +4817,11 @@ export type InviteServerUserMutationVariables = Exact<{
export type InviteServerUserMutation = { __typename?: 'Mutation', serverInviteBatchCreate: boolean };
export type SettingsSidebarWorkspacesQueryVariables = Exact<{ [key: string]: never; }>;
export type SettingsSidebarWorkspacesQuery = { __typename?: 'Query', activeUser?: { __typename?: 'User', workspaces: { __typename?: 'WorkspaceCollection', items: Array<{ __typename?: 'Workspace', id: string, name: string }> } } | null };
export type AppAuthorAvatarFragment = { __typename?: 'AppAuthor', id: string, name: string, avatar?: string | null };
export type LimitedUserAvatarFragment = { __typename?: 'LimitedUser', id: string, name: string, avatar?: string | null };
@@ -5220,6 +5230,7 @@ export const AdminPanelUsersListDocument = {"kind":"Document","definitions":[{"k
export const AdminPanelProjectsListDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"AdminPanelProjectsList"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"query"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"orderBy"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"limit"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"visibility"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"admin"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectList"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"query"},"value":{"kind":"Variable","name":{"kind":"Name","value":"query"}}},{"kind":"Argument","name":{"kind":"Name","value":"orderBy"},"value":{"kind":"Variable","name":{"kind":"Name","value":"orderBy"}}},{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"Variable","name":{"kind":"Name","value":"limit"}}},{"kind":"Argument","name":{"kind":"Name","value":"visibility"},"value":{"kind":"Variable","name":{"kind":"Name","value":"visibility"}}},{"kind":"Argument","name":{"kind":"Name","value":"cursor"},"value":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"cursor"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"models"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}},{"kind":"Field","name":{"kind":"Name","value":"versions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}},{"kind":"Field","name":{"kind":"Name","value":"team"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}}]}}]}}]}}]} as unknown as DocumentNode<AdminPanelProjectsListQuery, AdminPanelProjectsListQueryVariables>;
export const AdminPanelInvitesListDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"AdminPanelInvitesList"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"limit"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"query"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"admin"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"inviteList"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"Variable","name":{"kind":"Name","value":"limit"}}},{"kind":"Argument","name":{"kind":"Name","value":"cursor"},"value":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}}},{"kind":"Argument","name":{"kind":"Name","value":"query"},"value":{"kind":"Variable","name":{"kind":"Name","value":"query"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"cursor"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"invitedBy"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}}]}}]}}]} as unknown as DocumentNode<AdminPanelInvitesListQuery, AdminPanelInvitesListQueryVariables>;
export const InviteServerUserDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"InviteServerUser"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ServerInviteCreateInput"}}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"serverInviteBatchCreate"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]} as unknown as DocumentNode<InviteServerUserMutation, InviteServerUserMutationVariables>;
export const SettingsSidebarWorkspacesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"SettingsSidebarWorkspaces"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspaces"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]}}]} as unknown as DocumentNode<SettingsSidebarWorkspacesQuery, SettingsSidebarWorkspacesQueryVariables>;
export const UpdateUserDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateUser"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UserUpdateInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUserMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"update"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"user"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"bio"}},{"kind":"Field","name":{"kind":"Name","value":"company"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"}}]}}]}}]}}]} as unknown as DocumentNode<UpdateUserMutation, UpdateUserMutationVariables>;
export const UpdateNotificationPreferencesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateNotificationPreferences"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"JSONObject"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userNotificationPreferencesUpdate"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"preferences"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]} as unknown as DocumentNode<UpdateNotificationPreferencesMutation, UpdateNotificationPreferencesMutationVariables>;
export const DeleteAccountDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteAccount"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UserDeleteInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userDelete"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"userConfirmation"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]} as unknown as DocumentNode<DeleteAccountMutation, DeleteAccountMutationVariables>;
@@ -0,0 +1,14 @@
import { graphql } from '~~/lib/common/generated/gql'
export const settingsSidebarWorkspacesQuery = graphql(`
query SettingsSidebarWorkspaces {
activeUser {
workspaces {
items {
id
name
}
}
}
}
`)