Feat: Request to join workspace (#3871)
This commit is contained in:
@@ -28,7 +28,6 @@
|
||||
:size="buttonSize"
|
||||
color="outline"
|
||||
class="px-4"
|
||||
:icon-left="CheckIcon"
|
||||
:disabled="loading"
|
||||
@click="onAcceptClick(token)"
|
||||
>
|
||||
@@ -52,7 +51,6 @@
|
||||
<script setup lang="ts">
|
||||
import type { MaybeNullOrUndefined, Optional } from '@speckle/shared'
|
||||
import type { AvatarUserType } from '~/lib/user/composables/avatar'
|
||||
import { CheckIcon } from '@heroicons/vue/24/solid'
|
||||
import { usePostAuthRedirect } from '~/lib/auth/composables/postAuthRedirect'
|
||||
import {
|
||||
useNavigateToLogin,
|
||||
@@ -125,7 +123,9 @@ const mainInfoBlockClasses = computed(() => {
|
||||
const avatarSize = computed(() => (props.block ? 'xxl' : 'base'))
|
||||
const buttonSize = computed(() => (props.block ? 'lg' : 'sm'))
|
||||
const isForRegisteredUser = computed(() => !!props.invite.user?.id)
|
||||
const acceptMessage = computed(() => (props.invite.workspace ? 'Join' : 'Accept'))
|
||||
const acceptMessage = computed(() =>
|
||||
props.invite.workspace ? 'Request to join' : 'Accept'
|
||||
)
|
||||
const declineMessage = computed(() => (props.invite.workspace ? 'Dismiss' : 'Decline'))
|
||||
|
||||
const onLoginSignupClick = async () => {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
v-model:search="search"
|
||||
search-placeholder="Search guests..."
|
||||
:workspace="workspace"
|
||||
show-invite-button
|
||||
/>
|
||||
<LayoutTable
|
||||
class="mt-6 md:mt-8"
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
v-model:search="search"
|
||||
search-placeholder="Search pending invites..."
|
||||
:workspace="workspace"
|
||||
show-invite-button
|
||||
/>
|
||||
<LayoutTable
|
||||
class="mt-6 md:mt-8 mb-12"
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
<template>
|
||||
<div>
|
||||
<LayoutTable
|
||||
class="mt-2 mb-12"
|
||||
:columns="[
|
||||
{ id: 'name', header: 'Name', classes: 'col-span-3' },
|
||||
{ id: 'createdAt', header: 'Requested at', classes: 'col-span-3' },
|
||||
{
|
||||
id: 'actions',
|
||||
header: '',
|
||||
classes: 'col-span-3 lg:col-span-6 flex items-center justify-end'
|
||||
}
|
||||
]"
|
||||
:items="joinRequests"
|
||||
empty-message="There are no pending join requests"
|
||||
>
|
||||
<template #name="{ item }">
|
||||
<div class="flex items-center gap-2">
|
||||
<UserAvatar hide-tooltip :user="item.user" />
|
||||
<span class="truncate text-body-xs text-foreground">
|
||||
{{ item.user.name }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #createdAt="{ item }">
|
||||
<p class="text-body-xs text-foreground">
|
||||
{{ formattedFullDate(item.createdAt) }}
|
||||
</p>
|
||||
</template>
|
||||
<template #actions="{ item }">
|
||||
<div class="flex items-center gap-x-2">
|
||||
<FormButton color="outline" size="sm" @click="onApprove(item)">
|
||||
Approve
|
||||
</FormButton>
|
||||
<FormButton color="outline" size="sm" @click="onDeny(item)">Deny</FormButton>
|
||||
</div>
|
||||
</template>
|
||||
</LayoutTable>
|
||||
|
||||
<WorkspaceJoinRequestApproveDialog
|
||||
v-model:open="showApproveJoinRequestDialog"
|
||||
:join-request="requestToApprove"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { type MaybeNullOrUndefined } from '@speckle/shared'
|
||||
import type {
|
||||
SettingsWorkspacesMembersRequestsTable_WorkspaceFragment,
|
||||
WorkspaceJoinRequestApproveDialog_WorkspaceJoinRequestFragment
|
||||
} from '~~/lib/common/generated/gql/graphql'
|
||||
import { graphql } from '~/lib/common/generated/gql'
|
||||
import { useWorkspaceJoinRequest } from '~/lib/workspaces/composables/joinRequests'
|
||||
|
||||
graphql(`
|
||||
fragment SettingsWorkspacesMembersRequestsTable_Workspace on Workspace {
|
||||
...SettingsWorkspacesMembersTableHeader_Workspace
|
||||
id
|
||||
adminWorkspacesJoinRequests(filter: $joinRequestsFilter) {
|
||||
totalCount
|
||||
items {
|
||||
...WorkspaceJoinRequestApproveDialog_WorkspaceJoinRequest
|
||||
id
|
||||
createdAt
|
||||
status
|
||||
user {
|
||||
id
|
||||
avatar
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
const props = defineProps<{
|
||||
workspace: MaybeNullOrUndefined<SettingsWorkspacesMembersRequestsTable_WorkspaceFragment>
|
||||
}>()
|
||||
|
||||
const { deny } = useWorkspaceJoinRequest()
|
||||
|
||||
const showApproveJoinRequestDialog = ref(false)
|
||||
const requestToApprove =
|
||||
ref<WorkspaceJoinRequestApproveDialog_WorkspaceJoinRequestFragment>()
|
||||
|
||||
const joinRequests = computed(
|
||||
() => props.workspace?.adminWorkspacesJoinRequests?.items || []
|
||||
)
|
||||
|
||||
const onApprove = (
|
||||
request: WorkspaceJoinRequestApproveDialog_WorkspaceJoinRequestFragment
|
||||
) => {
|
||||
requestToApprove.value = request
|
||||
showApproveJoinRequestDialog.value = true
|
||||
}
|
||||
|
||||
const onDeny = async (
|
||||
request: WorkspaceJoinRequestApproveDialog_WorkspaceJoinRequestFragment
|
||||
) => {
|
||||
if (!props.workspace?.id) return
|
||||
await deny(
|
||||
{
|
||||
workspaceId: props.workspace?.id,
|
||||
userId: request.user.id
|
||||
},
|
||||
request.id
|
||||
)
|
||||
}
|
||||
</script>
|
||||
@@ -6,6 +6,7 @@
|
||||
search-placeholder="Search members..."
|
||||
:workspace="workspace"
|
||||
show-role-filter
|
||||
show-invite-button
|
||||
/>
|
||||
<LayoutTable
|
||||
class="mt-6 md:mt-8 mb-12"
|
||||
|
||||
@@ -24,12 +24,14 @@
|
||||
:hide-items="[Roles.Workspace.Guest]"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="!isWorkspaceAdmin" v-tippy="'You must be a workspace admin'">
|
||||
<FormButton :disabled="!isWorkspaceAdmin">Invite</FormButton>
|
||||
</div>
|
||||
<FormButton v-else @click="() => (isInviteDialogOpen = !isInviteDialogOpen)">
|
||||
Invite
|
||||
</FormButton>
|
||||
<template v-if="showInviteButton">
|
||||
<div v-if="!isWorkspaceAdmin" v-tippy="'You must be a workspace admin'">
|
||||
<FormButton :disabled="!isWorkspaceAdmin">Invite</FormButton>
|
||||
</div>
|
||||
<FormButton v-else @click="() => (isInviteDialogOpen = !isInviteDialogOpen)">
|
||||
Invite
|
||||
</FormButton>
|
||||
</template>
|
||||
</div>
|
||||
<InviteDialogWorkspace
|
||||
v-if="workspace"
|
||||
@@ -57,6 +59,7 @@ const props = defineProps<{
|
||||
searchPlaceholder: string
|
||||
workspace: MaybeNullOrUndefined<SettingsWorkspacesMembersTableHeader_WorkspaceFragment>
|
||||
showRoleFilter?: boolean
|
||||
showInviteButton?: boolean
|
||||
}>()
|
||||
|
||||
const search = defineModel<string>('search')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<InviteBanner :invite="invite" @processed="processJoin">
|
||||
<InviteBanner :invite="invite" @processed="processRequest">
|
||||
<template #message>
|
||||
Your team is already using Workspaces! Collaborate in the
|
||||
Your team is already using Workspaces, request to join the
|
||||
<span class="font-medium">{{ workspace.name }}</span>
|
||||
space!
|
||||
</template>
|
||||
@@ -9,21 +9,17 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useApolloClient } from '@vue/apollo-composable'
|
||||
import { useMutation } from '@vue/apollo-composable'
|
||||
import { useSynchronizedCookie } from '~/lib/common/composables/reactiveCookie'
|
||||
import { graphql } from '~/lib/common/generated/gql'
|
||||
import {
|
||||
DashboardJoinWorkspaceDocument,
|
||||
type WorkspaceInviteDiscoverableWorkspaceBanner_LimitedWorkspaceFragment
|
||||
} from '~/lib/common/generated/gql/graphql'
|
||||
import { type WorkspaceInviteDiscoverableWorkspaceBanner_LimitedWorkspaceFragment } from '~/lib/common/generated/gql/graphql'
|
||||
import { CookieKeys } from '~/lib/common/helpers/constants'
|
||||
import {
|
||||
getCacheId,
|
||||
getFirstErrorMessage,
|
||||
modifyObjectField
|
||||
} from '~/lib/common/helpers/graphql'
|
||||
import { workspaceRoute } from '~/lib/common/helpers/route'
|
||||
import { useMixpanel } from '~~/lib/core/composables/mp'
|
||||
import { dashboardRequestToJoinWorkspaceMutation } from '~~/lib/dashboard/graphql/mutations'
|
||||
import {
|
||||
convertThrowIntoFetchResult,
|
||||
getFirstErrorMessage
|
||||
} from '~~/lib/common/helpers/graphql'
|
||||
|
||||
graphql(`
|
||||
fragment WorkspaceInviteDiscoverableWorkspaceBanner_LimitedWorkspace on LimitedWorkspace {
|
||||
@@ -33,27 +29,15 @@ graphql(`
|
||||
description
|
||||
logo
|
||||
}
|
||||
fragment WorkspaceInviteDiscoverableWorkspaceBanner_Workspace on Workspace {
|
||||
id
|
||||
name
|
||||
description
|
||||
createdAt
|
||||
updatedAt
|
||||
logo
|
||||
domainBasedMembershipProtectionEnabled
|
||||
discoverabilityEnabled
|
||||
}
|
||||
`)
|
||||
|
||||
const props = defineProps<{
|
||||
workspace: WorkspaceInviteDiscoverableWorkspaceBanner_LimitedWorkspaceFragment
|
||||
}>()
|
||||
|
||||
const { mutate: requestToJoin } = useMutation(dashboardRequestToJoinWorkspaceMutation)
|
||||
const mixpanel = useMixpanel()
|
||||
const { client: apollo } = useApolloClient()
|
||||
const { activeUser } = useActiveUser()
|
||||
const { triggerNotification } = useGlobalToast()
|
||||
const router = useRouter()
|
||||
const dismissedDiscoverableWorkspaces = useSynchronizedCookie<string[]>(
|
||||
CookieKeys.DismissedDiscoverableWorkspaces,
|
||||
{
|
||||
@@ -69,73 +53,55 @@ const invite = computed(() => ({
|
||||
}
|
||||
}))
|
||||
|
||||
const processJoin = async (accept: boolean) => {
|
||||
if (!accept) {
|
||||
const processRequest = async (accept: boolean) => {
|
||||
if (accept) {
|
||||
const result = await requestToJoin({
|
||||
input: { workspaceId: props.workspace.id }
|
||||
}).catch(convertThrowIntoFetchResult)
|
||||
|
||||
if (result?.data) {
|
||||
// Dismiss it show it doesnt show again
|
||||
dismissedDiscoverableWorkspaces.value = [
|
||||
...dismissedDiscoverableWorkspaces.value,
|
||||
props.workspace.id
|
||||
]
|
||||
|
||||
mixpanel.track('Workspace Join Request Sent', {
|
||||
workspaceId: props.workspace.id,
|
||||
location: 'discovery banner',
|
||||
// eslint-disable-next-line camelcase
|
||||
workspace_id: props.workspace.id
|
||||
})
|
||||
|
||||
triggerNotification({
|
||||
title: 'Request sent',
|
||||
description: 'Your request to join the workspace has been sent.',
|
||||
type: ToastNotificationType.Success
|
||||
})
|
||||
} else {
|
||||
const errorMessage = getFirstErrorMessage(result?.errors)
|
||||
triggerNotification({
|
||||
title: 'Failed to send request',
|
||||
description: errorMessage,
|
||||
type: ToastNotificationType.Danger
|
||||
})
|
||||
}
|
||||
} else {
|
||||
dismissedDiscoverableWorkspaces.value = [
|
||||
...dismissedDiscoverableWorkspaces.value,
|
||||
props.workspace.id
|
||||
]
|
||||
apollo.cache.evict({
|
||||
id: getCacheId('LimitedWorkspace', props.workspace.id)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const userId = activeUser.value?.id
|
||||
if (!userId) return
|
||||
|
||||
const result = await apollo
|
||||
.mutate({
|
||||
mutation: DashboardJoinWorkspaceDocument,
|
||||
variables: {
|
||||
input: {
|
||||
workspaceId: props.workspace.id
|
||||
}
|
||||
},
|
||||
update(cache, { data }) {
|
||||
const workspaceId = data?.workspaceMutations.join.id
|
||||
if (!workspaceId) return
|
||||
|
||||
modifyObjectField(
|
||||
cache,
|
||||
getCacheId('User', userId),
|
||||
'workspaces',
|
||||
({ variables, helpers: { evict, createUpdatedValue, ref } }) => {
|
||||
if (variables.filter?.search?.length) return evict()
|
||||
|
||||
return createUpdatedValue(({ update }) => {
|
||||
update('totalCount', (totalCount) => totalCount + 1)
|
||||
update('items', (items) => [...items, ref('Workspace', workspaceId)])
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
})
|
||||
.catch(convertThrowIntoFetchResult)
|
||||
|
||||
if (result?.data) {
|
||||
apollo.cache.evict({
|
||||
id: getCacheId('LimitedWorkspace', props.workspace.id)
|
||||
})
|
||||
|
||||
triggerNotification({
|
||||
type: ToastNotificationType.Success,
|
||||
title: 'Joined workspace',
|
||||
description: 'Successfully joined workspace'
|
||||
})
|
||||
|
||||
mixpanel.track('Workspace Joined', {
|
||||
mixpanel.track('Workspace Discovery Banner Dismissed', {
|
||||
workspaceId: props.workspace.id,
|
||||
location: 'discovery banner',
|
||||
// eslint-disable-next-line camelcase
|
||||
workspace_id: props.workspace.id
|
||||
})
|
||||
|
||||
router.push(workspaceRoute(props.workspace.slug))
|
||||
} else {
|
||||
triggerNotification({
|
||||
type: ToastNotificationType.Danger,
|
||||
title: 'Failed to join workspace',
|
||||
description: getFirstErrorMessage(result?.errors)
|
||||
title: 'Discoverable workspace dismissed',
|
||||
type: ToastNotificationType.Info
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<LayoutDialog v-model:open="open" max-width="xs" :buttons="dialogButtons">
|
||||
<template #header>Approve join request</template>
|
||||
<p class="text-body-xs text-foreground">
|
||||
Are you sure you want to approve
|
||||
<span class="font-semibold">{{ joinRequest?.user.name }}'s</span>
|
||||
join request?
|
||||
</p>
|
||||
<div class="text-body-2xs text-foreground-2 leading-5 mt-4 mb-1">
|
||||
<p>
|
||||
Adding users may add seats to your current billing cycle. If there are available
|
||||
seats, they will be used first.
|
||||
</p>
|
||||
</div>
|
||||
</LayoutDialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import type { LayoutDialogButton } from '@speckle/ui-components'
|
||||
import { useWorkspaceJoinRequest } from '~/lib/workspaces/composables/joinRequests'
|
||||
import { graphql } from '~/lib/common/generated/gql'
|
||||
import type { WorkspaceJoinRequestApproveDialog_WorkspaceJoinRequestFragment } from '~/lib/common/generated/gql/graphql'
|
||||
import type { MaybeNullOrUndefined } from '@speckle/shared'
|
||||
|
||||
graphql(`
|
||||
fragment WorkspaceJoinRequestApproveDialog_WorkspaceJoinRequest on WorkspaceJoinRequest {
|
||||
id
|
||||
user {
|
||||
id
|
||||
name
|
||||
}
|
||||
workspace {
|
||||
id
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
const props = defineProps<{
|
||||
joinRequest: MaybeNullOrUndefined<WorkspaceJoinRequestApproveDialog_WorkspaceJoinRequestFragment>
|
||||
}>()
|
||||
|
||||
const open = defineModel<boolean>('open', { required: true })
|
||||
|
||||
const { approve } = useWorkspaceJoinRequest()
|
||||
|
||||
const dialogButtons = computed((): LayoutDialogButton[] => {
|
||||
return [
|
||||
{
|
||||
text: 'Cancel',
|
||||
props: { color: 'outline' },
|
||||
onClick: () => {
|
||||
open.value = false
|
||||
}
|
||||
},
|
||||
{
|
||||
text: 'Approve',
|
||||
onClick: async () => {
|
||||
if (props.joinRequest?.workspace.id && props.joinRequest?.user.id) {
|
||||
await approve(
|
||||
{
|
||||
workspaceId: props.joinRequest.workspace.id,
|
||||
userId: props.joinRequest.user.id
|
||||
},
|
||||
props.joinRequest.id
|
||||
)
|
||||
|
||||
open.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
</script>
|
||||
@@ -125,6 +125,7 @@ const documents = {
|
||||
"\n fragment SettingsWorkspacesMembersGuestsTable_Workspace on Workspace {\n id\n ...SettingsWorkspacesMembersTableHeader_Workspace\n ...SettingsSharedDeleteUserDialog_Workspace\n ...SettingsWorkspacesMembersChangeRoleDialog_Workspace\n team {\n items {\n id\n ...SettingsWorkspacesMembersGuestsTable_WorkspaceCollaborator\n }\n }\n }\n": types.SettingsWorkspacesMembersGuestsTable_WorkspaceFragmentDoc,
|
||||
"\n fragment SettingsWorkspacesMembersInvitesTable_PendingWorkspaceCollaborator on PendingWorkspaceCollaborator {\n id\n inviteId\n role\n title\n updatedAt\n user {\n id\n ...LimitedUserAvatar\n }\n invitedBy {\n id\n ...LimitedUserAvatar\n }\n }\n": types.SettingsWorkspacesMembersInvitesTable_PendingWorkspaceCollaboratorFragmentDoc,
|
||||
"\n fragment SettingsWorkspacesMembersInvitesTable_Workspace on Workspace {\n id\n ...SettingsWorkspacesMembersTableHeader_Workspace\n invitedTeam(filter: $invitesFilter) {\n ...SettingsWorkspacesMembersInvitesTable_PendingWorkspaceCollaborator\n }\n }\n": types.SettingsWorkspacesMembersInvitesTable_WorkspaceFragmentDoc,
|
||||
"\n fragment SettingsWorkspacesMembersRequestsTable_Workspace on Workspace {\n ...SettingsWorkspacesMembersTableHeader_Workspace\n id\n adminWorkspacesJoinRequests(filter: $joinRequestsFilter) {\n totalCount\n items {\n ...WorkspaceJoinRequestApproveDialog_WorkspaceJoinRequest\n id\n createdAt\n status\n user {\n id\n avatar\n name\n }\n }\n }\n }\n": types.SettingsWorkspacesMembersRequestsTable_WorkspaceFragmentDoc,
|
||||
"\n fragment SettingsWorkspacesMembersMembersTable_WorkspaceCollaborator on WorkspaceCollaborator {\n id\n role\n user {\n id\n avatar\n name\n company\n verified\n workspaceDomainPolicyCompliant\n }\n }\n": types.SettingsWorkspacesMembersMembersTable_WorkspaceCollaboratorFragmentDoc,
|
||||
"\n fragment SettingsWorkspacesMembersMembersTable_Workspace on Workspace {\n id\n name\n ...SettingsSharedDeleteUserDialog_Workspace\n ...SettingsWorkspacesMembersTableHeader_Workspace\n ...SettingsWorkspacesMembersChangeRoleDialog_Workspace\n team {\n items {\n id\n ...SettingsWorkspacesMembersMembersTable_WorkspaceCollaborator\n }\n }\n }\n": types.SettingsWorkspacesMembersMembersTable_WorkspaceFragmentDoc,
|
||||
"\n fragment SettingsWorkspacesMembersTableHeader_Workspace on Workspace {\n id\n role\n ...InviteDialogWorkspace_Workspace\n }\n": types.SettingsWorkspacesMembersTableHeader_WorkspaceFragmentDoc,
|
||||
@@ -143,7 +144,8 @@ const documents = {
|
||||
"\n fragment WorkspaceHeader_Workspace on Workspace {\n ...WorkspaceBase_Workspace\n ...WorkspaceTeam_Workspace\n ...BillingAlert_Workspace\n slug\n readOnly\n }\n": types.WorkspaceHeader_WorkspaceFragmentDoc,
|
||||
"\n fragment WorkspaceInviteBanner_PendingWorkspaceCollaborator on PendingWorkspaceCollaborator {\n id\n invitedBy {\n id\n ...LimitedUserAvatar\n }\n workspaceId\n workspaceName\n token\n user {\n id\n }\n ...UseWorkspaceInviteManager_PendingWorkspaceCollaborator\n }\n": types.WorkspaceInviteBanner_PendingWorkspaceCollaboratorFragmentDoc,
|
||||
"\n fragment WorkspaceInviteBlock_PendingWorkspaceCollaborator on PendingWorkspaceCollaborator {\n id\n workspaceId\n workspaceName\n token\n user {\n id\n name\n ...LimitedUserAvatar\n }\n title\n email\n ...UseWorkspaceInviteManager_PendingWorkspaceCollaborator\n }\n": types.WorkspaceInviteBlock_PendingWorkspaceCollaboratorFragmentDoc,
|
||||
"\n fragment WorkspaceInviteDiscoverableWorkspaceBanner_LimitedWorkspace on LimitedWorkspace {\n id\n name\n slug\n description\n logo\n }\n fragment WorkspaceInviteDiscoverableWorkspaceBanner_Workspace on Workspace {\n id\n name\n description\n createdAt\n updatedAt\n logo\n domainBasedMembershipProtectionEnabled\n discoverabilityEnabled\n }\n": types.WorkspaceInviteDiscoverableWorkspaceBanner_LimitedWorkspaceFragmentDoc,
|
||||
"\n fragment WorkspaceInviteDiscoverableWorkspaceBanner_LimitedWorkspace on LimitedWorkspace {\n id\n name\n slug\n description\n logo\n }\n": types.WorkspaceInviteDiscoverableWorkspaceBanner_LimitedWorkspaceFragmentDoc,
|
||||
"\n fragment WorkspaceJoinRequestApproveDialog_WorkspaceJoinRequest on WorkspaceJoinRequest {\n id\n user {\n id\n name\n }\n workspace {\n id\n }\n }\n": types.WorkspaceJoinRequestApproveDialog_WorkspaceJoinRequestFragmentDoc,
|
||||
"\n fragment WorkspaceSidebarAbout_Workspace on Workspace {\n ...WorkspaceDashboardAbout_Workspace\n }\n": types.WorkspaceSidebarAbout_WorkspaceFragmentDoc,
|
||||
"\n fragment WorkspaceSidebarMembers_Workspace on Workspace {\n ...WorkspaceTeam_Workspace\n }\n": types.WorkspaceSidebarMembers_WorkspaceFragmentDoc,
|
||||
"\n fragment WorkspaceSidebarSecurity_Workspace on Workspace {\n ...WorkspaceSecurity_Workspace\n }\n": types.WorkspaceSidebarSecurity_WorkspaceFragmentDoc,
|
||||
@@ -179,7 +181,7 @@ const documents = {
|
||||
"\n query ServerInfoAllScopes {\n serverInfo {\n scopes {\n name\n description\n }\n }\n }\n": types.ServerInfoAllScopesDocument,
|
||||
"\n query ProjectModelsSelectorValues($projectId: String!, $cursor: String) {\n project(id: $projectId) {\n id\n models(limit: 100, cursor: $cursor) {\n cursor\n totalCount\n items {\n ...CommonModelSelectorModel\n }\n }\n }\n }\n": types.ProjectModelsSelectorValuesDocument,
|
||||
"\n query MainServerInfoData {\n serverInfo {\n adminContact\n canonicalUrl\n company\n description\n guestModeEnabled\n inviteOnly\n name\n termsOfService\n version\n automateUrl\n }\n }\n": types.MainServerInfoDataDocument,
|
||||
"\n mutation DashboardJoinWorkspace($input: JoinWorkspaceInput!) {\n workspaceMutations {\n join(input: $input) {\n ...WorkspaceInviteDiscoverableWorkspaceBanner_Workspace\n }\n }\n }\n": types.DashboardJoinWorkspaceDocument,
|
||||
"\n mutation DashboardRequestToJoinWorkspace($input: WorkspaceRequestToJoinInput!) {\n workspaceMutations {\n requestToJoin(input: $input)\n }\n }\n": types.DashboardRequestToJoinWorkspaceDocument,
|
||||
"\n query DashboardProjectsPageQuery {\n activeUser {\n id\n projects(limit: 3) {\n items {\n ...DashboardProjectCard_Project\n }\n }\n ...ProjectsDashboardHeaderProjects_User\n }\n }\n": types.DashboardProjectsPageQueryDocument,
|
||||
"\n query DashboardProjectsPageWorkspaceQuery {\n activeUser {\n id\n ...ProjectsDashboardHeaderWorkspaces_User\n }\n }\n": types.DashboardProjectsPageWorkspaceQueryDocument,
|
||||
"\n mutation DeleteAccessToken($token: String!) {\n apiTokenRevoke(token: $token)\n }\n": types.DeleteAccessTokenDocument,
|
||||
@@ -306,8 +308,9 @@ const documents = {
|
||||
"\n query SettingsWorkspaceBilling($slug: String!) {\n workspaceBySlug(slug: $slug) {\n id\n ...SettingsWorkspacesBilling_Workspace\n }\n }\n": types.SettingsWorkspaceBillingDocument,
|
||||
"\n query SettingsWorkspaceBillingCustomerPortal($workspaceId: String!) {\n workspace(id: $workspaceId) {\n customerPortalUrl\n }\n }\n": types.SettingsWorkspaceBillingCustomerPortalDocument,
|
||||
"\n query SettingsWorkspaceRegions($slug: String!) {\n workspaceBySlug(slug: $slug) {\n id\n ...SettingsWorkspacesRegions_Workspace\n }\n serverInfo {\n ...SettingsWorkspacesRegions_ServerInfo\n }\n }\n": types.SettingsWorkspaceRegionsDocument,
|
||||
"\n query SettingsWorkspacesMembers(\n $slug: String!\n $invitesFilter: PendingWorkspaceCollaboratorsFilter\n ) {\n workspaceBySlug(slug: $slug) {\n ...SettingsWorkspacesMembers_Workspace\n ...SettingsWorkspacesMembersMembersTable_Workspace\n ...SettingsWorkspacesMembersGuestsTable_Workspace\n ...SettingsWorkspacesMembersInvitesTable_Workspace\n }\n }\n": types.SettingsWorkspacesMembersDocument,
|
||||
"\n query SettingsWorkspacesMembers(\n $slug: String!\n $invitesFilter: PendingWorkspaceCollaboratorsFilter\n $joinRequestsFilter: AdminWorkspaceJoinRequestFilter\n ) {\n workspaceBySlug(slug: $slug) {\n ...SettingsWorkspacesMembers_Workspace\n ...SettingsWorkspacesMembersMembersTable_Workspace\n ...SettingsWorkspacesMembersGuestsTable_Workspace\n ...SettingsWorkspacesMembersInvitesTable_Workspace\n ...SettingsWorkspacesMembersRequestsTable_Workspace\n }\n }\n": types.SettingsWorkspacesMembersDocument,
|
||||
"\n query SettingsWorkspacesMembersSearch($slug: String!, $filter: WorkspaceTeamFilter) {\n workspaceBySlug(slug: $slug) {\n id\n team(filter: $filter) {\n items {\n id\n ...SettingsWorkspacesMembersMembersTable_WorkspaceCollaborator\n }\n }\n }\n }\n": types.SettingsWorkspacesMembersSearchDocument,
|
||||
"\n query SettingsWorkspacesJoinRequestsSearch(\n $slug: String!\n $joinRequestsFilter: AdminWorkspaceJoinRequestFilter\n ) {\n workspaceBySlug(slug: $slug) {\n id\n ...SettingsWorkspacesMembersRequestsTable_Workspace\n }\n }\n": types.SettingsWorkspacesJoinRequestsSearchDocument,
|
||||
"\n query SettingsWorkspacesInvitesSearch(\n $slug: String!\n $invitesFilter: PendingWorkspaceCollaboratorsFilter\n ) {\n workspaceBySlug(slug: $slug) {\n ...SettingsWorkspacesMembersInvitesTable_Workspace\n }\n }\n": types.SettingsWorkspacesInvitesSearchDocument,
|
||||
"\n query SettingsUserEmailsQuery {\n activeUser {\n ...SettingsUserEmails_User\n }\n }\n": types.SettingsUserEmailsQueryDocument,
|
||||
"\n query SettingsWorkspacesProjects(\n $slug: String!\n $limit: Int!\n $cursor: String\n $filter: WorkspaceProjectsFilter\n ) {\n workspaceBySlug(slug: $slug) {\n id\n slug\n readOnly\n projects(limit: $limit, cursor: $cursor, filter: $filter) {\n cursor\n ...SettingsWorkspacesProjects_ProjectCollection\n }\n }\n }\n": types.SettingsWorkspacesProjectsDocument,
|
||||
@@ -357,6 +360,8 @@ const documents = {
|
||||
"\n mutation SetWorkspaceCreationState($input: WorkspaceCreationStateInput!) {\n workspaceMutations {\n updateCreationState(input: $input)\n }\n }\n": types.SetWorkspaceCreationStateDocument,
|
||||
"\n mutation WorkspaceUpdateDomainProtectionMutation($input: WorkspaceUpdateInput!) {\n workspaceMutations {\n update(input: $input) {\n id\n domainBasedMembershipProtectionEnabled\n }\n }\n }\n": types.WorkspaceUpdateDomainProtectionMutationDocument,
|
||||
"\n mutation WorkspaceUpdateDiscoverabilityMutation($input: WorkspaceUpdateInput!) {\n workspaceMutations {\n update(input: $input) {\n id\n discoverabilityEnabled\n }\n }\n }\n": types.WorkspaceUpdateDiscoverabilityMutationDocument,
|
||||
"\n mutation ApproveWorkspaceJoinRequest($input: ApproveWorkspaceJoinRequestInput!) {\n workspaceJoinRequestMutations {\n approve(input: $input)\n }\n }\n": types.ApproveWorkspaceJoinRequestDocument,
|
||||
"\n mutation DenyWorkspaceJoinRequest($input: DenyWorkspaceJoinRequestInput!) {\n workspaceJoinRequestMutations {\n deny(input: $input)\n }\n }\n": types.DenyWorkspaceJoinRequestDocument,
|
||||
"\n query WorkspaceAccessCheck($slug: String!) {\n workspaceBySlug(slug: $slug) {\n id\n }\n }\n": types.WorkspaceAccessCheckDocument,
|
||||
"\n query WorkspacePageQuery(\n $workspaceSlug: String!\n $invitesFilter: PendingWorkspaceCollaboratorsFilter\n $token: String\n ) {\n workspaceBySlug(slug: $workspaceSlug) {\n ...WorkspaceProjectList_Workspace\n }\n workspaceInvite(\n workspaceId: $workspaceSlug\n token: $token\n options: { useSlug: true }\n ) {\n id\n ...WorkspaceInviteBanner_PendingWorkspaceCollaborator\n ...WorkspaceInviteBlock_PendingWorkspaceCollaborator\n }\n }\n": types.WorkspacePageQueryDocument,
|
||||
"\n query WorkspaceProjectsQuery(\n $workspaceSlug: String!\n $filter: WorkspaceProjectsFilter\n $cursor: String\n ) {\n workspaceBySlug(slug: $workspaceSlug) {\n id\n projects(filter: $filter, cursor: $cursor, limit: 10) {\n ...WorkspaceProjectList_ProjectCollection\n }\n }\n }\n": types.WorkspaceProjectsQueryDocument,
|
||||
@@ -386,7 +391,7 @@ const documents = {
|
||||
"\n fragment SettingsUserEmails_User on User {\n id\n emails {\n ...SettingsUserEmailCards_UserEmail\n }\n }\n": types.SettingsUserEmails_UserFragmentDoc,
|
||||
"\n fragment SettingsWorkspacesBilling_Workspace on Workspace {\n ...BillingAlert_Workspace\n id\n role\n plan {\n name\n status\n createdAt\n paymentMethod\n }\n subscription {\n billingInterval\n currentBillingCycleEnd\n seats {\n guest\n plan\n }\n }\n team {\n items {\n id\n role\n }\n }\n }\n": types.SettingsWorkspacesBilling_WorkspaceFragmentDoc,
|
||||
"\n fragment SettingsWorkspacesGeneral_Workspace on Workspace {\n ...SettingsWorkspacesGeneralEditAvatar_Workspace\n ...SettingsWorkspaceGeneralDeleteDialog_Workspace\n ...SettingsWorkspacesGeneralEditSlugDialog_Workspace\n id\n name\n slug\n description\n logo\n role\n defaultProjectRole\n plan {\n status\n name\n }\n }\n": types.SettingsWorkspacesGeneral_WorkspaceFragmentDoc,
|
||||
"\n fragment SettingsWorkspacesMembers_Workspace on Workspace {\n id\n role\n team {\n items {\n id\n role\n }\n }\n invitedTeam(filter: $invitesFilter) {\n user {\n id\n }\n }\n }\n": types.SettingsWorkspacesMembers_WorkspaceFragmentDoc,
|
||||
"\n fragment SettingsWorkspacesMembers_Workspace on Workspace {\n id\n role\n team {\n items {\n id\n }\n }\n invitedTeam(filter: $invitesFilter) {\n user {\n id\n }\n }\n adminWorkspacesJoinRequests(filter: $joinRequestsFilter) {\n totalCount\n }\n }\n": types.SettingsWorkspacesMembers_WorkspaceFragmentDoc,
|
||||
"\n fragment SettingsWorkspacesProjects_ProjectCollection on ProjectCollection {\n totalCount\n items {\n ...SettingsSharedProjects_Project\n }\n }\n": types.SettingsWorkspacesProjects_ProjectCollectionFragmentDoc,
|
||||
"\n fragment SettingsWorkspacesRegions_Workspace on Workspace {\n id\n role\n defaultRegion {\n id\n ...SettingsWorkspacesRegionsSelect_ServerRegionItem\n }\n hasAccessToMultiRegion: hasAccessToFeature(\n featureName: workspaceDataRegionSpecificity\n )\n hasProjects: projects(limit: 0) {\n totalCount\n }\n }\n": types.SettingsWorkspacesRegions_WorkspaceFragmentDoc,
|
||||
"\n fragment SettingsWorkspacesRegions_ServerInfo on ServerInfo {\n multiRegion {\n regions {\n id\n ...SettingsWorkspacesRegionsSelect_ServerRegionItem\n }\n }\n }\n": types.SettingsWorkspacesRegions_ServerInfoFragmentDoc,
|
||||
@@ -851,6 +856,10 @@ export function graphql(source: "\n fragment SettingsWorkspacesMembersInvitesTa
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n fragment SettingsWorkspacesMembersInvitesTable_Workspace on Workspace {\n id\n ...SettingsWorkspacesMembersTableHeader_Workspace\n invitedTeam(filter: $invitesFilter) {\n ...SettingsWorkspacesMembersInvitesTable_PendingWorkspaceCollaborator\n }\n }\n"): (typeof documents)["\n fragment SettingsWorkspacesMembersInvitesTable_Workspace on Workspace {\n id\n ...SettingsWorkspacesMembersTableHeader_Workspace\n invitedTeam(filter: $invitesFilter) {\n ...SettingsWorkspacesMembersInvitesTable_PendingWorkspaceCollaborator\n }\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 fragment SettingsWorkspacesMembersRequestsTable_Workspace on Workspace {\n ...SettingsWorkspacesMembersTableHeader_Workspace\n id\n adminWorkspacesJoinRequests(filter: $joinRequestsFilter) {\n totalCount\n items {\n ...WorkspaceJoinRequestApproveDialog_WorkspaceJoinRequest\n id\n createdAt\n status\n user {\n id\n avatar\n name\n }\n }\n }\n }\n"): (typeof documents)["\n fragment SettingsWorkspacesMembersRequestsTable_Workspace on Workspace {\n ...SettingsWorkspacesMembersTableHeader_Workspace\n id\n adminWorkspacesJoinRequests(filter: $joinRequestsFilter) {\n totalCount\n items {\n ...WorkspaceJoinRequestApproveDialog_WorkspaceJoinRequest\n id\n createdAt\n status\n user {\n id\n avatar\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.
|
||||
*/
|
||||
@@ -926,7 +935,11 @@ export function graphql(source: "\n fragment WorkspaceInviteBlock_PendingWorksp
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n fragment WorkspaceInviteDiscoverableWorkspaceBanner_LimitedWorkspace on LimitedWorkspace {\n id\n name\n slug\n description\n logo\n }\n fragment WorkspaceInviteDiscoverableWorkspaceBanner_Workspace on Workspace {\n id\n name\n description\n createdAt\n updatedAt\n logo\n domainBasedMembershipProtectionEnabled\n discoverabilityEnabled\n }\n"): (typeof documents)["\n fragment WorkspaceInviteDiscoverableWorkspaceBanner_LimitedWorkspace on LimitedWorkspace {\n id\n name\n slug\n description\n logo\n }\n fragment WorkspaceInviteDiscoverableWorkspaceBanner_Workspace on Workspace {\n id\n name\n description\n createdAt\n updatedAt\n logo\n domainBasedMembershipProtectionEnabled\n discoverabilityEnabled\n }\n"];
|
||||
export function graphql(source: "\n fragment WorkspaceInviteDiscoverableWorkspaceBanner_LimitedWorkspace on LimitedWorkspace {\n id\n name\n slug\n description\n logo\n }\n"): (typeof documents)["\n fragment WorkspaceInviteDiscoverableWorkspaceBanner_LimitedWorkspace on LimitedWorkspace {\n id\n name\n slug\n description\n logo\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 fragment WorkspaceJoinRequestApproveDialog_WorkspaceJoinRequest on WorkspaceJoinRequest {\n id\n user {\n id\n name\n }\n workspace {\n id\n }\n }\n"): (typeof documents)["\n fragment WorkspaceJoinRequestApproveDialog_WorkspaceJoinRequest on WorkspaceJoinRequest {\n id\n user {\n id\n name\n }\n workspace {\n id\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@@ -1070,7 +1083,7 @@ export function graphql(source: "\n query MainServerInfoData {\n serverInfo
|
||||
/**
|
||||
* 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 DashboardJoinWorkspace($input: JoinWorkspaceInput!) {\n workspaceMutations {\n join(input: $input) {\n ...WorkspaceInviteDiscoverableWorkspaceBanner_Workspace\n }\n }\n }\n"): (typeof documents)["\n mutation DashboardJoinWorkspace($input: JoinWorkspaceInput!) {\n workspaceMutations {\n join(input: $input) {\n ...WorkspaceInviteDiscoverableWorkspaceBanner_Workspace\n }\n }\n }\n"];
|
||||
export function graphql(source: "\n mutation DashboardRequestToJoinWorkspace($input: WorkspaceRequestToJoinInput!) {\n workspaceMutations {\n requestToJoin(input: $input)\n }\n }\n"): (typeof documents)["\n mutation DashboardRequestToJoinWorkspace($input: WorkspaceRequestToJoinInput!) {\n workspaceMutations {\n requestToJoin(input: $input)\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@@ -1578,11 +1591,15 @@ export function graphql(source: "\n query SettingsWorkspaceRegions($slug: Strin
|
||||
/**
|
||||
* 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 SettingsWorkspacesMembers(\n $slug: String!\n $invitesFilter: PendingWorkspaceCollaboratorsFilter\n ) {\n workspaceBySlug(slug: $slug) {\n ...SettingsWorkspacesMembers_Workspace\n ...SettingsWorkspacesMembersMembersTable_Workspace\n ...SettingsWorkspacesMembersGuestsTable_Workspace\n ...SettingsWorkspacesMembersInvitesTable_Workspace\n }\n }\n"): (typeof documents)["\n query SettingsWorkspacesMembers(\n $slug: String!\n $invitesFilter: PendingWorkspaceCollaboratorsFilter\n ) {\n workspaceBySlug(slug: $slug) {\n ...SettingsWorkspacesMembers_Workspace\n ...SettingsWorkspacesMembersMembersTable_Workspace\n ...SettingsWorkspacesMembersGuestsTable_Workspace\n ...SettingsWorkspacesMembersInvitesTable_Workspace\n }\n }\n"];
|
||||
export function graphql(source: "\n query SettingsWorkspacesMembers(\n $slug: String!\n $invitesFilter: PendingWorkspaceCollaboratorsFilter\n $joinRequestsFilter: AdminWorkspaceJoinRequestFilter\n ) {\n workspaceBySlug(slug: $slug) {\n ...SettingsWorkspacesMembers_Workspace\n ...SettingsWorkspacesMembersMembersTable_Workspace\n ...SettingsWorkspacesMembersGuestsTable_Workspace\n ...SettingsWorkspacesMembersInvitesTable_Workspace\n ...SettingsWorkspacesMembersRequestsTable_Workspace\n }\n }\n"): (typeof documents)["\n query SettingsWorkspacesMembers(\n $slug: String!\n $invitesFilter: PendingWorkspaceCollaboratorsFilter\n $joinRequestsFilter: AdminWorkspaceJoinRequestFilter\n ) {\n workspaceBySlug(slug: $slug) {\n ...SettingsWorkspacesMembers_Workspace\n ...SettingsWorkspacesMembersMembersTable_Workspace\n ...SettingsWorkspacesMembersGuestsTable_Workspace\n ...SettingsWorkspacesMembersInvitesTable_Workspace\n ...SettingsWorkspacesMembersRequestsTable_Workspace\n }\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 SettingsWorkspacesMembersSearch($slug: String!, $filter: WorkspaceTeamFilter) {\n workspaceBySlug(slug: $slug) {\n id\n team(filter: $filter) {\n items {\n id\n ...SettingsWorkspacesMembersMembersTable_WorkspaceCollaborator\n }\n }\n }\n }\n"): (typeof documents)["\n query SettingsWorkspacesMembersSearch($slug: String!, $filter: WorkspaceTeamFilter) {\n workspaceBySlug(slug: $slug) {\n id\n team(filter: $filter) {\n items {\n id\n ...SettingsWorkspacesMembersMembersTable_WorkspaceCollaborator\n }\n }\n }\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 SettingsWorkspacesJoinRequestsSearch(\n $slug: String!\n $joinRequestsFilter: AdminWorkspaceJoinRequestFilter\n ) {\n workspaceBySlug(slug: $slug) {\n id\n ...SettingsWorkspacesMembersRequestsTable_Workspace\n }\n }\n"): (typeof documents)["\n query SettingsWorkspacesJoinRequestsSearch(\n $slug: String!\n $joinRequestsFilter: AdminWorkspaceJoinRequestFilter\n ) {\n workspaceBySlug(slug: $slug) {\n id\n ...SettingsWorkspacesMembersRequestsTable_Workspace\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@@ -1779,6 +1796,14 @@ export function graphql(source: "\n mutation WorkspaceUpdateDomainProtectionMut
|
||||
* 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 WorkspaceUpdateDiscoverabilityMutation($input: WorkspaceUpdateInput!) {\n workspaceMutations {\n update(input: $input) {\n id\n discoverabilityEnabled\n }\n }\n }\n"): (typeof documents)["\n mutation WorkspaceUpdateDiscoverabilityMutation($input: WorkspaceUpdateInput!) {\n workspaceMutations {\n update(input: $input) {\n id\n discoverabilityEnabled\n }\n }\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 mutation ApproveWorkspaceJoinRequest($input: ApproveWorkspaceJoinRequestInput!) {\n workspaceJoinRequestMutations {\n approve(input: $input)\n }\n }\n"): (typeof documents)["\n mutation ApproveWorkspaceJoinRequest($input: ApproveWorkspaceJoinRequestInput!) {\n workspaceJoinRequestMutations {\n approve(input: $input)\n }\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 mutation DenyWorkspaceJoinRequest($input: DenyWorkspaceJoinRequestInput!) {\n workspaceJoinRequestMutations {\n deny(input: $input)\n }\n }\n"): (typeof documents)["\n mutation DenyWorkspaceJoinRequest($input: DenyWorkspaceJoinRequestInput!) {\n workspaceJoinRequestMutations {\n deny(input: $input)\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@@ -1898,7 +1923,7 @@ export function graphql(source: "\n fragment SettingsWorkspacesGeneral_Workspac
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n fragment SettingsWorkspacesMembers_Workspace on Workspace {\n id\n role\n team {\n items {\n id\n role\n }\n }\n invitedTeam(filter: $invitesFilter) {\n user {\n id\n }\n }\n }\n"): (typeof documents)["\n fragment SettingsWorkspacesMembers_Workspace on Workspace {\n id\n role\n team {\n items {\n id\n role\n }\n }\n invitedTeam(filter: $invitesFilter) {\n user {\n id\n }\n }\n }\n"];
|
||||
export function graphql(source: "\n fragment SettingsWorkspacesMembers_Workspace on Workspace {\n id\n role\n team {\n items {\n id\n }\n }\n invitedTeam(filter: $invitesFilter) {\n user {\n id\n }\n }\n adminWorkspacesJoinRequests(filter: $joinRequestsFilter) {\n totalCount\n }\n }\n"): (typeof documents)["\n fragment SettingsWorkspacesMembers_Workspace on Workspace {\n id\n role\n team {\n items {\n id\n }\n }\n invitedTeam(filter: $invitesFilter) {\n user {\n id\n }\n }\n adminWorkspacesJoinRequests(filter: $joinRequestsFilter) {\n totalCount\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,11 +1,9 @@
|
||||
import { graphql } from '~~/lib/common/generated/gql'
|
||||
|
||||
export const dashboardJoinWorkspaceMutation = graphql(`
|
||||
mutation DashboardJoinWorkspace($input: JoinWorkspaceInput!) {
|
||||
export const dashboardRequestToJoinWorkspaceMutation = graphql(`
|
||||
mutation DashboardRequestToJoinWorkspace($input: WorkspaceRequestToJoinInput!) {
|
||||
workspaceMutations {
|
||||
join(input: $input) {
|
||||
...WorkspaceInviteDiscoverableWorkspaceBanner_Workspace
|
||||
}
|
||||
requestToJoin(input: $input)
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
@@ -57,12 +57,14 @@ export const settingsWorkspacesMembersQuery = graphql(`
|
||||
query SettingsWorkspacesMembers(
|
||||
$slug: String!
|
||||
$invitesFilter: PendingWorkspaceCollaboratorsFilter
|
||||
$joinRequestsFilter: AdminWorkspaceJoinRequestFilter
|
||||
) {
|
||||
workspaceBySlug(slug: $slug) {
|
||||
...SettingsWorkspacesMembers_Workspace
|
||||
...SettingsWorkspacesMembersMembersTable_Workspace
|
||||
...SettingsWorkspacesMembersGuestsTable_Workspace
|
||||
...SettingsWorkspacesMembersInvitesTable_Workspace
|
||||
...SettingsWorkspacesMembersRequestsTable_Workspace
|
||||
}
|
||||
}
|
||||
`)
|
||||
@@ -81,6 +83,18 @@ export const settingsWorkspacesMembersSearchQuery = graphql(`
|
||||
}
|
||||
`)
|
||||
|
||||
export const settingsWorkspacesJoinRequestsSearchQuery = graphql(`
|
||||
query SettingsWorkspacesJoinRequestsSearch(
|
||||
$slug: String!
|
||||
$joinRequestsFilter: AdminWorkspaceJoinRequestFilter
|
||||
) {
|
||||
workspaceBySlug(slug: $slug) {
|
||||
id
|
||||
...SettingsWorkspacesMembersRequestsTable_Workspace
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
export const settingsWorkspacesInvitesSearchQuery = graphql(`
|
||||
query SettingsWorkspacesInvitesSearch(
|
||||
$slug: String!
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
import { useMutation } from '@vue/apollo-composable'
|
||||
import {
|
||||
approveWorkspaceJoinRequestMutation,
|
||||
denyWorkspaceJoinRequestMutation
|
||||
} from '~/lib/workspaces/graphql/mutations'
|
||||
import type {
|
||||
ApproveWorkspaceJoinRequestInput,
|
||||
DenyWorkspaceJoinRequestInput
|
||||
} from '~~/lib/common/generated/gql/graphql'
|
||||
import { ToastNotificationType, useGlobalToast } from '~~/lib/common/composables/toast'
|
||||
import {
|
||||
convertThrowIntoFetchResult,
|
||||
getFirstErrorMessage,
|
||||
modifyObjectField,
|
||||
getCacheId
|
||||
} from '~~/lib/common/helpers/graphql'
|
||||
|
||||
export const useWorkspaceJoinRequest = () => {
|
||||
const { mutate: approveMutation } = useMutation(approveWorkspaceJoinRequestMutation)
|
||||
const { mutate: denyMutation } = useMutation(denyWorkspaceJoinRequestMutation)
|
||||
const { triggerNotification } = useGlobalToast()
|
||||
|
||||
const approve = async (
|
||||
input: ApproveWorkspaceJoinRequestInput,
|
||||
requestId: string
|
||||
) => {
|
||||
const result = await approveMutation(
|
||||
{ input },
|
||||
{
|
||||
update: (cache) => {
|
||||
cache.evict({
|
||||
id: getCacheId('WorkspaceJoinRequest', requestId)
|
||||
})
|
||||
|
||||
modifyObjectField(
|
||||
cache,
|
||||
getCacheId('Workspace', input.workspaceId),
|
||||
'adminWorkspacesJoinRequests',
|
||||
({ helpers: { createUpdatedValue } }) => {
|
||||
return createUpdatedValue(({ update }) => {
|
||||
update('totalCount', (totalCount) => totalCount - 1)
|
||||
})
|
||||
},
|
||||
{
|
||||
autoEvictFiltered: true
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
).catch(convertThrowIntoFetchResult)
|
||||
|
||||
if (result?.data) {
|
||||
triggerNotification({
|
||||
type: ToastNotificationType.Success,
|
||||
title: 'Workspace join request approved'
|
||||
})
|
||||
} else {
|
||||
const errorMessage = getFirstErrorMessage(result?.errors)
|
||||
triggerNotification({
|
||||
type: ToastNotificationType.Danger,
|
||||
title: 'Workspace join request approval failed',
|
||||
description: errorMessage
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const deny = async (input: DenyWorkspaceJoinRequestInput, requestId: string) => {
|
||||
const result = await denyMutation(
|
||||
{ input },
|
||||
{
|
||||
update: (cache) => {
|
||||
cache.evict({
|
||||
id: getCacheId('WorkspaceJoinRequest', requestId)
|
||||
})
|
||||
|
||||
modifyObjectField(
|
||||
cache,
|
||||
getCacheId('Workspace', input.workspaceId),
|
||||
'adminWorkspacesJoinRequests',
|
||||
({ helpers: { createUpdatedValue } }) => {
|
||||
return createUpdatedValue(({ update }) => {
|
||||
update('totalCount', (totalCount) => totalCount - 1)
|
||||
})
|
||||
},
|
||||
{
|
||||
autoEvictFiltered: true
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
).catch(convertThrowIntoFetchResult)
|
||||
|
||||
if (result?.data) {
|
||||
triggerNotification({
|
||||
type: ToastNotificationType.Success,
|
||||
title: 'Workspace join request denied'
|
||||
})
|
||||
} else {
|
||||
const errorMessage = getFirstErrorMessage(result?.errors)
|
||||
triggerNotification({
|
||||
type: ToastNotificationType.Danger,
|
||||
title: 'Workspace join request denial failed',
|
||||
description: errorMessage
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return { approve, deny }
|
||||
}
|
||||
@@ -105,3 +105,19 @@ export const workspaceUpdateDiscoverabilityMutation = graphql(`
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
export const approveWorkspaceJoinRequestMutation = graphql(`
|
||||
mutation ApproveWorkspaceJoinRequest($input: ApproveWorkspaceJoinRequestInput!) {
|
||||
workspaceJoinRequestMutations {
|
||||
approve(input: $input)
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
export const denyWorkspaceJoinRequestMutation = graphql(`
|
||||
mutation DenyWorkspaceJoinRequest($input: DenyWorkspaceJoinRequestInput!) {
|
||||
workspaceJoinRequestMutations {
|
||||
deny(input: $input)
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
@@ -24,6 +24,11 @@
|
||||
:workspace="workspace"
|
||||
:workspace-slug="slug"
|
||||
/>
|
||||
<SettingsWorkspacesMembersJoinRequestsTable
|
||||
v-if="activeItem.id === 'joinRequests'"
|
||||
:workspace="workspace"
|
||||
:workspace-slug="slug"
|
||||
/>
|
||||
</template>
|
||||
</LayoutTabsHorizontal>
|
||||
</div>
|
||||
@@ -36,6 +41,8 @@ import { useQuery } from '@vue/apollo-composable'
|
||||
import { graphql } from '~/lib/common/generated/gql'
|
||||
import { settingsWorkspacesMembersQuery } from '~/lib/settings/graphql/queries'
|
||||
import type { LayoutPageTabItem } from '~~/lib/layout/helpers/components'
|
||||
import { useOnWorkspaceUpdated } from '~/lib/workspaces/composables/management'
|
||||
import { WorkspaceJoinRequestStatus } from '~/lib/common/generated/gql/graphql'
|
||||
|
||||
graphql(`
|
||||
fragment SettingsWorkspacesMembers_Workspace on Workspace {
|
||||
@@ -44,7 +51,6 @@ graphql(`
|
||||
team {
|
||||
items {
|
||||
id
|
||||
role
|
||||
}
|
||||
}
|
||||
invitedTeam(filter: $invitesFilter) {
|
||||
@@ -52,6 +58,9 @@ graphql(`
|
||||
id
|
||||
}
|
||||
}
|
||||
adminWorkspacesJoinRequests(filter: $joinRequestsFilter) {
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
@@ -63,11 +72,14 @@ useHead({
|
||||
title: 'Settings | Workspace - Members'
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
const slug = computed(() => (route.params.slug as string) || '')
|
||||
|
||||
const route = useRoute()
|
||||
const { result } = useQuery(settingsWorkspacesMembersQuery, () => ({
|
||||
slug: slug.value
|
||||
slug: slug.value,
|
||||
joinRequestsFilter: {
|
||||
status: WorkspaceJoinRequestStatus.Pending
|
||||
}
|
||||
}))
|
||||
|
||||
const workspace = computed(() => result.value?.workspaceBySlug)
|
||||
@@ -83,6 +95,9 @@ const guestCount = computed(
|
||||
.length
|
||||
)
|
||||
const invitedCount = computed(() => workspace.value?.invitedTeam?.length)
|
||||
const joinRequestCount = computed(
|
||||
() => workspace.value?.adminWorkspacesJoinRequests?.totalCount
|
||||
)
|
||||
const tabItems = computed<LayoutPageTabItem[]>(() => [
|
||||
{ title: 'Members', id: 'members', count: memberCount.value },
|
||||
{ title: 'Guests', id: 'guests', count: guestCount.value },
|
||||
@@ -92,8 +107,17 @@ const tabItems = computed<LayoutPageTabItem[]>(() => [
|
||||
disabled: !isAdmin.value,
|
||||
disabledMessage: 'Only workspace admins can manage invites',
|
||||
count: invitedCount.value
|
||||
},
|
||||
{
|
||||
title: 'Join requests',
|
||||
id: 'joinRequests',
|
||||
disabled: !isAdmin.value,
|
||||
disabledMessage: 'Only workspace admins can manage join requests',
|
||||
count: joinRequestCount.value
|
||||
}
|
||||
])
|
||||
|
||||
const activeTab = ref(tabItems.value[0])
|
||||
|
||||
useOnWorkspaceUpdated({ workspaceSlug: slug })
|
||||
</script>
|
||||
|
||||
@@ -123,7 +123,6 @@ import type { ShallowRef } from 'vue'
|
||||
import { useQuery, useMutation } from '@vue/apollo-composable'
|
||||
import { graphql } from '~/lib/common/generated/gql'
|
||||
import type { SettingsWorkspacesSecurityDomainRemoveDialog_WorkspaceDomainFragment } from '~/lib/common/generated/gql/graphql'
|
||||
import { getFirstErrorMessage } from '~/lib/common/helpers/graphql'
|
||||
import { settingsWorkspacesSecurityQuery } from '~/lib/settings/graphql/queries'
|
||||
import { useAddWorkspaceDomain } from '~/lib/settings/composables/management'
|
||||
import { useMixpanel } from '~/lib/core/composables/mp'
|
||||
@@ -170,7 +169,6 @@ const slug = computed(() => (route.params.slug as string) || '')
|
||||
|
||||
const route = useRoute()
|
||||
const addWorkspaceDomain = useAddWorkspaceDomain()
|
||||
const { triggerNotification } = useGlobalToast()
|
||||
const isSsoEnabled = useIsWorkspacesSsoEnabled()
|
||||
const mixpanel = useMixpanel()
|
||||
const { mutate: updateDomainProtection } = useMutation(
|
||||
@@ -226,17 +224,6 @@ const isDomainProtectionEnabled = computed({
|
||||
// eslint-disable-next-line camelcase
|
||||
workspace_id: workspace.value?.id
|
||||
})
|
||||
|
||||
triggerNotification({
|
||||
type: ToastNotificationType.Success,
|
||||
title: `Domain protection ${newVal ? 'enabled' : 'disabled'}`
|
||||
})
|
||||
} else {
|
||||
triggerNotification({
|
||||
type: ToastNotificationType.Danger,
|
||||
title: 'Failed to update',
|
||||
description: getFirstErrorMessage(result?.errors)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -259,17 +246,6 @@ const isDomainDiscoverabilityEnabled = computed({
|
||||
// eslint-disable-next-line camelcase
|
||||
workspace_id: workspace.value?.id
|
||||
})
|
||||
|
||||
triggerNotification({
|
||||
type: ToastNotificationType.Success,
|
||||
title: `Discoverability ${newVal ? 'enabled' : 'disabled'}`
|
||||
})
|
||||
} else {
|
||||
triggerNotification({
|
||||
type: ToastNotificationType.Danger,
|
||||
title: 'Failed to update',
|
||||
description: getFirstErrorMessage(result?.errors)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -6,6 +6,7 @@ import { getUserFactory } from '@/modules/core/repositories/users'
|
||||
import { renderEmail } from '@/modules/emails/services/emailRendering'
|
||||
import { sendEmail } from '@/modules/emails/services/sending'
|
||||
import { commandFactory } from '@/modules/shared/command'
|
||||
import { getEventBus } from '@/modules/shared/services/eventBus'
|
||||
import { getPaginatedItemsFactory } from '@/modules/shared/services/paginatedItems'
|
||||
import {
|
||||
ApproveWorkspaceJoinRequest,
|
||||
@@ -30,6 +31,8 @@ import {
|
||||
import { WorkspaceJoinRequestStatus } from '@/modules/workspacesCore/domain/types'
|
||||
import { WorkspaceJoinRequestGraphQLReturn } from '@/modules/workspacesCore/helpers/graphTypes'
|
||||
|
||||
const eventBus = getEventBus()
|
||||
|
||||
export default {
|
||||
Workspace: {
|
||||
adminWorkspacesJoinRequests: async (parent, args, ctx) => {
|
||||
@@ -78,7 +81,8 @@ export default {
|
||||
approve: async (_parent, args) => {
|
||||
const approveWorkspaceJoinRequest = commandFactory<ApproveWorkspaceJoinRequest>({
|
||||
db,
|
||||
operationFactory: ({ db }) => {
|
||||
eventBus,
|
||||
operationFactory: ({ db, emit }) => {
|
||||
const updateWorkspaceJoinRequestStatus =
|
||||
updateWorkspaceJoinRequestStatusFactory({
|
||||
db
|
||||
@@ -98,7 +102,8 @@ export default {
|
||||
getWorkspaceJoinRequest: getWorkspaceJoinRequestFactory({
|
||||
db
|
||||
}),
|
||||
upsertWorkspaceRole: upsertWorkspaceRoleFactory({ db })
|
||||
upsertWorkspaceRole: upsertWorkspaceRoleFactory({ db }),
|
||||
emit
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -21,6 +21,8 @@ import {
|
||||
import { Roles } from '@speckle/shared'
|
||||
import { FindEmailsByUserId } from '@/modules/core/domain/userEmails/operations'
|
||||
import { userEmailsCompliantWithWorkspaceDomains } from '@/modules/workspaces/domain/logic'
|
||||
import { EventBus } from '@/modules/shared/services/eventBus'
|
||||
import { WorkspaceEvents } from '@/modules/workspacesCore/domain/events'
|
||||
|
||||
export const dismissWorkspaceJoinRequestFactory =
|
||||
({
|
||||
@@ -104,7 +106,8 @@ export const approveWorkspaceJoinRequestFactory =
|
||||
getUserById,
|
||||
getWorkspace,
|
||||
getWorkspaceJoinRequest,
|
||||
upsertWorkspaceRole
|
||||
upsertWorkspaceRole,
|
||||
emit
|
||||
}: {
|
||||
updateWorkspaceJoinRequestStatus: UpdateWorkspaceJoinRequestStatus
|
||||
sendWorkspaceJoinRequestApprovedEmail: SendWorkspaceJoinRequestApprovedEmail
|
||||
@@ -112,6 +115,7 @@ export const approveWorkspaceJoinRequestFactory =
|
||||
getWorkspace: GetWorkspace
|
||||
getWorkspaceJoinRequest: GetWorkspaceJoinRequest
|
||||
upsertWorkspaceRole: UpsertWorkspaceRole
|
||||
emit: EventBus['emit']
|
||||
}) =>
|
||||
async ({ userId, workspaceId }: { userId: string; workspaceId: string }) => {
|
||||
const requester = await getUserById(userId)
|
||||
@@ -142,6 +146,8 @@ export const approveWorkspaceJoinRequestFactory =
|
||||
const role = Roles.Workspace.Member
|
||||
await upsertWorkspaceRole({ userId, workspaceId, role, createdAt: new Date() })
|
||||
|
||||
await emit({ eventName: WorkspaceEvents.Updated, payload: { workspace } })
|
||||
|
||||
await sendWorkspaceJoinRequestApprovedEmail({
|
||||
workspace,
|
||||
requester
|
||||
|
||||
@@ -245,7 +245,8 @@ const { FF_WORKSPACES_MODULE_ENABLED } = getFeatureFlags()
|
||||
getUserById: async () => null,
|
||||
getWorkspace: async () => null,
|
||||
getWorkspaceJoinRequest: async () => undefined,
|
||||
upsertWorkspaceRole: async () => Promise.resolve()
|
||||
upsertWorkspaceRole: async () => Promise.resolve(),
|
||||
emit: async () => Promise.resolve()
|
||||
})({ workspaceId: createRandomString(), userId: createRandomString() })
|
||||
)
|
||||
|
||||
@@ -261,7 +262,8 @@ const { FF_WORKSPACES_MODULE_ENABLED } = getFeatureFlags()
|
||||
getUserById: async () => user as unknown as UserWithOptionalRole,
|
||||
getWorkspace: async () => null,
|
||||
getWorkspaceJoinRequest: async () => undefined,
|
||||
upsertWorkspaceRole: async () => Promise.resolve()
|
||||
upsertWorkspaceRole: async () => Promise.resolve(),
|
||||
emit: async () => Promise.resolve()
|
||||
})({ workspaceId: createRandomString(), userId: createRandomString() })
|
||||
)
|
||||
|
||||
@@ -285,7 +287,8 @@ const { FF_WORKSPACES_MODULE_ENABLED } = getFeatureFlags()
|
||||
getUserById: async () => user as unknown as UserWithOptionalRole,
|
||||
getWorkspace: async () => workspace as unknown as Workspace,
|
||||
getWorkspaceJoinRequest: async () => undefined,
|
||||
upsertWorkspaceRole: async () => Promise.resolve()
|
||||
upsertWorkspaceRole: async () => Promise.resolve(),
|
||||
emit: async () => Promise.resolve()
|
||||
})({ workspaceId: createRandomString(), userId: createRandomString() })
|
||||
)
|
||||
|
||||
@@ -343,7 +346,8 @@ const { FF_WORKSPACES_MODULE_ENABLED } = getFeatureFlags()
|
||||
getUserById: async () => user as unknown as UserWithOptionalRole,
|
||||
getWorkspace: async () => workspace as unknown as Workspace,
|
||||
getWorkspaceJoinRequest: async () => request,
|
||||
upsertWorkspaceRole
|
||||
upsertWorkspaceRole,
|
||||
emit: async () => Promise.resolve()
|
||||
})({ workspaceId: workspace.id, userId: user.id })
|
||||
).to.equal(true)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user