Merge pull request #4328 from specklesystems/andrew/usage-limits-plan-composables
refactor(fe): usage/plan/limits composables
This commit is contained in:
@@ -1,64 +1,68 @@
|
||||
<template>
|
||||
<LayoutDialog v-model:open="open" max-width="sm" :buttons="dialogButtons">
|
||||
<template #header>Move project to workspace</template>
|
||||
<div class="flex flex-col space-y-4">
|
||||
<ProjectsWorkspaceSelect
|
||||
v-if="hasWorkspaces"
|
||||
v-model="selectedWorkspace"
|
||||
:items="workspaces"
|
||||
:disabled-roles="[Roles.Workspace.Member, Roles.Workspace.Guest]"
|
||||
disabled-item-tooltip="Only workspace admins can move projects into a workspace."
|
||||
label="Select a workspace"
|
||||
help="Once a project is moved to a workspace, it cannot be moved out from it."
|
||||
show-label
|
||||
/>
|
||||
<div v-else class="flex flex-col gap-y-2">
|
||||
<p class="text-body-xs text-foreground font-medium">
|
||||
You're not a member of any workspaces.
|
||||
</p>
|
||||
<FormButton :to="workspaceCreateRoute">Create a workspace</FormButton>
|
||||
</div>
|
||||
<div>
|
||||
<LayoutDialog v-model:open="open" max-width="sm" :buttons="dialogButtons">
|
||||
<template #header>Move project to workspace</template>
|
||||
<div class="flex flex-col space-y-4">
|
||||
<template v-if="!workspace">
|
||||
<ProjectsWorkspaceSelect
|
||||
v-if="hasWorkspaces"
|
||||
v-model="selectedWorkspace"
|
||||
:items="workspaces"
|
||||
:disabled-roles="[Roles.Workspace.Member, Roles.Workspace.Guest]"
|
||||
disabled-item-tooltip="Only workspace admins can move projects into a workspace."
|
||||
label="Select a workspace"
|
||||
help="Once a project is moved to a workspace, it cannot be moved out from it."
|
||||
show-label
|
||||
/>
|
||||
<div v-else class="flex flex-col gap-y-2">
|
||||
<p class="text-body-xs text-foreground font-medium">
|
||||
You're not a member of any workspaces.
|
||||
</p>
|
||||
<FormButton :to="workspaceCreateRoute">Learn about workspaces</FormButton>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div v-if="project && selectedWorkspace" class="text-body-xs">
|
||||
<div class="text-body-xs text-foreground flex flex-col gap-y-4">
|
||||
<div class="rounded border bg-foundation-2 border-outline-3 py-2 px-4">
|
||||
<p>
|
||||
Move
|
||||
<span class="font-medium">{{ project.name }}</span>
|
||||
to
|
||||
<span class="font-medium">
|
||||
{{ selectedWorkspace?.name }}
|
||||
<div v-if="project && (selectedWorkspace || workspace)" class="text-body-xs">
|
||||
<div class="text-body-xs text-foreground flex flex-col gap-y-4">
|
||||
<div class="rounded border bg-foundation-2 border-outline-3 py-2 px-4">
|
||||
<p>
|
||||
Move
|
||||
<span class="font-medium">{{ project.name }}</span>
|
||||
to
|
||||
<span class="font-medium">
|
||||
{{ selectedWorkspace?.name ?? workspace?.name }}
|
||||
</span>
|
||||
</p>
|
||||
<p class="text-foreground-3">
|
||||
{{ project.modelCount.totalCount }} {{ modelText }},
|
||||
{{ project.versions.totalCount }} {{ versionsText }}
|
||||
</p>
|
||||
</div>
|
||||
<p class="text-body-2xs text-foreground-2">
|
||||
The project, including models and versions, will be moved to the
|
||||
workspace, where all existing members and admins will have access.
|
||||
<span class="pt-2 block">
|
||||
The project's collaborators will become workspace members and keep their
|
||||
project roles.
|
||||
</span>
|
||||
</p>
|
||||
<p class="text-foreground-3">
|
||||
{{ project.modelCount.totalCount }} {{ modelText }},
|
||||
{{ project.versions.totalCount }} {{ versionsText }}
|
||||
</p>
|
||||
</div>
|
||||
<p class="text-body-2xs text-foreground-2">
|
||||
The project, including models and versions, will be moved to the workspace,
|
||||
where all existing members and admins will have access.
|
||||
<span class="pt-2 block">
|
||||
The project's collaborators will become workspace members and keep their
|
||||
project roles.
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<WorkspaceRegionStaticDataDisclaimer
|
||||
v-if="showRegionStaticDataDisclaimer"
|
||||
v-model:open="showRegionStaticDataDisclaimer"
|
||||
:variant="RegionStaticDataDisclaimerVariant.MoveProjectIntoWorkspace"
|
||||
@confirm="onConfirmHandler"
|
||||
/>
|
||||
<WorkspaceRegionStaticDataDisclaimer
|
||||
v-if="showRegionStaticDataDisclaimer"
|
||||
v-model:open="showRegionStaticDataDisclaimer"
|
||||
:variant="RegionStaticDataDisclaimerVariant.MoveProjectIntoWorkspace"
|
||||
@confirm="onConfirmHandler"
|
||||
/>
|
||||
</LayoutDialog>
|
||||
<WorkspacePlanLimitReachedDialog
|
||||
v-if="activeLimit"
|
||||
v-model:open="showLimitReachedDialog"
|
||||
:limit="activeLimit"
|
||||
:limit-type="limitType"
|
||||
/>
|
||||
</LayoutDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@@ -76,17 +80,15 @@ import {
|
||||
useWorkspaceCustomDataResidencyDisclaimer,
|
||||
RegionStaticDataDisclaimerVariant
|
||||
} from '~/lib/workspaces/composables/region'
|
||||
import { useWorkspacePlanLimits } from '~/lib/workspaces/composables/plan'
|
||||
import { useWorkspaceLimits } from '~/lib/workspaces/composables/limits'
|
||||
|
||||
graphql(`
|
||||
fragment ProjectsMoveToWorkspaceDialog_Workspace on Workspace {
|
||||
id
|
||||
role
|
||||
projectCount: projects(limit: 0) {
|
||||
totalCount
|
||||
}
|
||||
name
|
||||
logo
|
||||
slug
|
||||
...WorkspaceHasCustomDataResidency_Workspace
|
||||
...ProjectsWorkspaceSelect_Workspace
|
||||
}
|
||||
@@ -126,8 +128,10 @@ const query = graphql(`
|
||||
|
||||
const props = defineProps<{
|
||||
project: ProjectsMoveToWorkspaceDialog_ProjectFragment
|
||||
workspace?: ProjectsMoveToWorkspaceDialog_WorkspaceFragment
|
||||
eventSource?: string // Used for mixpanel tracking
|
||||
}>()
|
||||
|
||||
const open = defineModel<boolean>('open', { required: true })
|
||||
|
||||
const isWorkspacesEnabled = useIsWorkspacesEnabled()
|
||||
@@ -138,6 +142,16 @@ const loading = useMutationLoading()
|
||||
const moveProject = useMoveProjectToWorkspace()
|
||||
|
||||
const selectedWorkspace = ref<ProjectsMoveToWorkspaceDialog_WorkspaceFragment>()
|
||||
|
||||
const activeWorkspaceSlug = computed(
|
||||
() => selectedWorkspace.value?.slug || props.workspace?.slug || ''
|
||||
)
|
||||
|
||||
// Get workspace limits
|
||||
const { canAddProject, canAddModels, limits } = useWorkspaceLimits(
|
||||
activeWorkspaceSlug.value
|
||||
)
|
||||
|
||||
const showLimitReachedDialog = ref(false)
|
||||
|
||||
const workspaces = computed(() => result.value?.activeUser?.workspaces.items ?? [])
|
||||
@@ -149,16 +163,23 @@ const versionsText = computed(() =>
|
||||
props.project.versions.totalCount === 1 ? 'version' : 'versions'
|
||||
)
|
||||
|
||||
const modelCount = computed(() => {
|
||||
return props.project.modelCount.totalCount
|
||||
// Determine which limit type is hit
|
||||
const limitType = computed((): 'project' | 'model' | null => {
|
||||
if (!canAddProject.value) return 'project'
|
||||
|
||||
const projectModelCount = props.project.modelCount.totalCount
|
||||
if (!canAddModels(projectModelCount)) return 'model'
|
||||
|
||||
return null
|
||||
})
|
||||
|
||||
const projectCount = computed(() => {
|
||||
return selectedWorkspace.value?.projectCount.totalCount ?? 0
|
||||
// Get the value of the limit that's hit
|
||||
const activeLimit = computed(() => {
|
||||
if (limitType.value === 'project') return limits.value.projectCount ?? 0
|
||||
if (limitType.value === 'model') return limits.value.modelCount ?? 0
|
||||
return 0
|
||||
})
|
||||
|
||||
const { limitType, activeLimit } = useWorkspacePlanLimits(projectCount, modelCount)
|
||||
|
||||
const dialogButtons = computed<LayoutDialogButton[]>(() => {
|
||||
return hasWorkspaces.value
|
||||
? [
|
||||
@@ -173,7 +194,7 @@ const dialogButtons = computed<LayoutDialogButton[]>(() => {
|
||||
text: 'Move',
|
||||
props: {
|
||||
color: 'primary',
|
||||
disabled: !selectedWorkspace.value || loading.value
|
||||
disabled: (!selectedWorkspace.value && !props.workspace) || loading.value
|
||||
},
|
||||
onClick: () => onMoveClick()
|
||||
}
|
||||
@@ -190,8 +211,8 @@ const dialogButtons = computed<LayoutDialogButton[]>(() => {
|
||||
})
|
||||
|
||||
const onMoveProject = async () => {
|
||||
const workspaceId = selectedWorkspace.value?.id
|
||||
const workspaceName = selectedWorkspace.value?.name
|
||||
const workspaceId = selectedWorkspace.value?.id ?? props.workspace?.id
|
||||
const workspaceName = selectedWorkspace.value?.name ?? props.workspace?.name
|
||||
if (!workspaceId || !workspaceName) return
|
||||
|
||||
const res = await moveProject({
|
||||
@@ -207,7 +228,7 @@ const onMoveProject = async () => {
|
||||
|
||||
const { showRegionStaticDataDisclaimer, triggerAction, onConfirmHandler } =
|
||||
useWorkspaceCustomDataResidencyDisclaimer({
|
||||
workspace: computed(() => selectedWorkspace.value),
|
||||
workspace: computed(() => selectedWorkspace.value ?? props.workspace),
|
||||
onConfirmAction: onMoveProject
|
||||
})
|
||||
|
||||
@@ -222,7 +243,11 @@ watch(
|
||||
)
|
||||
|
||||
const onMoveClick = () => {
|
||||
if (limitType.value) {
|
||||
const projectModelCount = props.project.modelCount.totalCount
|
||||
|
||||
// Check if we can add this project to the workspace
|
||||
if (!canAddProject.value || !canAddModels(projectModelCount)) {
|
||||
open.value = false
|
||||
showLimitReachedDialog.value = true
|
||||
} else {
|
||||
triggerAction()
|
||||
|
||||
@@ -18,9 +18,15 @@
|
||||
/>
|
||||
<div class="text-body-2xs py-2">
|
||||
You can move up to
|
||||
<span class="font-medium">{{ remainingProjects }} projects</span>
|
||||
<span class="font-medium">
|
||||
{{ Math.max(0, remainingProjectCount) }}
|
||||
{{ remainingProjectCount === 1 ? 'project' : 'projects' }}
|
||||
</span>
|
||||
and
|
||||
<span class="font-medium">{{ remainingModels }} models</span>
|
||||
<span class="font-medium">
|
||||
{{ Math.max(0, remainingModelCount) }}
|
||||
{{ remainingModelCount === 1 ? 'model' : 'models' }}
|
||||
</span>
|
||||
in total.
|
||||
</div>
|
||||
<div
|
||||
@@ -67,12 +73,6 @@
|
||||
:project="selectedProject"
|
||||
event-source="move-projects-dialog"
|
||||
/>
|
||||
<WorkspacePlanLimitReachedDialog
|
||||
v-if="activeLimit"
|
||||
v-model:open="showLimitReachedDialog"
|
||||
:limit="activeLimit"
|
||||
:limit-type="limitType"
|
||||
/>
|
||||
</LayoutDialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
@@ -89,10 +89,7 @@ import type {
|
||||
import { usePaginatedQuery } from '~/lib/common/composables/graphql'
|
||||
import { moveProjectsDialogQuery } from '~~/lib/workspaces/graphql/queries'
|
||||
import { Roles } from '@speckle/shared'
|
||||
import {
|
||||
useWorkspacePlanLimits,
|
||||
useGetWorkspacePlanUsage
|
||||
} from '~/lib/workspaces/composables/plan'
|
||||
import { useWorkspaceLimits } from '~/lib/workspaces/composables/limits'
|
||||
|
||||
graphql(`
|
||||
fragment MoveProjectsDialog_Workspace on Workspace {
|
||||
@@ -101,12 +98,6 @@ graphql(`
|
||||
projects {
|
||||
items {
|
||||
id
|
||||
modelCount: models(limit: 0) {
|
||||
totalCount
|
||||
}
|
||||
versions(limit: 0) {
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -161,12 +152,10 @@ const {
|
||||
|
||||
const selectedProject = ref<ProjectsMoveToWorkspaceDialog_ProjectFragment | null>(null)
|
||||
const showMoveToWorkspaceDialog = ref(false)
|
||||
const showLimitReachedDialog = ref(false)
|
||||
|
||||
const { projectCount, modelCount } = useGetWorkspacePlanUsage(props.workspace.slug)
|
||||
|
||||
const { remainingProjects, remainingModels, limitType, activeLimit } =
|
||||
useWorkspacePlanLimits(projectCount, modelCount)
|
||||
const { remainingModelCount, remainingProjectCount } = useWorkspaceLimits(
|
||||
props.workspace.slug
|
||||
)
|
||||
|
||||
const workspaceProjects = computed(() =>
|
||||
props.workspace.projects.items.map((project) => project.id)
|
||||
@@ -177,6 +166,7 @@ const moveableProjects = computed(() =>
|
||||
userProjects.value.filter((project) => !workspaceProjects.value.includes(project.id))
|
||||
)
|
||||
const hasMoveableProjects = computed(() => moveableProjects.value.length > 0)
|
||||
|
||||
const buttons = computed((): LayoutDialogButton[] => [
|
||||
{
|
||||
text: 'Done',
|
||||
@@ -189,10 +179,6 @@ const buttons = computed((): LayoutDialogButton[] => [
|
||||
|
||||
const onMoveClick = (project: ProjectsMoveToWorkspaceDialog_ProjectFragment) => {
|
||||
selectedProject.value = project
|
||||
if (!limitType.value) {
|
||||
showMoveToWorkspaceDialog.value = true
|
||||
} else {
|
||||
showLimitReachedDialog.value = true
|
||||
}
|
||||
showMoveToWorkspaceDialog.value = true
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -105,7 +105,6 @@ graphql(`
|
||||
...WorkspaceTeam_Workspace
|
||||
...WorkspaceSecurity_Workspace
|
||||
...BillingAlert_Workspace
|
||||
...MoveProjectsDialog_Workspace
|
||||
...InviteDialogWorkspace_Workspace
|
||||
projects {
|
||||
...WorkspaceProjectList_ProjectCollection
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
<div class="flex flex-col justify-between h-full px-5 py-4">
|
||||
<NuxtImg src="/images/logo.png" alt="Speckle logo" class="h-8 w-8" />
|
||||
<h3 class="text-white limit-reached-text-shadow text-base">
|
||||
Plan limit reached.
|
||||
<span class="capitalize">{{ props.limitType }}</span>
|
||||
limit reached.
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
@@ -46,7 +47,7 @@ import { settingsWorkspaceRoutes } from '~/lib/common/helpers/route'
|
||||
const isOpen = defineModel<boolean>('open', { required: true })
|
||||
|
||||
const props = defineProps<{
|
||||
limit: number
|
||||
limit: Nullable<number>
|
||||
limitType: Nullable<'project' | 'model'>
|
||||
}>()
|
||||
</script>
|
||||
|
||||
@@ -101,7 +101,7 @@ type Documents = {
|
||||
"\n fragment ProjectsDashboardFilledUser on UserProjectCollection {\n items {\n ...ProjectDashboardItem\n }\n }\n": typeof types.ProjectsDashboardFilledUserFragmentDoc,
|
||||
"\n fragment ProjectsDeleteDialog_Project on Project {\n id\n name\n role\n models(limit: 0) {\n totalCount\n }\n workspace {\n slug\n id\n }\n versions(limit: 0) {\n totalCount\n }\n }\n": typeof types.ProjectsDeleteDialog_ProjectFragmentDoc,
|
||||
"\n fragment ProjectsHiddenProjectWarning_User on User {\n id\n expiredSsoSessions {\n id\n slug\n name\n logo\n }\n }\n": typeof types.ProjectsHiddenProjectWarning_UserFragmentDoc,
|
||||
"\n fragment ProjectsMoveToWorkspaceDialog_Workspace on Workspace {\n id\n role\n projectCount: projects(limit: 0) {\n totalCount\n }\n name\n logo\n ...WorkspaceHasCustomDataResidency_Workspace\n ...ProjectsWorkspaceSelect_Workspace\n }\n": typeof types.ProjectsMoveToWorkspaceDialog_WorkspaceFragmentDoc,
|
||||
"\n fragment ProjectsMoveToWorkspaceDialog_Workspace on Workspace {\n id\n role\n name\n logo\n slug\n ...WorkspaceHasCustomDataResidency_Workspace\n ...ProjectsWorkspaceSelect_Workspace\n }\n": typeof types.ProjectsMoveToWorkspaceDialog_WorkspaceFragmentDoc,
|
||||
"\n fragment ProjectsMoveToWorkspaceDialog_User on User {\n workspaces {\n items {\n ...ProjectsMoveToWorkspaceDialog_Workspace\n }\n }\n }\n": typeof types.ProjectsMoveToWorkspaceDialog_UserFragmentDoc,
|
||||
"\n fragment ProjectsMoveToWorkspaceDialog_Project on Project {\n id\n name\n modelCount: models(limit: 0) {\n totalCount\n }\n versions(limit: 0) {\n totalCount\n }\n }\n": typeof types.ProjectsMoveToWorkspaceDialog_ProjectFragmentDoc,
|
||||
"\n query ProjectsMoveToWorkspaceDialog {\n activeUser {\n id\n ...ProjectsMoveToWorkspaceDialog_User\n }\n }\n": typeof types.ProjectsMoveToWorkspaceDialogDocument,
|
||||
@@ -136,9 +136,9 @@ type Documents = {
|
||||
"\n fragment ThreadCommentAttachment on Comment {\n text {\n attachments {\n id\n fileName\n fileType\n fileSize\n }\n }\n }\n": typeof types.ThreadCommentAttachmentFragmentDoc,
|
||||
"\n fragment ViewerCommentsListItem on Comment {\n id\n rawText\n archived\n author {\n ...LimitedUserAvatar\n }\n createdAt\n viewedAt\n replies {\n totalCount\n cursor\n items {\n ...ViewerCommentsReplyItem\n }\n }\n replyAuthors(limit: 4) {\n totalCount\n items {\n ...FormUsersSelectItem\n }\n }\n resources {\n resourceId\n resourceType\n }\n }\n": typeof types.ViewerCommentsListItemFragmentDoc,
|
||||
"\n fragment ViewerModelVersionCardItem on Version {\n id\n message\n referencedObject\n sourceApplication\n createdAt\n previewUrl\n authorUser {\n ...LimitedUserAvatar\n }\n }\n": typeof types.ViewerModelVersionCardItemFragmentDoc,
|
||||
"\n fragment MoveProjectsDialog_Workspace on Workspace {\n id\n ...ProjectsMoveToWorkspaceDialog_Workspace\n projects {\n items {\n id\n modelCount: models(limit: 0) {\n totalCount\n }\n versions(limit: 0) {\n totalCount\n }\n }\n }\n }\n": typeof types.MoveProjectsDialog_WorkspaceFragmentDoc,
|
||||
"\n fragment MoveProjectsDialog_Workspace on Workspace {\n id\n ...ProjectsMoveToWorkspaceDialog_Workspace\n projects {\n items {\n id\n }\n }\n }\n": typeof types.MoveProjectsDialog_WorkspaceFragmentDoc,
|
||||
"\n fragment MoveProjectsDialog_User on User {\n projects(cursor: $cursor, filter: $filter, limit: 10) {\n totalCount\n cursor\n items {\n ...ProjectsMoveToWorkspaceDialog_Project\n role\n workspace {\n id\n }\n }\n }\n }\n": typeof types.MoveProjectsDialog_UserFragmentDoc,
|
||||
"\n fragment WorkspaceProjectList_Workspace on Workspace {\n id\n ...WorkspaceBase_Workspace\n ...WorkspaceTeam_Workspace\n ...WorkspaceSecurity_Workspace\n ...BillingAlert_Workspace\n ...MoveProjectsDialog_Workspace\n ...InviteDialogWorkspace_Workspace\n projects {\n ...WorkspaceProjectList_ProjectCollection\n }\n creationState {\n completed\n state\n }\n readOnly\n }\n": typeof types.WorkspaceProjectList_WorkspaceFragmentDoc,
|
||||
"\n fragment WorkspaceProjectList_Workspace on Workspace {\n id\n ...WorkspaceBase_Workspace\n ...WorkspaceTeam_Workspace\n ...WorkspaceSecurity_Workspace\n ...BillingAlert_Workspace\n ...InviteDialogWorkspace_Workspace\n projects {\n ...WorkspaceProjectList_ProjectCollection\n }\n creationState {\n completed\n state\n }\n readOnly\n }\n": typeof types.WorkspaceProjectList_WorkspaceFragmentDoc,
|
||||
"\n fragment WorkspaceProjectList_ProjectCollection on ProjectCollection {\n totalCount\n items {\n ...ProjectDashboardItem\n }\n cursor\n }\n": typeof types.WorkspaceProjectList_ProjectCollectionFragmentDoc,
|
||||
"\n fragment WorkspaceHeader_Workspace on Workspace {\n ...WorkspaceBase_Workspace\n ...WorkspaceTeam_Workspace\n ...BillingAlert_Workspace\n slug\n readOnly\n }\n": typeof 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": typeof types.WorkspaceInviteBanner_PendingWorkspaceCollaboratorFragmentDoc,
|
||||
@@ -349,14 +349,15 @@ type Documents = {
|
||||
"\n fragment LinkableComment on Comment {\n id\n viewerResources {\n modelId\n versionId\n objectId\n }\n }\n": typeof types.LinkableCommentFragmentDoc,
|
||||
"\n fragment DiscoverableList_Discoverable on User {\n discoverableWorkspaces {\n id\n name\n logo\n description\n slug\n team {\n totalCount\n items {\n avatar\n }\n }\n }\n }\n": typeof types.DiscoverableList_DiscoverableFragmentDoc,
|
||||
"\n fragment DiscoverableList_Requests on User {\n workspaceJoinRequests {\n items {\n id\n status\n workspace {\n id\n name\n logo\n slug\n team {\n totalCount\n items {\n avatar\n }\n }\n }\n }\n }\n }\n": typeof types.DiscoverableList_RequestsFragmentDoc,
|
||||
"\n fragment WorkspacePlanLimits_Workspace on Workspace {\n id\n plan {\n name\n }\n }\n": typeof types.WorkspacePlanLimits_WorkspaceFragmentDoc,
|
||||
"\n fragment UseWorkspaceInviteManager_PendingWorkspaceCollaborator on PendingWorkspaceCollaborator {\n id\n token\n workspaceId\n workspaceSlug\n user {\n id\n }\n }\n": typeof types.UseWorkspaceInviteManager_PendingWorkspaceCollaboratorFragmentDoc,
|
||||
"\n fragment WorkspacesPlan_Workspace on Workspace {\n id\n plan {\n status\n createdAt\n name\n paymentMethod\n usage {\n projectCount\n modelCount\n }\n }\n subscription {\n billingInterval\n currentBillingCycleEnd\n seats {\n editors {\n assigned\n available\n }\n viewers {\n assigned\n available\n }\n }\n }\n }\n": typeof types.WorkspacesPlan_WorkspaceFragmentDoc,
|
||||
"\n fragment WorkspacePlanLimits_Workspace on Workspace {\n id\n projects(limit: 0) {\n totalCount\n items {\n id\n models(limit: 0) {\n totalCount\n }\n }\n }\n plan {\n name\n }\n }\n": typeof types.WorkspacePlanLimits_WorkspaceFragmentDoc,
|
||||
"\n fragment WorkspacesPlan_Workspace on Workspace {\n id\n plan {\n status\n createdAt\n name\n paymentMethod\n usage {\n projectCount\n modelCount\n }\n }\n subscription {\n billingInterval\n currentBillingCycleEnd\n seats {\n editors {\n available\n assigned\n }\n viewers {\n available\n assigned\n }\n }\n }\n }\n": typeof types.WorkspacesPlan_WorkspaceFragmentDoc,
|
||||
"\n subscription OnWorkspaceProjectsUpdate($slug: String!) {\n workspaceProjectsUpdated(workspaceId: null, workspaceSlug: $slug) {\n projectId\n workspaceId\n type\n project {\n ...ProjectDashboardItem\n }\n }\n }\n ": typeof types.OnWorkspaceProjectsUpdateDocument,
|
||||
"\n fragment WorkspaceHasCustomDataResidency_Workspace on Workspace {\n id\n defaultRegion {\n id\n name\n }\n }\n": typeof types.WorkspaceHasCustomDataResidency_WorkspaceFragmentDoc,
|
||||
"\n query CheckProjectWorkspaceDataResidency($projectId: String!) {\n project(id: $projectId) {\n id\n workspace {\n ...WorkspaceHasCustomDataResidency_Workspace\n }\n }\n }\n": typeof types.CheckProjectWorkspaceDataResidencyDocument,
|
||||
"\n fragment WorkspaceSsoStatus_Workspace on Workspace {\n id\n sso {\n provider {\n id\n name\n clientId\n issuerUrl\n }\n session {\n validUntil\n }\n }\n }\n ": typeof types.WorkspaceSsoStatus_WorkspaceFragmentDoc,
|
||||
"\n fragment WorkspaceSsoStatus_User on User {\n expiredSsoSessions {\n id\n slug\n }\n }\n ": typeof types.WorkspaceSsoStatus_UserFragmentDoc,
|
||||
"\n fragment WorkspaceUsage_Workspace on Workspace {\n id\n plan {\n usage {\n projectCount\n modelCount\n }\n }\n }\n": typeof types.WorkspaceUsage_WorkspaceFragmentDoc,
|
||||
"\n fragment WorkspaceBase_Workspace on Workspace {\n id\n name\n slug\n role\n description\n logo\n plan {\n status\n createdAt\n }\n }\n": typeof types.WorkspaceBase_WorkspaceFragmentDoc,
|
||||
"\n fragment WorkspaceDashboardAbout_Workspace on Workspace {\n id\n name\n description\n }\n": typeof types.WorkspaceDashboardAbout_WorkspaceFragmentDoc,
|
||||
"\n fragment WorkspaceInvitedTeam_Workspace on Workspace {\n id\n invitedTeam(filter: $invitesFilter) {\n id\n role\n email\n }\n }\n": typeof types.WorkspaceInvitedTeam_WorkspaceFragmentDoc,
|
||||
@@ -392,7 +393,8 @@ type Documents = {
|
||||
"\n query DiscoverableWorkspacesRequests {\n activeUser {\n id\n ...DiscoverableList_Requests\n }\n }\n": typeof types.DiscoverableWorkspacesRequestsDocument,
|
||||
"\n query WorkspacePlan($slug: String!) {\n workspaceBySlug(slug: $slug) {\n ...WorkspacesPlan_Workspace\n }\n }\n": typeof types.WorkspacePlanDocument,
|
||||
"\n query WorkspaceLastAdminCheck($slug: String!) {\n workspaceBySlug(slug: $slug) {\n ...WorkspaceLastAdminCheck_Workspace\n }\n }\n": typeof types.WorkspaceLastAdminCheckDocument,
|
||||
"\n query WorkspacePlanLimits($slug: String!) {\n workspaceBySlug(slug: $slug) {\n ...WorkspacePlanLimits_Workspace\n }\n }\n": typeof types.WorkspacePlanLimitsDocument,
|
||||
"\n query WorkspaceLimits($slug: String!) {\n workspaceBySlug(slug: $slug) {\n ...WorkspacePlanLimits_Workspace\n }\n }\n": typeof types.WorkspaceLimitsDocument,
|
||||
"\n query WorkspaceUsage($slug: String!) {\n workspaceBySlug(slug: $slug) {\n ...WorkspaceUsage_Workspace\n }\n }\n": typeof types.WorkspaceUsageDocument,
|
||||
"\n subscription onWorkspaceUpdated(\n $workspaceId: String\n $workspaceSlug: String\n $invitesFilter: PendingWorkspaceCollaboratorsFilter\n ) {\n workspaceUpdated(workspaceId: $workspaceId, workspaceSlug: $workspaceSlug) {\n id\n workspace {\n id\n ...WorkspaceProjectList_Workspace\n }\n }\n }\n": typeof types.OnWorkspaceUpdatedDocument,
|
||||
"\n query LegacyBranchRedirectMetadata($streamId: String!, $branchName: String!) {\n project(id: $streamId) {\n modelByName(name: $branchName) {\n id\n }\n }\n }\n": typeof types.LegacyBranchRedirectMetadataDocument,
|
||||
"\n query LegacyViewerCommitRedirectMetadata($streamId: String!, $commitId: String!) {\n project(id: $streamId) {\n version(id: $commitId) {\n id\n model {\n id\n }\n }\n }\n }\n": typeof types.LegacyViewerCommitRedirectMetadataDocument,
|
||||
@@ -503,7 +505,7 @@ const documents: Documents = {
|
||||
"\n fragment ProjectsDashboardFilledUser on UserProjectCollection {\n items {\n ...ProjectDashboardItem\n }\n }\n": types.ProjectsDashboardFilledUserFragmentDoc,
|
||||
"\n fragment ProjectsDeleteDialog_Project on Project {\n id\n name\n role\n models(limit: 0) {\n totalCount\n }\n workspace {\n slug\n id\n }\n versions(limit: 0) {\n totalCount\n }\n }\n": types.ProjectsDeleteDialog_ProjectFragmentDoc,
|
||||
"\n fragment ProjectsHiddenProjectWarning_User on User {\n id\n expiredSsoSessions {\n id\n slug\n name\n logo\n }\n }\n": types.ProjectsHiddenProjectWarning_UserFragmentDoc,
|
||||
"\n fragment ProjectsMoveToWorkspaceDialog_Workspace on Workspace {\n id\n role\n projectCount: projects(limit: 0) {\n totalCount\n }\n name\n logo\n ...WorkspaceHasCustomDataResidency_Workspace\n ...ProjectsWorkspaceSelect_Workspace\n }\n": types.ProjectsMoveToWorkspaceDialog_WorkspaceFragmentDoc,
|
||||
"\n fragment ProjectsMoveToWorkspaceDialog_Workspace on Workspace {\n id\n role\n name\n logo\n slug\n ...WorkspaceHasCustomDataResidency_Workspace\n ...ProjectsWorkspaceSelect_Workspace\n }\n": types.ProjectsMoveToWorkspaceDialog_WorkspaceFragmentDoc,
|
||||
"\n fragment ProjectsMoveToWorkspaceDialog_User on User {\n workspaces {\n items {\n ...ProjectsMoveToWorkspaceDialog_Workspace\n }\n }\n }\n": types.ProjectsMoveToWorkspaceDialog_UserFragmentDoc,
|
||||
"\n fragment ProjectsMoveToWorkspaceDialog_Project on Project {\n id\n name\n modelCount: models(limit: 0) {\n totalCount\n }\n versions(limit: 0) {\n totalCount\n }\n }\n": types.ProjectsMoveToWorkspaceDialog_ProjectFragmentDoc,
|
||||
"\n query ProjectsMoveToWorkspaceDialog {\n activeUser {\n id\n ...ProjectsMoveToWorkspaceDialog_User\n }\n }\n": types.ProjectsMoveToWorkspaceDialogDocument,
|
||||
@@ -538,9 +540,9 @@ const documents: Documents = {
|
||||
"\n fragment ThreadCommentAttachment on Comment {\n text {\n attachments {\n id\n fileName\n fileType\n fileSize\n }\n }\n }\n": types.ThreadCommentAttachmentFragmentDoc,
|
||||
"\n fragment ViewerCommentsListItem on Comment {\n id\n rawText\n archived\n author {\n ...LimitedUserAvatar\n }\n createdAt\n viewedAt\n replies {\n totalCount\n cursor\n items {\n ...ViewerCommentsReplyItem\n }\n }\n replyAuthors(limit: 4) {\n totalCount\n items {\n ...FormUsersSelectItem\n }\n }\n resources {\n resourceId\n resourceType\n }\n }\n": types.ViewerCommentsListItemFragmentDoc,
|
||||
"\n fragment ViewerModelVersionCardItem on Version {\n id\n message\n referencedObject\n sourceApplication\n createdAt\n previewUrl\n authorUser {\n ...LimitedUserAvatar\n }\n }\n": types.ViewerModelVersionCardItemFragmentDoc,
|
||||
"\n fragment MoveProjectsDialog_Workspace on Workspace {\n id\n ...ProjectsMoveToWorkspaceDialog_Workspace\n projects {\n items {\n id\n modelCount: models(limit: 0) {\n totalCount\n }\n versions(limit: 0) {\n totalCount\n }\n }\n }\n }\n": types.MoveProjectsDialog_WorkspaceFragmentDoc,
|
||||
"\n fragment MoveProjectsDialog_Workspace on Workspace {\n id\n ...ProjectsMoveToWorkspaceDialog_Workspace\n projects {\n items {\n id\n }\n }\n }\n": types.MoveProjectsDialog_WorkspaceFragmentDoc,
|
||||
"\n fragment MoveProjectsDialog_User on User {\n projects(cursor: $cursor, filter: $filter, limit: 10) {\n totalCount\n cursor\n items {\n ...ProjectsMoveToWorkspaceDialog_Project\n role\n workspace {\n id\n }\n }\n }\n }\n": types.MoveProjectsDialog_UserFragmentDoc,
|
||||
"\n fragment WorkspaceProjectList_Workspace on Workspace {\n id\n ...WorkspaceBase_Workspace\n ...WorkspaceTeam_Workspace\n ...WorkspaceSecurity_Workspace\n ...BillingAlert_Workspace\n ...MoveProjectsDialog_Workspace\n ...InviteDialogWorkspace_Workspace\n projects {\n ...WorkspaceProjectList_ProjectCollection\n }\n creationState {\n completed\n state\n }\n readOnly\n }\n": types.WorkspaceProjectList_WorkspaceFragmentDoc,
|
||||
"\n fragment WorkspaceProjectList_Workspace on Workspace {\n id\n ...WorkspaceBase_Workspace\n ...WorkspaceTeam_Workspace\n ...WorkspaceSecurity_Workspace\n ...BillingAlert_Workspace\n ...InviteDialogWorkspace_Workspace\n projects {\n ...WorkspaceProjectList_ProjectCollection\n }\n creationState {\n completed\n state\n }\n readOnly\n }\n": types.WorkspaceProjectList_WorkspaceFragmentDoc,
|
||||
"\n fragment WorkspaceProjectList_ProjectCollection on ProjectCollection {\n totalCount\n items {\n ...ProjectDashboardItem\n }\n cursor\n }\n": types.WorkspaceProjectList_ProjectCollectionFragmentDoc,
|
||||
"\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,
|
||||
@@ -751,14 +753,15 @@ const documents: Documents = {
|
||||
"\n fragment LinkableComment on Comment {\n id\n viewerResources {\n modelId\n versionId\n objectId\n }\n }\n": types.LinkableCommentFragmentDoc,
|
||||
"\n fragment DiscoverableList_Discoverable on User {\n discoverableWorkspaces {\n id\n name\n logo\n description\n slug\n team {\n totalCount\n items {\n avatar\n }\n }\n }\n }\n": types.DiscoverableList_DiscoverableFragmentDoc,
|
||||
"\n fragment DiscoverableList_Requests on User {\n workspaceJoinRequests {\n items {\n id\n status\n workspace {\n id\n name\n logo\n slug\n team {\n totalCount\n items {\n avatar\n }\n }\n }\n }\n }\n }\n": types.DiscoverableList_RequestsFragmentDoc,
|
||||
"\n fragment WorkspacePlanLimits_Workspace on Workspace {\n id\n plan {\n name\n }\n }\n": types.WorkspacePlanLimits_WorkspaceFragmentDoc,
|
||||
"\n fragment UseWorkspaceInviteManager_PendingWorkspaceCollaborator on PendingWorkspaceCollaborator {\n id\n token\n workspaceId\n workspaceSlug\n user {\n id\n }\n }\n": types.UseWorkspaceInviteManager_PendingWorkspaceCollaboratorFragmentDoc,
|
||||
"\n fragment WorkspacesPlan_Workspace on Workspace {\n id\n plan {\n status\n createdAt\n name\n paymentMethod\n usage {\n projectCount\n modelCount\n }\n }\n subscription {\n billingInterval\n currentBillingCycleEnd\n seats {\n editors {\n assigned\n available\n }\n viewers {\n assigned\n available\n }\n }\n }\n }\n": types.WorkspacesPlan_WorkspaceFragmentDoc,
|
||||
"\n fragment WorkspacePlanLimits_Workspace on Workspace {\n id\n projects(limit: 0) {\n totalCount\n items {\n id\n models(limit: 0) {\n totalCount\n }\n }\n }\n plan {\n name\n }\n }\n": types.WorkspacePlanLimits_WorkspaceFragmentDoc,
|
||||
"\n fragment WorkspacesPlan_Workspace on Workspace {\n id\n plan {\n status\n createdAt\n name\n paymentMethod\n usage {\n projectCount\n modelCount\n }\n }\n subscription {\n billingInterval\n currentBillingCycleEnd\n seats {\n editors {\n available\n assigned\n }\n viewers {\n available\n assigned\n }\n }\n }\n }\n": types.WorkspacesPlan_WorkspaceFragmentDoc,
|
||||
"\n subscription OnWorkspaceProjectsUpdate($slug: String!) {\n workspaceProjectsUpdated(workspaceId: null, workspaceSlug: $slug) {\n projectId\n workspaceId\n type\n project {\n ...ProjectDashboardItem\n }\n }\n }\n ": types.OnWorkspaceProjectsUpdateDocument,
|
||||
"\n fragment WorkspaceHasCustomDataResidency_Workspace on Workspace {\n id\n defaultRegion {\n id\n name\n }\n }\n": types.WorkspaceHasCustomDataResidency_WorkspaceFragmentDoc,
|
||||
"\n query CheckProjectWorkspaceDataResidency($projectId: String!) {\n project(id: $projectId) {\n id\n workspace {\n ...WorkspaceHasCustomDataResidency_Workspace\n }\n }\n }\n": types.CheckProjectWorkspaceDataResidencyDocument,
|
||||
"\n fragment WorkspaceSsoStatus_Workspace on Workspace {\n id\n sso {\n provider {\n id\n name\n clientId\n issuerUrl\n }\n session {\n validUntil\n }\n }\n }\n ": types.WorkspaceSsoStatus_WorkspaceFragmentDoc,
|
||||
"\n fragment WorkspaceSsoStatus_User on User {\n expiredSsoSessions {\n id\n slug\n }\n }\n ": types.WorkspaceSsoStatus_UserFragmentDoc,
|
||||
"\n fragment WorkspaceUsage_Workspace on Workspace {\n id\n plan {\n usage {\n projectCount\n modelCount\n }\n }\n }\n": types.WorkspaceUsage_WorkspaceFragmentDoc,
|
||||
"\n fragment WorkspaceBase_Workspace on Workspace {\n id\n name\n slug\n role\n description\n logo\n plan {\n status\n createdAt\n }\n }\n": types.WorkspaceBase_WorkspaceFragmentDoc,
|
||||
"\n fragment WorkspaceDashboardAbout_Workspace on Workspace {\n id\n name\n description\n }\n": types.WorkspaceDashboardAbout_WorkspaceFragmentDoc,
|
||||
"\n fragment WorkspaceInvitedTeam_Workspace on Workspace {\n id\n invitedTeam(filter: $invitesFilter) {\n id\n role\n email\n }\n }\n": types.WorkspaceInvitedTeam_WorkspaceFragmentDoc,
|
||||
@@ -794,7 +797,8 @@ const documents: Documents = {
|
||||
"\n query DiscoverableWorkspacesRequests {\n activeUser {\n id\n ...DiscoverableList_Requests\n }\n }\n": types.DiscoverableWorkspacesRequestsDocument,
|
||||
"\n query WorkspacePlan($slug: String!) {\n workspaceBySlug(slug: $slug) {\n ...WorkspacesPlan_Workspace\n }\n }\n": types.WorkspacePlanDocument,
|
||||
"\n query WorkspaceLastAdminCheck($slug: String!) {\n workspaceBySlug(slug: $slug) {\n ...WorkspaceLastAdminCheck_Workspace\n }\n }\n": types.WorkspaceLastAdminCheckDocument,
|
||||
"\n query WorkspacePlanLimits($slug: String!) {\n workspaceBySlug(slug: $slug) {\n ...WorkspacePlanLimits_Workspace\n }\n }\n": types.WorkspacePlanLimitsDocument,
|
||||
"\n query WorkspaceLimits($slug: String!) {\n workspaceBySlug(slug: $slug) {\n ...WorkspacePlanLimits_Workspace\n }\n }\n": types.WorkspaceLimitsDocument,
|
||||
"\n query WorkspaceUsage($slug: String!) {\n workspaceBySlug(slug: $slug) {\n ...WorkspaceUsage_Workspace\n }\n }\n": types.WorkspaceUsageDocument,
|
||||
"\n subscription onWorkspaceUpdated(\n $workspaceId: String\n $workspaceSlug: String\n $invitesFilter: PendingWorkspaceCollaboratorsFilter\n ) {\n workspaceUpdated(workspaceId: $workspaceId, workspaceSlug: $workspaceSlug) {\n id\n workspace {\n id\n ...WorkspaceProjectList_Workspace\n }\n }\n }\n": types.OnWorkspaceUpdatedDocument,
|
||||
"\n query LegacyBranchRedirectMetadata($streamId: String!, $branchName: String!) {\n project(id: $streamId) {\n modelByName(name: $branchName) {\n id\n }\n }\n }\n": types.LegacyBranchRedirectMetadataDocument,
|
||||
"\n query LegacyViewerCommitRedirectMetadata($streamId: String!, $commitId: String!) {\n project(id: $streamId) {\n version(id: $commitId) {\n id\n model {\n id\n }\n }\n }\n }\n": types.LegacyViewerCommitRedirectMetadataDocument,
|
||||
@@ -1183,7 +1187,7 @@ export function graphql(source: "\n fragment ProjectsHiddenProjectWarning_User
|
||||
/**
|
||||
* 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 ProjectsMoveToWorkspaceDialog_Workspace on Workspace {\n id\n role\n projectCount: projects(limit: 0) {\n totalCount\n }\n name\n logo\n ...WorkspaceHasCustomDataResidency_Workspace\n ...ProjectsWorkspaceSelect_Workspace\n }\n"): (typeof documents)["\n fragment ProjectsMoveToWorkspaceDialog_Workspace on Workspace {\n id\n role\n projectCount: projects(limit: 0) {\n totalCount\n }\n name\n logo\n ...WorkspaceHasCustomDataResidency_Workspace\n ...ProjectsWorkspaceSelect_Workspace\n }\n"];
|
||||
export function graphql(source: "\n fragment ProjectsMoveToWorkspaceDialog_Workspace on Workspace {\n id\n role\n name\n logo\n slug\n ...WorkspaceHasCustomDataResidency_Workspace\n ...ProjectsWorkspaceSelect_Workspace\n }\n"): (typeof documents)["\n fragment ProjectsMoveToWorkspaceDialog_Workspace on Workspace {\n id\n role\n name\n logo\n slug\n ...WorkspaceHasCustomDataResidency_Workspace\n ...ProjectsWorkspaceSelect_Workspace\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@@ -1323,7 +1327,7 @@ export function graphql(source: "\n fragment ViewerModelVersionCardItem on Vers
|
||||
/**
|
||||
* 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 MoveProjectsDialog_Workspace on Workspace {\n id\n ...ProjectsMoveToWorkspaceDialog_Workspace\n projects {\n items {\n id\n modelCount: models(limit: 0) {\n totalCount\n }\n versions(limit: 0) {\n totalCount\n }\n }\n }\n }\n"): (typeof documents)["\n fragment MoveProjectsDialog_Workspace on Workspace {\n id\n ...ProjectsMoveToWorkspaceDialog_Workspace\n projects {\n items {\n id\n modelCount: models(limit: 0) {\n totalCount\n }\n versions(limit: 0) {\n totalCount\n }\n }\n }\n }\n"];
|
||||
export function graphql(source: "\n fragment MoveProjectsDialog_Workspace on Workspace {\n id\n ...ProjectsMoveToWorkspaceDialog_Workspace\n projects {\n items {\n id\n }\n }\n }\n"): (typeof documents)["\n fragment MoveProjectsDialog_Workspace on Workspace {\n id\n ...ProjectsMoveToWorkspaceDialog_Workspace\n projects {\n items {\n id\n }\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@@ -1331,7 +1335,7 @@ export function graphql(source: "\n fragment MoveProjectsDialog_User on User {\
|
||||
/**
|
||||
* 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 WorkspaceProjectList_Workspace on Workspace {\n id\n ...WorkspaceBase_Workspace\n ...WorkspaceTeam_Workspace\n ...WorkspaceSecurity_Workspace\n ...BillingAlert_Workspace\n ...MoveProjectsDialog_Workspace\n ...InviteDialogWorkspace_Workspace\n projects {\n ...WorkspaceProjectList_ProjectCollection\n }\n creationState {\n completed\n state\n }\n readOnly\n }\n"): (typeof documents)["\n fragment WorkspaceProjectList_Workspace on Workspace {\n id\n ...WorkspaceBase_Workspace\n ...WorkspaceTeam_Workspace\n ...WorkspaceSecurity_Workspace\n ...BillingAlert_Workspace\n ...MoveProjectsDialog_Workspace\n ...InviteDialogWorkspace_Workspace\n projects {\n ...WorkspaceProjectList_ProjectCollection\n }\n creationState {\n completed\n state\n }\n readOnly\n }\n"];
|
||||
export function graphql(source: "\n fragment WorkspaceProjectList_Workspace on Workspace {\n id\n ...WorkspaceBase_Workspace\n ...WorkspaceTeam_Workspace\n ...WorkspaceSecurity_Workspace\n ...BillingAlert_Workspace\n ...InviteDialogWorkspace_Workspace\n projects {\n ...WorkspaceProjectList_ProjectCollection\n }\n creationState {\n completed\n state\n }\n readOnly\n }\n"): (typeof documents)["\n fragment WorkspaceProjectList_Workspace on Workspace {\n id\n ...WorkspaceBase_Workspace\n ...WorkspaceTeam_Workspace\n ...WorkspaceSecurity_Workspace\n ...BillingAlert_Workspace\n ...InviteDialogWorkspace_Workspace\n projects {\n ...WorkspaceProjectList_ProjectCollection\n }\n creationState {\n completed\n state\n }\n readOnly\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@@ -2172,6 +2176,10 @@ export function graphql(source: "\n fragment DiscoverableList_Discoverable on U
|
||||
* 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 DiscoverableList_Requests on User {\n workspaceJoinRequests {\n items {\n id\n status\n workspace {\n id\n name\n logo\n slug\n team {\n totalCount\n items {\n avatar\n }\n }\n }\n }\n }\n }\n"): (typeof documents)["\n fragment DiscoverableList_Requests on User {\n workspaceJoinRequests {\n items {\n id\n status\n workspace {\n id\n name\n logo\n slug\n team {\n totalCount\n items {\n avatar\n }\n }\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 fragment WorkspacePlanLimits_Workspace on Workspace {\n id\n plan {\n name\n }\n }\n"): (typeof documents)["\n fragment WorkspacePlanLimits_Workspace on Workspace {\n id\n plan {\n name\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@@ -2179,11 +2187,7 @@ export function graphql(source: "\n fragment UseWorkspaceInviteManager_PendingW
|
||||
/**
|
||||
* 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 WorkspacesPlan_Workspace on Workspace {\n id\n plan {\n status\n createdAt\n name\n paymentMethod\n usage {\n projectCount\n modelCount\n }\n }\n subscription {\n billingInterval\n currentBillingCycleEnd\n seats {\n editors {\n assigned\n available\n }\n viewers {\n assigned\n available\n }\n }\n }\n }\n"): (typeof documents)["\n fragment WorkspacesPlan_Workspace on Workspace {\n id\n plan {\n status\n createdAt\n name\n paymentMethod\n usage {\n projectCount\n modelCount\n }\n }\n subscription {\n billingInterval\n currentBillingCycleEnd\n seats {\n editors {\n assigned\n available\n }\n viewers {\n assigned\n available\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 fragment WorkspacePlanLimits_Workspace on Workspace {\n id\n projects(limit: 0) {\n totalCount\n items {\n id\n models(limit: 0) {\n totalCount\n }\n }\n }\n plan {\n name\n }\n }\n"): (typeof documents)["\n fragment WorkspacePlanLimits_Workspace on Workspace {\n id\n projects(limit: 0) {\n totalCount\n items {\n id\n models(limit: 0) {\n totalCount\n }\n }\n }\n plan {\n name\n }\n }\n"];
|
||||
export function graphql(source: "\n fragment WorkspacesPlan_Workspace on Workspace {\n id\n plan {\n status\n createdAt\n name\n paymentMethod\n usage {\n projectCount\n modelCount\n }\n }\n subscription {\n billingInterval\n currentBillingCycleEnd\n seats {\n editors {\n available\n assigned\n }\n viewers {\n available\n assigned\n }\n }\n }\n }\n"): (typeof documents)["\n fragment WorkspacesPlan_Workspace on Workspace {\n id\n plan {\n status\n createdAt\n name\n paymentMethod\n usage {\n projectCount\n modelCount\n }\n }\n subscription {\n billingInterval\n currentBillingCycleEnd\n seats {\n editors {\n available\n assigned\n }\n viewers {\n available\n assigned\n }\n }\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@@ -2204,6 +2208,10 @@ export function graphql(source: "\n fragment WorkspaceSsoStatus_Workspace on
|
||||
* 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 WorkspaceSsoStatus_User on User {\n expiredSsoSessions {\n id\n slug\n }\n }\n "): (typeof documents)["\n fragment WorkspaceSsoStatus_User on User {\n expiredSsoSessions {\n id\n slug\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 WorkspaceUsage_Workspace on Workspace {\n id\n plan {\n usage {\n projectCount\n modelCount\n }\n }\n }\n"): (typeof documents)["\n fragment WorkspaceUsage_Workspace on Workspace {\n id\n plan {\n usage {\n projectCount\n modelCount\n }\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@@ -2347,7 +2355,11 @@ export function graphql(source: "\n query WorkspaceLastAdminCheck($slug: String
|
||||
/**
|
||||
* 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 WorkspacePlanLimits($slug: String!) {\n workspaceBySlug(slug: $slug) {\n ...WorkspacePlanLimits_Workspace\n }\n }\n"): (typeof documents)["\n query WorkspacePlanLimits($slug: String!) {\n workspaceBySlug(slug: $slug) {\n ...WorkspacePlanLimits_Workspace\n }\n }\n"];
|
||||
export function graphql(source: "\n query WorkspaceLimits($slug: String!) {\n workspaceBySlug(slug: $slug) {\n ...WorkspacePlanLimits_Workspace\n }\n }\n"): (typeof documents)["\n query WorkspaceLimits($slug: String!) {\n workspaceBySlug(slug: $slug) {\n ...WorkspacePlanLimits_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 WorkspaceUsage($slug: String!) {\n workspaceBySlug(slug: $slug) {\n ...WorkspaceUsage_Workspace\n }\n }\n"): (typeof documents)["\n query WorkspaceUsage($slug: String!) {\n workspaceBySlug(slug: $slug) {\n ...WorkspaceUsage_Workspace\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
@@ -0,0 +1,71 @@
|
||||
import { graphql } from '~/lib/common/generated/gql/gql'
|
||||
import { useQuery } from '@vue/apollo-composable'
|
||||
import { workspaceLimitsQuery } from '~/lib/workspaces/graphql/queries'
|
||||
import { WorkspacePlanConfigs } from '@speckle/shared'
|
||||
import { useWorkspaceUsage } from '~/lib/workspaces/composables/usage'
|
||||
|
||||
graphql(`
|
||||
fragment WorkspacePlanLimits_Workspace on Workspace {
|
||||
id
|
||||
plan {
|
||||
name
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
export const useWorkspaceLimits = (slug: string) => {
|
||||
const { modelCount, projectCount } = useWorkspaceUsage(slug)
|
||||
|
||||
const { result } = useQuery(
|
||||
workspaceLimitsQuery,
|
||||
() => ({
|
||||
slug
|
||||
}),
|
||||
() => ({
|
||||
enabled: !!slug
|
||||
})
|
||||
)
|
||||
|
||||
// Plan limits
|
||||
const limits = computed(() => {
|
||||
const planName = result.value?.workspaceBySlug?.plan?.name
|
||||
if (!planName) return { projectCount: 0, modelCount: 0 }
|
||||
|
||||
const planConfig = WorkspacePlanConfigs[planName]
|
||||
return planConfig?.limits
|
||||
})
|
||||
|
||||
const remainingProjectCount = computed(() =>
|
||||
limits.value.projectCount ? limits.value.projectCount - projectCount.value : 0
|
||||
)
|
||||
const remainingModelCount = computed(() =>
|
||||
limits.value.modelCount ? limits.value.modelCount - modelCount.value : 0
|
||||
)
|
||||
|
||||
const canAddProject = computed(() => {
|
||||
// Unlimited
|
||||
if (limits.value.projectCount === null) return true
|
||||
|
||||
return projectCount.value + 1 <= limits.value.projectCount
|
||||
})
|
||||
|
||||
const canAddModels = (additionalModels?: number) => {
|
||||
// Unlimited
|
||||
if (limits.value.modelCount === null) return true
|
||||
|
||||
if (!additionalModels) {
|
||||
return remainingModelCount.value > 0
|
||||
}
|
||||
return modelCount.value + additionalModels <= limits.value.modelCount
|
||||
}
|
||||
|
||||
return {
|
||||
projectCount,
|
||||
modelCount,
|
||||
limits,
|
||||
remainingProjectCount,
|
||||
remainingModelCount,
|
||||
canAddProject,
|
||||
canAddModels
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,5 @@
|
||||
import { graphql } from '~~/lib/common/generated/gql'
|
||||
import {
|
||||
workspacePlanLimitsQuery,
|
||||
workspacePlanQuery
|
||||
} from '~~/lib/workspaces/graphql/queries'
|
||||
import { workspacePlanQuery } from '~~/lib/workspaces/graphql/queries'
|
||||
import { useQuery } from '@vue/apollo-composable'
|
||||
import {
|
||||
isNewWorkspacePlan,
|
||||
@@ -149,103 +146,3 @@ export const useWorkspacePlan = (slug: string) => {
|
||||
editorSeats
|
||||
}
|
||||
}
|
||||
|
||||
graphql(`
|
||||
fragment WorkspacePlanLimits_Workspace on Workspace {
|
||||
id
|
||||
projects(limit: 0) {
|
||||
totalCount
|
||||
items {
|
||||
id
|
||||
models(limit: 0) {
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
}
|
||||
plan {
|
||||
name
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
export const useGetWorkspacePlanUsage = (slug: string) => {
|
||||
const { result } = useQuery(
|
||||
workspacePlanLimitsQuery,
|
||||
() => ({
|
||||
slug
|
||||
}),
|
||||
() => ({
|
||||
enabled: !!slug
|
||||
})
|
||||
)
|
||||
|
||||
const projectCount = computed(
|
||||
() => result.value?.workspaceBySlug?.projects?.totalCount ?? 0
|
||||
)
|
||||
const modelCount = computed(
|
||||
() =>
|
||||
result.value?.workspaceBySlug?.projects?.items?.reduce(
|
||||
(total, project) => total + (project?.models?.totalCount ?? 0),
|
||||
0
|
||||
) ?? 0
|
||||
)
|
||||
|
||||
return {
|
||||
projectCount,
|
||||
modelCount
|
||||
}
|
||||
}
|
||||
|
||||
export const useWorkspacePlanLimits = (
|
||||
projectCount: ComputedRef<number>,
|
||||
modelCount: ComputedRef<number>
|
||||
) => {
|
||||
const projectLimit = computed(() => 3)
|
||||
const modelLimit = computed(() => 8)
|
||||
|
||||
const remainingProjects = computed(() => {
|
||||
return projectLimit.value - projectCount.value
|
||||
})
|
||||
|
||||
const remainingModels = computed(() => {
|
||||
return modelLimit.value - modelCount.value
|
||||
})
|
||||
|
||||
const limitType = computed(() => {
|
||||
if (projectCount.value > projectLimit.value) {
|
||||
return 'project'
|
||||
}
|
||||
if (modelCount.value > modelLimit.value) {
|
||||
return 'model'
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
||||
const activeLimit = computed(() => {
|
||||
const limit =
|
||||
limitType.value === 'project'
|
||||
? projectLimit.value
|
||||
: limitType.value === 'model'
|
||||
? modelLimit.value
|
||||
: null
|
||||
return limit
|
||||
})
|
||||
|
||||
const canAddProject = computed(
|
||||
() => remainingProjects.value !== null && remainingProjects.value > 0
|
||||
)
|
||||
const canAddModels = computed(
|
||||
() => remainingModels.value !== null && remainingModels.value > 0
|
||||
)
|
||||
|
||||
return {
|
||||
projectLimit,
|
||||
modelLimit,
|
||||
remainingProjects,
|
||||
remainingModels,
|
||||
canAddProject,
|
||||
canAddModels,
|
||||
limitType,
|
||||
activeLimit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import { graphql } from '~/lib/common/generated/gql/gql'
|
||||
import { useQuery } from '@vue/apollo-composable'
|
||||
import { workspaceUsageQuery } from '~/lib/workspaces/graphql/queries'
|
||||
|
||||
graphql(`
|
||||
fragment WorkspaceUsage_Workspace on Workspace {
|
||||
id
|
||||
plan {
|
||||
usage {
|
||||
projectCount
|
||||
modelCount
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
export const useWorkspaceUsage = (slug: string) => {
|
||||
const { result } = useQuery(
|
||||
workspaceUsageQuery,
|
||||
() => ({
|
||||
slug
|
||||
}),
|
||||
() => ({
|
||||
enabled: !!slug
|
||||
})
|
||||
)
|
||||
|
||||
const projectCount = computed(
|
||||
() => result.value?.workspaceBySlug?.plan?.usage.projectCount ?? 0
|
||||
)
|
||||
const modelCount = computed(
|
||||
() => result.value?.workspaceBySlug?.plan?.usage.modelCount ?? 0
|
||||
)
|
||||
|
||||
return {
|
||||
projectCount,
|
||||
modelCount
|
||||
}
|
||||
}
|
||||
@@ -158,10 +158,18 @@ export const workspaceLastAdminCheckQuery = graphql(`
|
||||
}
|
||||
`)
|
||||
|
||||
export const workspacePlanLimitsQuery = graphql(`
|
||||
query WorkspacePlanLimits($slug: String!) {
|
||||
export const workspaceLimitsQuery = graphql(`
|
||||
query WorkspaceLimits($slug: String!) {
|
||||
workspaceBySlug(slug: $slug) {
|
||||
...WorkspacePlanLimits_Workspace
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
export const workspaceUsageQuery = graphql(`
|
||||
query WorkspaceUsage($slug: String!) {
|
||||
workspaceBySlug(slug: $slug) {
|
||||
...WorkspaceUsage_Workspace
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
Reference in New Issue
Block a user