feat(fe2): move settings to tab on projects page (#2207)

* Add settings tab. Update style of component

* Structuring of files/components

* Updates to TexInput

* Add RadioGroup

* Last FE work

* FE Updates

* Webhooks Settings Tab

* Styling updates to webhooks

* Title/Description Update

* General Page done

* Collaborators WIP

* Styling updates

* Add custom message to updateProject

* Radio Group Same Height

* Styling updates to radio group. Disabled state

* Updates pre demo

* Updates to icons & post demo changes

* Major Updates

* Unsaved Changes Dialog

* Routing WIP

* Remove StatsBlock

* Auto update discussions on Private

* Routing/Redirects

* New input style

* Invite Dialog

* Fix mobile radiogroup

* Mobile Improvements

* Fix console warning

* Fix build

* Disabled States

* Fix console

* Unhide webhooks

* Updates from testing

* Responsive fixes

* Alignment fixes

* Fix textarea mobile height

* Updates to GraphQL Fragments

* Fix disabled state

* WIP Arrows for scroll

* Update PageTabs - broken

* Fix to PageTabs

* PageTab fix initial scroll

* Hide Scrollbar

* Better underline method

* Fix mobile initial underline

* Webhooks Empty State

* Fix input border

* Fix empty state

* Input Styling updates

* Remove mobile smaller text

* Update disabled state for disabled items

* Updates disabled sates on Settings Block

* Fix build. Disable Invite

* Fixes to invite permissions

* Disable role select when invite is disabled

* Small alignment fix

* Fix webhooks empty state

* cleaning up unnecessary vue files

* story improvement

* Remove DisabledMessage prop

* Fix disabled prop on Button

* Move team to Leave Fragment

* Remove unused Disabled Message props

* Add limit to graphql query

* Updates to BlockDiscussions

* add formatTriggers function to webhooks

* Remove md from button. Improved switch

* Update RadioGroup.stories.ts

* Update RadioGroup to use defineModel

* Various styling and copy updates

- More concise and accurate copy
- More readable
- Works better on mobile

* Updates to Invite Dialog

* Custom success Message

* Update slot names

* Remove md in TextInput. Set h-8 to default

* Changes from call with fabs

* Replace isOwner with composable

* Set SettingsBlock icon as optional

* Comments from PR

* Updates from PR

* Final Tidy Ups

* Fix Title/Description

* Fix spacing issue on Webhooks page

* Update borders and colors to align with Automate

Makes the same changes that I recently made to the unreleased Automate tab

* WEB-869

* Improve styling of radiogroup component

Better borders, hover effect, bigger checkmark icon, more subtle active background color, same across breakpoints.

* Adjust border styling of RadioGroup component

* Improve circle around checkmark in RadioGroup

* Split Tabs into 2 components

* Restyle overflow arrows

* Adjust gap and remove icons from vertical nav

Too many icons on the screen got distracting.

* Ensure active item visible

* Increase gap on vertical nav

* Update copy for Access and Discussions settings

* Input Tidyup

* WEB-877 update-collaborators-block

* Update inputs to new style

* Fix webhooks button hover state

* Fix comment copy

Appears in the access settings before embedding a model

* Remove hover shadow from search input on Dashboard

* Small change from Benjamin

* Change collaborators permissions copy

* Comments from PR #1

* Comments from PR #2

* Fix condition for EditableHeader

* Updates from CR

---------

Co-authored-by: Kristaps Fabians Geikins <fabis94@live.com>
Co-authored-by: Benjamin Ottensten <benjamin.ottensten@gmail.com>
This commit is contained in:
andrewwallacespeckle
2024-05-10 14:04:11 +02:00
committed by GitHub
parent e9ee53b827
commit e72b193f06
72 changed files with 2398 additions and 1295 deletions
@@ -27,7 +27,7 @@
</div>
</label>
<PencilIcon
v-if="canEdit"
v-if="canEdit && !isDisabled"
class="shrink-0 ml-2 mt-3 w-4 h-4 opacity-0 group-hover:opacity-100 transition text-foreground-2"
/>
</div>
@@ -65,7 +65,7 @@
</label>
<div class="shrink-0 ml-2 mt-1 text-foreground-2">
<PencilIcon
v-if="canEdit"
v-if="canEdit && !isDisabled"
class="w-4 h-4 opacity-0 group-hover:opacity-100 transition text-foreground-2"
/>
</div>
@@ -10,6 +10,7 @@
:fully-control-value="fullyControlValue"
:label-id="labelId"
:button-id="buttonId"
mount-menu-on-body
>
<template #nothing-selected>
{{ multiple ? 'Select roles' : 'Select role' }}
@@ -66,7 +66,7 @@ const items = ref<
},
[ProjectVisibility.Private]: {
id: ProjectVisibility.Private,
description: 'Only team members will have access',
description: 'Only collaborators can access',
title: 'Private'
}
})
@@ -16,7 +16,7 @@
:title="titleState"
:description="descriptionState"
:can-edit="canEdit"
:is-disabled="anyMutationsLoading"
:is-disabled="canEdit || anyMutationsLoading"
@update:title="handleUpdateTitle"
@update:description="handleUpdateDescription"
/>
@@ -8,32 +8,38 @@
Move {{ versions.length }} version{{ versions.length > 1 ? 's' : '' }}
</template>
<div class="flex flex-col space-y-4">
<LayoutTabs v-slot="{ activeItem }" :items="tabItems">
<ProjectModelPageDialogMoveToExistingTab
v-if="activeItem.id === 'existing-model'"
:versions="versions"
:project-id="projectId"
:disabled="loading"
:model-id="modelId"
@model-selected="onMove"
/>
<ProjectModelPageDialogMoveToNewTab
v-else
:project-id="projectId"
:versions="versions"
:disabled="loading"
@model-selected="onMove($event, true)"
/>
</LayoutTabs>
<LayoutTabsHoriztonal v-model:active-item="activeTab" :items="tabItems">
<template #default="{ activeItem }">
<div class="min-h-40">
<ProjectModelPageDialogMoveToExistingTab
v-if="activeItem.id === 'existing-model'"
:versions="versions"
:project-id="projectId"
:disabled="loading"
:model-id="modelId"
@model-selected="onMove"
/>
<ProjectModelPageDialogMoveToNewTab
v-else-if="activeItem.id === 'new-model'"
:project-id="projectId"
:versions="versions"
:disabled="loading"
@model-selected="onMove($event, true)"
/>
</div>
</template>
</LayoutTabsHoriztonal>
</div>
</LayoutDialog>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { graphql } from '~~/lib/common/generated/gql'
import type { ProjectModelPageDialogMoveToVersionFragment } from '~~/lib/common/generated/gql/graphql'
import { useMixpanel } from '~~/lib/core/composables/mp'
import type { LayoutTabItem } from '~~/lib/layout/helpers/components'
import { useMoveVersions } from '~~/lib/projects/composables/versionManagement'
import { LayoutTabsHoriztonal } from '@speckle/ui-components'
import type { LayoutPageTabItem } from '@speckle/ui-components'
graphql(`
fragment ProjectModelPageDialogMoveToVersion on Version {
@@ -55,20 +61,23 @@ const props = defineProps<{
}>()
const moveVersions = useMoveVersions()
const mp = useMixpanel()
const loading = ref(false)
const tabItems = ref<LayoutTabItem[]>([
// Define tab items
const tabItems = ref<LayoutPageTabItem[]>([
{ title: 'Existing model', id: 'existing-model' },
{ title: 'New model', id: 'new-model' }
])
// Manage active tab state
const activeTab = ref(tabItems.value[0])
const isOpen = computed({
get: () => props.open,
set: (newVal) => emit('update:open', newVal)
set: (value) => emit('update:open', value)
})
const mp = useMixpanel()
const onMove = async (targetModelName: string, newModelCreated?: boolean) => {
loading.value = true
const success = await moveVersions(
@@ -76,7 +85,11 @@ const onMove = async (targetModelName: string, newModelCreated?: boolean) => {
versionIds: props.versions.map((v) => v.id),
targetModelName
},
{ previousModelId: props.modelId, newModelCreated, projectId: props.projectId }
{
previousModelId: props.modelId,
newModelCreated,
projectId: props.projectId
}
)
loading.value = false
mp.track('Commit Action', {
@@ -11,7 +11,7 @@
:title="titleState"
:description="descriptionState"
:can-edit="canEdit"
:is-disabled="anyMutationsLoading"
:is-disabled="!canEdit || anyMutationsLoading"
@update:title="handleUpdateTitle"
@update:description="handleUpdateDescription"
/>
@@ -1,25 +1,28 @@
<template>
<LayoutDialogSection
allow-overflow
border-b
border-t
title="Invite"
:always-open="defaultOpen"
>
<template #icon>
<UserPlusIcon class="h-full w-full" />
</template>
<LayoutDialog v-model:open="isOpen" max-width="md" :buttons="dialogButtons">
<template #header>Invite to Project</template>
<div class="flex flex-col mt-2">
<FormTextInput
v-model="search"
name="search"
size="lg"
placeholder="Search"
help="Search by username or email"
:disabled="disabled"
:help="
disabled
? 'You must be the project owner to invite users'
: 'Search by username or email'
"
input-classes="pr-[85px] text-sm"
color="foundation"
label="Add people by email or username"
show-label
>
<template #input-right>
<div class="absolute inset-y-0 right-0 flex items-center pr-2">
<div
class="absolute inset-y-0 right-0 flex items-center pr-2"
:class="disabled ? 'pointer-events-none' : ''"
>
<ProjectPageTeamPermissionSelect v-model="role" hide-remove />
</div>
</template>
@@ -48,34 +51,43 @@
/>
</div>
</div>
</LayoutDialogSection>
</LayoutDialog>
</template>
<script setup lang="ts">
import { Roles } from '@speckle/shared'
import type { ServerRoles, StreamRoles } from '@speckle/shared'
import { LayoutDialogSection } from '@speckle/ui-components'
import { useUserSearch } from '~~/lib/common/composables/users'
import type { UserSearchItem } from '~~/lib/common/composables/users'
import type {
ProjectInviteCreateInput,
ProjectPageTeamDialogFragment
ProjectPageInviteDialog_ProjectFragment
} from '~~/lib/common/generated/gql/graphql'
import type { SetFullyRequired } from '~~/lib/common/helpers/type'
import { isEmail } from '~~/lib/common/helpers/validation'
import { isArray, isString } from 'lodash-es'
import { useInviteUserToProject } from '~~/lib/projects/composables/projectManagement'
import { useTeamDialogInternals } from '~~/lib/projects/composables/team'
import { UserPlusIcon } from '@heroicons/vue/24/outline'
import { useTeamInternals } from '~~/lib/projects/composables/team'
import { useMixpanel } from '~~/lib/core/composables/mp'
import { useServerInfo } from '~~/lib/core/composables/server'
import { graphql } from '~/lib/common/generated/gql/gql'
graphql(`
fragment ProjectPageInviteDialog_Project on Project {
id
...ProjectPageTeamInternals_Project
}
`)
type InvitableUser = UserSearchItem | string
const props = defineProps<{
project: ProjectPageTeamDialogFragment
defaultOpen: boolean
projectId: string
project?: ProjectPageInviteDialog_ProjectFragment
disabled?: boolean
}>()
const isOpen = defineModel<boolean>('open', { required: true })
const loading = ref(false)
const search = ref('')
const role = ref<StreamRoles>(Roles.Stream.Contributor)
@@ -88,9 +100,22 @@ const { userSearch, searchVariables } = useUserSearch({
limit: 5
}))
})
const { collaboratorListItems } = useTeamDialogInternals({
props: toRefs(props)
})
const projectId = computed(() => props.projectId as string)
const projectData = computed(() => props.project)
const { collaboratorListItems } = useTeamInternals(projectData)
const dialogButtons = computed(() => [
{
text: 'Cancel',
props: { color: 'secondary', fullWidth: true },
onClick: () => {
isOpen.value = false
}
}
])
const selectedEmails = computed(() => {
const query = searchVariables.value?.query || ''
@@ -150,7 +175,7 @@ const onInviteUser = async (
// Invite email
loading.value = true
await createInvite(props.project.id, inputs)
await createInvite(projectId.value, inputs)
mp.track('Invite Action', {
type: 'project invite',
@@ -1,5 +1,5 @@
<template>
<div class="bg-foundation rounded-lg p-4 sm:px-6">
<div class="bg-foundation rounded-lg p-4 border border-outline-3">
<div class="flex flex-col">
<div class="text-foreground-2 mb-2">
<slot name="top" />
@@ -1,80 +0,0 @@
<template>
<ProjectPageLatestItems
:count="project?.commentThreadCount.totalCount || 0"
:hide-filters="showCommentsIntro"
:see-all-url="projectDiscussionsRoute(projectId)"
title="Discussions"
>
<template #default="{ gridOrList }">
<template v-if="!showCommentsIntro">
<ProjectPageLatestItemsCommentsGrid
v-if="gridOrList === GridListToggleValue.Grid"
:threads="latestCommentsResult"
disable-pagination
/>
<ProjectPageLatestItemsCommentsList
v-else
:threads="latestCommentsResult"
disable-pagination
/>
</template>
<template v-else>
<ProjectPageLatestItemsCommentsEmptyState />
</template>
</template>
</ProjectPageLatestItems>
</template>
<script setup lang="ts">
import { graphql } from '~~/lib/common/generated/gql'
import type { ProjectPageLatestItemsCommentsFragment } from '~~/lib/common/generated/gql/graphql'
import { GridListToggleValue } from '~~/lib/layout/helpers/components'
import { useQuery } from '@vue/apollo-composable'
import { latestCommentThreadsQuery } from '~~/lib/projects/graphql/queries'
import { projectDiscussionsRoute } from '~~/lib/common/helpers/route'
import type { Optional } from '@speckle/shared'
graphql(`
fragment ProjectPageLatestItemsComments on Project {
id
commentThreadCount: commentThreads(limit: 0) {
totalCount
}
}
`)
graphql(`
fragment ProjectPageLatestItemsCommentItem on Comment {
id
author {
...FormUsersSelectItem
}
screenshot
rawText
createdAt
updatedAt
archived
repliesCount: replies(limit: 0) {
totalCount
}
replyAuthors(limit: 4) {
totalCount
items {
...FormUsersSelectItem
}
}
}
`)
const props = defineProps<{
projectId: string
project: Optional<ProjectPageLatestItemsCommentsFragment>
}>()
const { result: latestCommentsResult } = useQuery(latestCommentThreadsQuery, () => ({
projectId: props.projectId
}))
const showCommentsIntro = computed(() =>
props.project ? props.project.commentThreadCount.totalCount < 1 : false
)
</script>
@@ -1,176 +0,0 @@
<template>
<ProjectPageLatestItems
:count="project?.modelCount.totalCount || 0"
:title="title"
:see-all-url="allProjectModelsRoute(projectId)"
hide-heading-bottom-margin
>
<template #default>
<CommonLoadingBar :loading="showLoadingBar" class="my-2" />
<div>
<ProjectPageModelsListView
v-if="gridOrList === GridListToggleValue.List"
:search="debouncedSearch"
:project="project"
:project-id="projectId"
disable-pagination
@update:loading="queryLoading = $event"
@clear-search=";(search = ''), updateSearchImmediately()"
/>
<ProjectPageModelsCardView
v-if="gridOrList === GridListToggleValue.Grid"
:search="debouncedSearch"
:project="project"
:project-id="projectId"
disable-pagination
@update:loading="queryLoading = $event"
@clear-search=";(search = ''), updateSearchImmediately()"
/>
</div>
<ProjectPageModelsNewDialog
v-model:open="showNewDialog"
:project-id="projectId"
/>
</template>
<template #filters>
<div class="flex grow mt-2 w-full lg:mt-0 lg:w-auto lg:justify-end">
<div
class="flex flex-col space-y-2 sm:space-y-0 sm:flex-row sm:items-center sm:space-x-2 w-full lg:w-auto"
>
<div class="flex items-center space-x-2 grow">
<FormTextInput
v-model="search"
name="modelsearch"
:show-label="false"
placeholder="Search"
color="foundation"
wrapper-classes="grow lg:w-60"
:show-clear="search !== ''"
@change="($event) => updateSearchImmediately($event.value)"
@update:model-value="updateDebouncedSearch"
></FormTextInput>
<LayoutGridListToggle v-model="gridOrList" />
</div>
<div class="flex items-center space-x-2">
<FormButton
color="secondary"
:icon-right="CubeIcon"
:to="allModelsRoute"
class="grow"
@click="trackFederateAll"
>
View all in 3D
</FormButton>
<FormButton
v-if="canContribute"
class="grow"
:icon-left="PlusIcon"
@click="showNewDialog = true"
>
New
</FormButton>
<FormButton v-if="false" @click="onTest">Test</FormButton>
</div>
</div>
</div>
</template>
</ProjectPageLatestItems>
</template>
<script setup lang="ts">
import { GridListToggleValue } from '~~/lib/layout/helpers/components'
import type { ProjectPageLatestItemsModelsFragment } from '~~/lib/common/generated/gql/graphql'
import { graphql } from '~~/lib/common/generated/gql'
import { useProjectPageItemViewType } from '~~/lib/projects/composables/projectPages'
import { canModifyModels } from '~~/lib/projects/helpers/permissions'
import { debounce } from 'lodash-es'
import { PlusIcon } from '@heroicons/vue/24/solid'
import { CubeIcon } from '@heroicons/vue/24/outline'
import { allProjectModelsRoute, modelRoute } from '~~/lib/common/helpers/route'
import { SpeckleViewer, type Optional } from '@speckle/shared'
import { useMixpanel } from '~~/lib/core/composables/mp'
graphql(`
fragment ProjectPageLatestItemsModels on Project {
id
role
visibility
modelCount: models(limit: 0) {
totalCount
}
...ProjectPageModelsStructureItem_Project
}
`)
const props = defineProps<{
projectId: string
project: Optional<ProjectPageLatestItemsModelsFragment>
}>()
const mp = useMixpanel()
const trackFederateAll = () =>
mp.track('Viewer Action', {
type: 'action',
name: 'federation',
action: 'view-all',
source: 'all models page'
})
const queryLoading = ref(false)
const search = ref('')
const debouncedSearch = ref('')
const showNewDialog = ref(false)
const showLoadingBar = ref(false)
const title = ref('Models')
const gridOrList = useProjectPageItemViewType(title.value)
const canContribute = computed(() =>
props.project ? canModifyModels(props.project) : false
)
const allModelsRoute = computed(() => {
const resourceIdString = SpeckleViewer.ViewerRoute.resourceBuilder()
.addAllModels()
.toString()
return modelRoute(props.projectId, resourceIdString)
})
const updateDebouncedSearch = debounce(() => {
debouncedSearch.value = search.value.trim()
}, 500)
const updateSearchImmediately = (val?: string) => {
updateDebouncedSearch.cancel()
debouncedSearch.value = (val ?? search.value).trim()
}
const onTest = () => {
// TODO: Remove after RUM tests are done
// Unhandled rejection
void new Promise((_resolve, reject) => {
setTimeout(() => {
reject(new Error('Unhandled rejection!'))
}, 200)
})
// Uncaught error
setTimeout(() => {
throw new Error('Unhandled exception!')
}, 300)
// Sync error
throw new Error('Sync error!')
}
watch(search, (newVal) => {
if (newVal) showLoadingBar.value = true
else showLoadingBar.value = false
})
watch(queryLoading, (newVal) => (showLoadingBar.value = newVal))
// TODO: Remove after RUM tests are done
// if (process.server) {
// onTest()
// }
</script>
@@ -7,9 +7,10 @@
>
<template #header>Create New Model</template>
<form @submit="onSubmit">
<div class="flex flex-col space-y-4">
<div class="flex flex-col space-y-6 mb-4">
<FormTextInput
v-model="newModelName"
color="foundation"
name="name"
label="Model Name"
show-label
@@ -21,6 +22,7 @@
/>
<FormTextArea
v-model="newDescription"
color="foundation"
name="description"
show-label
label="Model Description"
@@ -0,0 +1,62 @@
<template>
<div
class="flex flex-col w-full"
:class="
background
? 'bg-foundation border border-outline-3 rounded-lg overflow-hidden '
: ''
"
>
<div
class="flex items-center gap-4 justify-between transition"
:class="background ? 'pt-4 px-4 sm:pt-6 sm:px-6' : ''"
>
<div class="flex items-center gap-2">
<component :is="icon" v-if="icon" class="h-5 w-5"></component>
<h3 class="text-xl font-bold">{{ title }}</h3>
</div>
<div v-if="$slots['top-buttons']" class="flex gap-4">
<slot name="top-buttons" />
</div>
</div>
<div
v-if="$slots.introduction"
class="text-foreground"
:class="background ? 'px-4 sm:px-6 pt-4' : 'pt-6'"
>
<slot name="introduction" />
</div>
<div class="flex flex-col" :class="background ? 'p-4 sm:p-6' : ''">
<slot />
</div>
<div
v-if="disabledMessage || $slots['bottom-buttons']"
class="flex flex-col sm:flex-row gap-2 justify-between items-end sm:items-center bg-gray-50 dark:bg-foundation px-4 sm:px-6 py-4 border-t border-outline-3"
>
<div v-if="disabledMessage" class="text-xs flex gap-1 sm:items-center w-full">
<ExclamationCircleIcon
v-tippy="disabledMessage"
class="h-5 w-5 text-foreground-2"
/>
<span class="text-foreground-2">
You must be a project owner to edit project details
</span>
</div>
<div v-else></div>
<div v-if="$slots['bottom-buttons']" class="flex gap-2">
<slot name="bottom-buttons" />
</div>
</div>
</div>
</template>
<script setup lang="ts">
import type { PropAnyComponent } from '@speckle/ui-components'
import { ExclamationCircleIcon } from '@heroicons/vue/24/outline'
defineProps<{
title: string
icon?: PropAnyComponent
background?: boolean
disabledMessage?: string
}>()
</script>
@@ -0,0 +1,162 @@
<template>
<ProjectPageSettingsBlock title="Collaborators">
<template #introduction>
<p>Invite new collaborators and set permissions.</p>
</template>
<template #top-buttons>
<FormButton :icon-left="UserPlusIcon" @click="toggleInviteDialog">
Invite
</FormButton>
</template>
<div class="flex flex-col mt-6">
<div
v-for="collaborator in collaboratorListItems"
:key="collaborator.id"
class="bg-foundation flex items-center gap-2 py-3 px-4 border-t border-x last:border-b border-outline-3 first:rounded-t-lg last:rounded-b-lg"
>
<UserAvatar :user="collaborator.user" size="sm" />
<span class="grow truncate text-sm">{{ collaborator.title }}</span>
<template v-if="!collaborator.inviteId">
<ProjectPageTeamPermissionSelect
v-if="canEdit && activeUser && collaborator.id !== activeUser.id"
class="shrink-0"
:model-value="collaborator.role"
:disabled="loading"
:hide-owner="collaborator.serverRole === Roles.Server.Guest"
@update:model-value="onCollaboratorRoleChange(collaborator, $event)"
@delete="onCollaboratorRoleChange(collaborator, null)"
/>
<span v-else class="shrink-0 text-sm">
{{ roleSelectItems[collaborator.role].title }}
</span>
</template>
<template v-else-if="canEdit">
<div class="flex items-end sm:items-center shrink-0 gap-3">
<span class="shrink-0 text-foreground-2 text-sm">
{{ roleSelectItems[collaborator.role].title }}
</span>
<FormButton
class="shrink-0"
color="danger"
size="xs"
:disabled="loading"
@click="
cancelInvite({
projectId,
inviteId: collaborator.inviteId || ''
})
"
>
Cancel Invite
</FormButton>
</div>
</template>
</div>
</div>
<ProjectPageInviteDialog
v-if="project"
v-model:open="showInviteDialog"
:project="project"
:project-id="projectId"
:disabled="!isOwner"
/>
</ProjectPageSettingsBlock>
</template>
<script setup lang="ts">
import { Roles } from '@speckle/shared'
import type { Nullable, StreamRoles } from '@speckle/shared'
import { useApolloClient, useQuery } from '@vue/apollo-composable'
import { useActiveUser } from '~~/lib/auth/composables/activeUser'
import type { Project } from '~~/lib/common/generated/gql/graphql'
import {
getCacheId,
getObjectReference,
modifyObjectFields
} from '~~/lib/common/helpers/graphql'
import {
useCancelProjectInvite,
useUpdateUserRole
} from '~~/lib/projects/composables/projectManagement'
import { useTeamInternals } from '~~/lib/projects/composables/team'
import { roleSelectItems } from '~~/lib/projects/helpers/components'
import type { ProjectCollaboratorListItem } from '~~/lib/projects/helpers/components'
import { UserPlusIcon } from '@heroicons/vue/24/outline'
import { useMixpanel } from '~~/lib/core/composables/mp'
import { graphql } from '~~/lib/common/generated/gql'
const projectPageSettingsCollaboratorsQuery = graphql(`
query ProjectPageSettingsCollaborators($projectId: String!) {
project(id: $projectId) {
id
...ProjectPageTeamInternals_Project
...ProjectPageInviteDialog_Project
}
}
`)
const route = useRoute()
const apollo = useApolloClient().client
const updateRole = useUpdateUserRole()
const cancelInvite = useCancelProjectInvite()
const { activeUser } = useActiveUser()
const mp = useMixpanel()
const showInviteDialog = ref(false)
const loading = ref(false)
const projectId = computed(() => route.params.id as string)
const { result: pageResult } = useQuery(projectPageSettingsCollaboratorsQuery, () => ({
projectId: projectId.value
}))
const project = computed(() => pageResult.value?.project)
const { collaboratorListItems, isOwner, isServerGuest } = useTeamInternals(project)
const canEdit = computed(() => isOwner.value && !isServerGuest.value)
const onCollaboratorRoleChange = async (
collaborator: ProjectCollaboratorListItem,
newRole: Nullable<StreamRoles>
) => {
if (collaborator.inviteId) return
loading.value = true
await updateRole({
projectId: projectId.value,
userId: collaborator.id,
role: newRole
})
loading.value = false
mp.track('Stream Action', {
type: 'action',
name: 'update',
action: 'team member role'
})
if (!newRole) {
// Remove from team
modifyObjectFields<undefined, Project['team']>(
apollo.cache,
getCacheId('Project', projectId.value),
(fieldName, _variables, value) => {
if (fieldName !== 'team') return
return value.filter(
(t) =>
!t.user ||
t.user.__ref !== getObjectReference('LimitedUser', collaborator.id).__ref
)
}
)
}
}
const toggleInviteDialog = () => {
showInviteDialog.value = true
}
</script>
@@ -0,0 +1,128 @@
<template>
<div v-if="project" class="flex flex-col gap-4">
<ProjectPageSettingsGeneralBlockProjectInfo
:project="project"
:disabled="isDisabled"
@update-project="
({ name, description, onComplete }) =>
handleUpdate({ name, description }, 'Project info updated', onComplete)
"
/>
<ProjectPageSettingsGeneralBlockAccess
:project="project"
:disabled="isDisabled"
@update-visibility="
(newVisibility) =>
handleUpdate({ visibility: newVisibility }, 'Project access updated')
"
/>
<ProjectPageSettingsGeneralBlockDiscussions
:project="project"
:disabled="isDisabled"
@update-comments-permission="
(newCommentsPermission) =>
handleUpdate(
{ allowPublicComments: newCommentsPermission },
'Comment permissions updated'
)
"
/>
<ProjectPageSettingsGeneralBlockLeave :project="project" />
<ProjectPageSettingsGeneralBlockDelete
v-if="isOwner && !isGuest"
:project="project"
@update-comments-permission="
(newCommentsPermission) =>
handleUpdate(
{ allowPublicComments: newCommentsPermission },
'Comment permissions updated'
)
"
/>
</div>
<div v-else></div>
</template>
<script setup lang="ts">
import { useQuery } from '@vue/apollo-composable'
import type { ProjectUpdateInput } from '~~/lib/common/generated/gql/graphql'
import { useUpdateProject } from '~~/lib/projects/composables/projectManagement'
import { graphql } from '~~/lib/common/generated/gql'
import { useTeamInternals } from '~/lib/projects/composables/team'
const projectPageSettingsGeneralQuery = graphql(`
query ProjectPageSettingsGeneral($projectId: String!) {
project(id: $projectId) {
id
role
...ProjectPageSettingsGeneralBlockProjectInfo_Project
...ProjectPageSettingsGeneralBlockAccess_Project
...ProjectPageSettingsGeneralBlockDiscussions_Project
...ProjectPageSettingsGeneralBlockLeave_Project
...ProjectPageSettingsGeneralBlockDelete_Project
...ProjectPageTeamInternals_Project
}
}
`)
const route = useRoute()
const updateProject = useUpdateProject()
const projectId = computed(() => route.params.id as string)
const { result: pageResult } = useQuery(
projectPageSettingsGeneralQuery,
() => ({
projectId: projectId.value
}),
() => ({
// Custom error policy so that a failing invitedTeam resolver (due to access rights)
// doesn't kill the entire query
errorPolicy: 'all',
context: {
skipLoggingErrors: (err) =>
err.graphQLErrors?.length === 1 &&
err.graphQLErrors.some((e) => !!e.path?.includes('invitedTeam'))
}
})
)
const project = computed(() => pageResult.value?.project)
const { isGuest } = useActiveUser()
const logger = useLogger()
const { isOwner } = useTeamInternals(project)
const isDisabled = computed(() => !isOwner.value || isGuest.value)
const handleUpdate = async (
updates: Partial<ProjectUpdateInput>,
customSuccessMessage?: string,
onComplete?: () => void
) => {
if (!project.value) {
return
}
const updatePayload: ProjectUpdateInput = {
id: project.value.id,
...updates
}
const options = customSuccessMessage ? { customSuccessMessage } : {}
try {
const result = await updateProject(updatePayload, options)
if (result && result.id) {
if (onComplete) {
onComplete()
}
}
} catch (error) {
logger.error('Failed to update project:', error)
}
}
</script>
@@ -0,0 +1,76 @@
<template>
<ProjectPageSettingsBlock
background
title="Access"
:icon="LockClosedIcon"
:disabled-message="disabled ? 'You must be a project owner' : undefined"
>
<template #introduction>
<p>Choose how you want to share this project with others.</p>
</template>
<FormRadioGroup
v-model="selectedOption"
:options="radioOptions"
:disabled="disabled"
@update:model-value="emitUpdate"
/>
</ProjectPageSettingsBlock>
</template>
<script setup lang="ts">
import { LockClosedIcon, LinkIcon, GlobeAltIcon } from '@heroicons/vue/24/outline'
import { FormRadioGroup } from '@speckle/ui-components'
import { ProjectVisibility } from '~/lib/common/generated/gql/graphql'
import { graphql } from '~~/lib/common/generated/gql'
import type { ProjectPageSettingsGeneralBlockAccess_ProjectFragment } from '~~/lib/common/generated/gql/graphql'
graphql(`
fragment ProjectPageSettingsGeneralBlockAccess_Project on Project {
id
visibility
}
`)
const props = defineProps<{
project: ProjectPageSettingsGeneralBlockAccess_ProjectFragment
disabled?: boolean
}>()
const emit = defineEmits<{
(e: 'update-visibility', v: ProjectVisibility): void
}>()
const selectedOption = ref(props.project.visibility || ProjectVisibility.Private)
const radioOptions = computed(() => [
{
value: ProjectVisibility.Public,
title: 'Public',
introduction: 'Anyone can view and access your project',
icon: GlobeAltIcon
},
{
value: ProjectVisibility.Unlisted,
title: 'Unlisted',
introduction: 'Anyone with the link can access',
icon: LinkIcon
},
{
value: ProjectVisibility.Private,
title: 'Private',
introduction: 'Only collaborators can access',
icon: LockClosedIcon
}
])
watch(
() => props.project.visibility,
(newVal) => {
selectedOption.value = newVal ?? ProjectVisibility.Private
}
)
const emitUpdate = (value: ProjectVisibility) => {
emit('update-visibility', value)
}
</script>
@@ -0,0 +1,46 @@
<template>
<div>
<ProjectPageSettingsBlock background title="Delete Project" :icon="TrashIcon">
<p>
Permanently delete this project and all of its content from the Speckle
platform. This action is not reversible.
</p>
<template #bottom-buttons>
<FormButton color="danger" @click="showDeleteDialog = true">
Delete Project
</FormButton>
</template>
</ProjectPageSettingsBlock>
<ProjectPageSettingsGeneralBlockDeleteDialog
v-if="project"
v-model:open="showDeleteDialog"
:project="project"
/>
</div>
</template>
<script setup lang="ts">
import { TrashIcon } from '@heroicons/vue/24/outline'
import { graphql } from '~~/lib/common/generated/gql'
import type { ProjectPageSettingsGeneralBlockDelete_ProjectFragment } from '~~/lib/common/generated/gql/graphql'
graphql(`
fragment ProjectPageSettingsGeneralBlockDelete_Project on Project {
id
name
role
models(limit: 0) {
totalCount
}
commentThreads(limit: 0) {
totalCount
}
}
`)
defineProps<{
project?: ProjectPageSettingsGeneralBlockDelete_ProjectFragment
}>()
const showDeleteDialog = ref(false)
</script>
@@ -0,0 +1,87 @@
<template>
<LayoutDialog v-model:open="isOpen" max-width="md" :buttons="dialogButtons">
<template #header>Delete Project</template>
<div class="space-y-4">
<p>
Are you sure you want to permanently
<strong>delete {{ project.name }}</strong>
and all its contents, including
<strong>({{ project.models.totalCount }}) {{ modelText }}</strong>
<span v-if="project.commentThreads.totalCount">
and
<strong>
({{ project.commentThreads.totalCount }}) {{ discussionText }}
</strong>
</span>
?
</p>
<p>To confirm deletion, type the project name below and press Delete.</p>
<FormTextInput
v-model="projectNameInput"
name="projectNameConfirm"
label="Project name"
placeholder="Type the project name here"
full-width
hide-error-message
class="text-sm"
color="foundation"
/>
</div>
</LayoutDialog>
</template>
<script setup lang="ts">
import { LayoutDialog, FormTextInput } from '@speckle/ui-components'
import { useDeleteProject } from '~~/lib/projects/composables/projectManagement'
import { useMixpanel } from '~~/lib/core/composables/mp'
import type { ProjectPageSettingsGeneralBlockDelete_ProjectFragment } from '~~/lib/common/generated/gql/graphql'
import { Roles } from '@speckle/shared'
const isOpen = defineModel<boolean>('open', { required: true })
const props = defineProps<{
project: ProjectPageSettingsGeneralBlockDelete_ProjectFragment
}>()
const projectNameInput = ref('')
const deleteProject = useDeleteProject()
const mp = useMixpanel()
const modelText = computed(() =>
props.project.models.totalCount === 1 ? 'model' : 'models'
)
const discussionText = computed(() =>
props.project.commentThreads.totalCount === 1 ? 'discussion' : 'discussions'
)
const dialogButtons = computed(() => [
{
text: 'Cancel',
props: { color: 'secondary', fullWidth: true },
onClick: () => {
isOpen.value = false
projectNameInput.value = ''
}
},
{
text: 'Delete',
props: {
color: 'danger',
fullWidth: true,
outline: true,
disabled: projectNameInput.value !== props.project.name
},
onClick: async () => {
if (
projectNameInput.value === props.project.name &&
props.project.role === Roles.Stream.Owner
) {
await deleteProject(props.project.id, { goHome: true })
isOpen.value = false
mp.track('Stream Action', { type: 'action', name: 'delete' })
}
}
}
])
</script>
@@ -0,0 +1,95 @@
<template>
<ProjectPageSettingsBlock
background
title="Discussions"
:icon="ChatBubbleLeftRightIcon"
:disabled-message="disabled ? 'You must be a project owner' : undefined"
>
<template #introduction>
<p>Control who can leave comments on this project.</p>
</template>
<FormRadioGroup
v-model="selectedOption"
:disabled="isDisabled"
:options="radioOptions"
@update:model-value="emitUpdate"
/>
</ProjectPageSettingsBlock>
</template>
<script setup lang="ts">
import {
ChatBubbleLeftRightIcon,
UserGroupIcon,
UserCircleIcon
} from '@heroicons/vue/24/outline'
import { FormRadioGroup } from '@speckle/ui-components'
import { ProjectVisibility } from '~/lib/common/generated/gql/graphql'
import { graphql } from '~~/lib/common/generated/gql'
import type { ProjectPageSettingsGeneralBlockDiscussions_ProjectFragment } from '~~/lib/common/generated/gql/graphql'
graphql(`
fragment ProjectPageSettingsGeneralBlockDiscussions_Project on Project {
id
visibility
allowPublicComments
}
`)
const props = defineProps<{
project: ProjectPageSettingsGeneralBlockDiscussions_ProjectFragment
disabled?: boolean
}>()
const emit = defineEmits<{
(event: 'update-comments-permission', value: boolean): void
}>()
enum CommentPermission {
Anyone = 'anyone',
TeamMembers = 'teamMembers'
}
const selectedOption = ref(
props.project.allowPublicComments
? CommentPermission.Anyone
: CommentPermission.TeamMembers
)
const isDisabled = computed(
() => props.project.visibility === ProjectVisibility.Private || props.disabled
)
const radioOptions = computed(() => [
{
value: CommentPermission.Anyone,
title: 'Anyone',
introduction: 'Anyone can comment',
icon: UserGroupIcon
},
{
value: CommentPermission.TeamMembers,
title: 'Collaborators',
introduction: 'Only collaborators can comment',
icon: UserCircleIcon,
help:
props.project.visibility === ProjectVisibility.Private
? 'Only collaborators can comment on private projects'
: undefined
}
])
watch(
() => props.project.visibility,
(newVisibility) => {
if (newVisibility === ProjectVisibility.Private) {
selectedOption.value = CommentPermission.TeamMembers
}
},
{ immediate: true }
)
const emitUpdate = (value: CommentPermission) => {
emit('update-comments-permission', value === CommentPermission.Anyone)
}
</script>
@@ -0,0 +1,53 @@
<template>
<LayoutDialog v-model:open="isOpen" max-width="md" :buttons="dialogButtons">
<template #header>Leave Project</template>
<div class="space-y-4">
<p>Are you sure you want to leave this project?</p>
<p class="font-bold my-2">
Leaving this project removes your access to its data and functionalities.
</p>
<p>You can only rejoin if invited back by a project owner.</p>
</div>
</LayoutDialog>
</template>
<script setup lang="ts">
import { LayoutDialog } from '@speckle/ui-components'
import { useLeaveProject } from '~~/lib/projects/composables/projectManagement'
import { useMixpanel } from '~~/lib/core/composables/mp'
import type { ProjectPageSettingsGeneralBlockLeave_ProjectFragment } from '~~/lib/common/generated/gql/graphql'
const isOpen = defineModel<boolean>('open', { required: true })
const props = defineProps<{
project: ProjectPageSettingsGeneralBlockLeave_ProjectFragment
}>()
const leaveProject = useLeaveProject()
const mp = useMixpanel()
const dialogButtons = computed(() => [
{
text: 'Cancel',
props: { color: 'secondary', fullWidth: true, outline: true },
onClick: () => {
isOpen.value = false
}
},
{
text: 'Leave',
props: {
color: 'danger',
fullWidth: true,
outline: true,
submit: true
},
onClick: onLeave
}
])
const onLeave = async () => {
await leaveProject(props.project.id, { goHome: true })
mp.track('Stream Action', { type: 'action', name: 'leave' })
}
</script>
@@ -0,0 +1,64 @@
<template>
<div>
<ProjectPageSettingsBlock
v-if="canLeaveProject"
background
title="Leave Project"
:icon="ArrowRightOnRectangleIcon"
>
<p>
Remove yourself from this project. To join again you will need to get invited.
</p>
<template #bottom-buttons>
<FormButton color="danger" @click="showLeaveDialog = true">
Leave Project
</FormButton>
</template>
</ProjectPageSettingsBlock>
<ProjectPageSettingsGeneralBlockLeaveDialog
v-if="canLeaveProject"
v-model:open="showLeaveDialog"
:project="project"
/>
</div>
</template>
<script setup lang="ts">
import { ArrowRightOnRectangleIcon } from '@heroicons/vue/24/outline'
import { graphql } from '~~/lib/common/generated/gql'
import type { ProjectPageSettingsGeneralBlockLeave_ProjectFragment } from '~~/lib/common/generated/gql/graphql'
import { Roles } from '@speckle/shared'
graphql(`
fragment ProjectPageSettingsGeneralBlockLeave_Project on Project {
id
name
role
team {
role
user {
...LimitedUserAvatar
role
}
}
}
`)
const props = defineProps<{
project: ProjectPageSettingsGeneralBlockLeave_ProjectFragment
}>()
const showLeaveDialog = ref(false)
const { activeUser } = useActiveUser()
const canLeaveProject = computed(() => {
if (!activeUser.value || !props.project.role) {
return false
}
const userId = activeUser.value.id
const owners = props.project.team.filter((t) => t.role === Roles.Stream.Owner)
return owners.length !== 1 || owners[0].user.id !== userId
})
</script>
@@ -0,0 +1,156 @@
<template>
<div class="flex flex-col gap-4">
<ProjectPageSettingsBlock
background
title="Project Info"
:disabled-message="disabled ? 'You must be a project owner' : undefined"
:icon="PencilIcon"
>
<FormTextInput
v-model="localProjectName"
name="projectName"
label="Project Name"
placeholder="Project Name"
show-label
color="foundation"
class="mb-4"
:disabled="disabled"
/>
<FormTextArea
v-model="localProjectDescription"
name="projectDescription"
label="Project Description"
placeholder="Description (optional)"
show-label
color="foundation"
:disabled="disabled"
/>
<template #bottom-buttons>
<FormButton text :disabled="!hasChanges" @click="resetLocalState">
Cancel
</FormButton>
<FormButton :disabled="!hasChanges" @click="emitUpdate">Update</FormButton>
</template>
</ProjectPageSettingsBlock>
<LayoutDialog
v-model:open="showConfirmDialog"
max-width="md"
:buttons="dialogButtons"
>
<template #header>Unsaved Changes</template>
<div class="space-y-4">
<p>You have unsaved changes. Do you want to save them before leaving?</p>
</div>
</LayoutDialog>
</div>
</template>
<script setup lang="ts">
import { onBeforeRouteLeave, useRouter } from 'vue-router'
import { PencilIcon } from '@heroicons/vue/24/outline'
import {
FormTextInput,
FormTextArea,
FormButton,
LayoutDialog
} from '@speckle/ui-components'
import type { ProjectPageSettingsGeneralBlockProjectInfo_ProjectFragment } from '~~/lib/common/generated/gql/graphql'
import type { RouteLocationRaw } from 'vue-router'
import { graphql } from '~~/lib/common/generated/gql'
graphql(`
fragment ProjectPageSettingsGeneralBlockProjectInfo_Project on Project {
id
role
name
description
}
`)
const props = defineProps<{
project: ProjectPageSettingsGeneralBlockProjectInfo_ProjectFragment
disabled?: boolean
}>()
const emit = defineEmits(['update-project'])
const router = useRouter()
const targetRoute = ref<RouteLocationRaw | undefined>(undefined)
const localProjectName = ref(props.project.name)
const localProjectDescription = ref(props.project.description ?? '')
const showConfirmDialog = ref(false)
const hasChanges = computed(() => {
return (
localProjectName.value !== props.project.name ||
localProjectDescription.value !== props.project.description
)
})
const emitUpdate = () => {
emit('update-project', {
name: localProjectName.value,
description: localProjectDescription.value,
onComplete: handleRedirection
})
}
const handleRedirection = () => {
showConfirmDialog.value = false
resetLocalState()
if (targetRoute.value) {
router.push(targetRoute.value)
targetRoute.value = undefined
}
}
const resetLocalState = () => {
localProjectName.value = props.project.name
localProjectDescription.value = props.project.description ?? ''
showConfirmDialog.value = false
}
const dialogButtons = computed(() => [
{
text: 'Discard Changes',
props: { color: 'secondary', fullWidth: true, outline: true },
onClick: handleRedirection
},
{
text: 'Save Changes',
props: {
fullWidth: true,
outline: true,
submit: true
},
onClick: () => {
showConfirmDialog.value = false
emitUpdate()
}
}
])
watch(
() => props.project,
(newProject, oldProject) => {
if (newProject.name !== oldProject.name) {
localProjectName.value = newProject.name
}
if (newProject.description !== oldProject.description) {
localProjectDescription.value = newProject.description ?? ''
}
},
{ deep: true }
)
onBeforeRouteLeave((to, from, next) => {
if (hasChanges.value && !showConfirmDialog.value) {
targetRoute.value = to
showConfirmDialog.value = true
next(false)
} else {
next()
}
})
</script>
@@ -9,7 +9,7 @@
{{ props.webhook ? 'Edit Webhook' : 'Create Webhook' }}
</template>
<form @submit="onSubmit">
<div class="flex flex-col gap-6">
<div class="flex flex-col gap-4">
<FormTextInput
v-model="url"
label="URL"
@@ -19,6 +19,7 @@
show-required
:rules="[isRequired, isUrl]"
type="text"
color="foundation"
/>
<FormTextInput
v-model="description"
@@ -27,6 +28,7 @@
name="hookName"
show-label
type="text"
color="foundation"
/>
<FormTextInput
v-if="!props.webhook"
@@ -36,6 +38,7 @@
name="hookSecret"
show-label
type="text"
color="foundation"
/>
<FormSelectBadges
v-model="triggers"
@@ -106,15 +106,15 @@ const deleteConfirmed = async () => {
}
const dialogButtons = [
{
text: 'Delete',
props: { color: 'danger', fullWidth: true },
onClick: deleteConfirmed
},
{
text: 'Cancel',
props: { color: 'secondary', fullWidth: true, outline: true },
onClick: () => (isOpen.value = false)
},
{
text: 'Delete',
props: { color: 'danger', fullWidth: true },
onClick: deleteConfirmed
}
]
</script>
@@ -0,0 +1,7 @@
<template>
<ProjectEmptyState title="No webhooks, yet.">
<template #image>
<IconWebhooks class="h-24 w-24 mt-6 ml-9" />
</template>
</ProjectEmptyState>
</template>
@@ -0,0 +1,243 @@
<template>
<ProjectPageSettingsBlock title="Webhooks">
<template #introduction>
Subscribe to events and get notified in real time. Use to trigger CI apps,
automation workflows, and more.
</template>
<template #top-buttons>
<FormButton
color="secondary"
text-color="primary"
:icon-left="BookOpenIcon"
to="https://speckle.guide/dev/server-webhooks.html"
external
target="_blank"
>
Docs
</FormButton>
<FormButton :icon-left="PlusIcon" @click="openCreateWebhookDialog">
Create
</FormButton>
</template>
<template v-if="webhooks.length !== 0">
<LayoutTable
class="mt-6"
:columns="[
{ id: 'enabled', header: 'State', classes: 'col-span-1' },
{ id: 'data', header: 'Data', classes: 'col-span-5' },
{
id: 'triggers',
header: 'Trigger Events',
classes: 'col-span-6 whitespace-break-spaces text-xs'
}
]"
:items="webhooks"
:buttons="[
{
icon: PencilIcon,
label: 'Edit',
action: openEditWebhookDialog,
class: '!text-primary'
},
{
icon: TrashIcon,
label: 'Delete',
action: openDeleteWebhookDialog,
class: '!text-danger'
}
]"
>
<template #enabled="{ item }">
<FormSwitch
:model-value="!!item.enabled"
icons
class="scale-90"
@update:model-value="(newValue) => onEnabledChange(item, newValue)"
/>
</template>
<template #data="{ item }">
<div class="flex flex-col">
<h3
class="font-bold text-sm truncate"
:class="{ 'opacity-60': !item.enabled }"
>
{{ item.description }}
</h3>
<div class="flex gap-1 items-center">
<div class="h-4 w-4" :class="{ grayscale: !item.enabled }">
<InformationCircleIcon
v-if="getHistoryStatus(item) === HistoryStatus.NoEvents"
class="opacity-40"
/>
<CheckCircleIcon
v-if="getHistoryStatus(item) === HistoryStatus.Called"
class="text-success"
/>
<XCircleIcon
v-if="
[HistoryStatus.Alert, HistoryStatus.Error].includes(
getHistoryStatus(item)
)
"
class="text-danger"
/>
</div>
<span class="text-foreground opacity-50 text-xs truncate">
{{ getHistoryStatusInfo(item) }}
</span>
</div>
<span class="text-foreground opacity-50 text-xs truncate">
{{ item.url }}
</span>
</div>
</template>
<template #triggers="{ item }">
<div :class="{ 'opacity-60': !item.enabled }">
{{ formatTriggers(item) }}
</div>
</template>
</LayoutTable>
</template>
<template v-else>
<div class="mt-6">
<ProjectPageSettingsWebhooksEmptyState />
</div>
</template>
<ProjectPageSettingsWebhooksDeleteDialog
v-model:open="showDeleteWebhookDialog"
:webhook="webhookToModify"
/>
<ProjectPageSettingsWebhooksCreateOrEditDialog
v-model:open="showEditWebhookDialog"
:webhook="webhookToModify"
:stream-id="projectId"
@webhook-created="handleWebhookCreated"
/>
</ProjectPageSettingsBlock>
</template>
<script setup lang="ts">
import { useMutation, useQuery } from '@vue/apollo-composable'
import {
PlusIcon,
BookOpenIcon,
InformationCircleIcon,
CheckCircleIcon,
XCircleIcon
} from '@heroicons/vue/20/solid'
import { TrashIcon, PencilIcon } from '@heroicons/vue/24/outline'
import { FormSwitch, LayoutTable } from '@speckle/ui-components'
import { projectWebhooksQuery } from '~~/lib/projects/graphql/queries'
import { updateWebhookMutation } from '~~/lib/projects/graphql/mutations'
import { useGlobalToast } from '~~/lib/common/composables/toast'
import type { WebhookItem } from '~~/lib/projects/helpers/types'
import {
convertThrowIntoFetchResult,
getCacheId,
getFirstErrorMessage
} from '~~/lib/common/helpers/graphql'
import type { Optional } from '@speckle/shared'
const projectId = computed(() => route.params.id as string)
const route = useRoute()
const { result: pageResult, refetch: refetchWebhooks } = useQuery(
projectWebhooksQuery,
() => ({
projectId: projectId.value
})
)
const { triggerNotification } = useGlobalToast()
const { mutate: updateMutation } = useMutation(updateWebhookMutation)
const webhookToModify = ref<WebhookItem | null>(null)
const showDeleteWebhookDialog = ref(false)
const showEditWebhookDialog = ref(false)
const webhooks = computed<WebhookItem[]>(() => {
return pageResult.value?.project?.webhooks?.items || []
})
enum HistoryStatus {
NoEvents = 0,
Alert = 1,
Called = 2,
Error = 3
}
const getHistoryStatus = (item: WebhookItem) => {
const recentHistory = item.history?.items?.[0]
const status = recentHistory?.status as Optional<HistoryStatus>
return status || HistoryStatus.NoEvents
}
const getHistoryStatusInfo = (item: WebhookItem) => {
const recentHistory = item.history?.items?.[0]
return recentHistory ? recentHistory.statusInfo : 'No events yet'
}
const formatTriggers = (item: WebhookItem): string => {
return item.triggers
.map((event, index, array) => `"${event}"${index < array.length - 1 ? ',' : ''}`)
.join(' ')
}
const openDeleteWebhookDialog = (item: WebhookItem) => {
webhookToModify.value = item
showDeleteWebhookDialog.value = true
}
const openEditWebhookDialog = (item: WebhookItem) => {
webhookToModify.value = item
showEditWebhookDialog.value = true
}
const openCreateWebhookDialog = () => {
webhookToModify.value = null
showEditWebhookDialog.value = true
}
const handleWebhookCreated = () => {
refetchWebhooks()
}
const onEnabledChange = async (item: WebhookItem, newValue: boolean) => {
const result = await updateMutation(
{
webhook: {
streamId: projectId.value,
id: item.id,
enabled: newValue
}
},
{
update: (cache, { data }) => {
if (data?.webhookUpdate) {
cache.modify({
id: getCacheId('Webhook', item.id),
fields: {
enabled: () => newValue
}
})
}
}
}
).catch(convertThrowIntoFetchResult)
if (result?.data?.webhookUpdate) {
triggerNotification({
type: ToastNotificationType.Success,
title: newValue ? 'Webhook Enabled' : 'Webhook Disabled'
})
} else {
triggerNotification({
type: ToastNotificationType.Danger,
title: 'Failed to update webhook',
description: getFirstErrorMessage(result?.errors)
})
}
}
</script>
@@ -1,33 +0,0 @@
<template>
<ProjectPageStatsBlock>
<template #top>
<div class="flex flex-col sm:flex-row gap-x-1.5 sm:items-center">
<ChatBubbleOvalLeftIcon class="h-5 w-5" />
<span class="text-xs sm:text-sm">Threads</span>
</div>
</template>
<template #bottom>
<span v-if="project.commentThreadCount.totalCount" class="h2 font-bold">
{{ project.commentThreadCount.totalCount }}
</span>
<span v-else class="h2 font-bold text-slate-400 dark:text-neutral-700">0</span>
</template>
</ProjectPageStatsBlock>
</template>
<script setup lang="ts">
import { ChatBubbleOvalLeftIcon } from '@heroicons/vue/24/outline'
import { graphql } from '~~/lib/common/generated/gql'
import type { ProjectPageStatsBlockCommentsFragment } from '~~/lib/common/generated/gql/graphql'
graphql(`
fragment ProjectPageStatsBlockComments on Project {
commentThreadCount: commentThreads(limit: 0) {
totalCount
}
}
`)
defineProps<{
project: ProjectPageStatsBlockCommentsFragment
}>()
</script>
@@ -1,33 +0,0 @@
<template>
<ProjectPageStatsBlock>
<template #top>
<div class="flex flex-col sm:flex-row gap-x-1.5 sm:items-center">
<CubeIcon class="h-5 w-5" />
<span class="text-xs sm:text-sm">Models</span>
</div>
</template>
<template #bottom>
<span v-if="project.modelCount.totalCount" class="h2 font-bold">
{{ project.modelCount.totalCount }}
</span>
<span v-else class="h2 font-bold text-slate-400 dark:text-neutral-700">0</span>
</template>
</ProjectPageStatsBlock>
</template>
<script setup lang="ts">
import { CubeIcon } from '@heroicons/vue/24/outline'
import { graphql } from '~~/lib/common/generated/gql'
import type { ProjectPageStatsBlockModelsFragment } from '~~/lib/common/generated/gql/graphql'
graphql(`
fragment ProjectPageStatsBlockModels on Project {
modelCount: models(limit: 0) {
totalCount
}
}
`)
defineProps<{
project: ProjectPageStatsBlockModelsFragment
}>()
</script>
@@ -1,114 +0,0 @@
<template>
<ProjectPageStatsBlock>
<template #top>
<div class="flex items-center">
<div class="flex items-center justify-between w-full">
<div
v-if="activeUser"
class="flex items-center gap-0.5 flex-grow select-none"
>
<Cog6ToothIcon class="h-5 w-5" />
<span class="text-sm">Settings</span>
</div>
<div v-else class="flex items-center gap-0.5 flex-grow select-none">
<UsersIcon class="h-5 w-5" />
<span class="text-sm">Team</span>
</div>
<div class="flex items-center text-xs">
{{ project.role?.split(':').reverse()[0] }}
</div>
</div>
</div>
</template>
<template #bottom>
<div class="flex items-center justify-between mt-3">
<UserAvatarGroup :users="teamUsers" class="max-w-[104px]" />
<div v-if="activeUser">
<FormButton class="ml-2" @click="onButtonClick">
{{ project.role === 'stream:owner' ? 'Manage' : 'View' }}
</FormButton>
</div>
</div>
</template>
<template #default>
<ProjectPageTeamDialog
v-model:open="dialogOpen"
:project="project"
:open-section="openSection"
/>
</template>
</ProjectPageStatsBlock>
</template>
<script setup lang="ts">
import { Cog6ToothIcon, UsersIcon } from '@heroicons/vue/24/outline'
import type { Optional } from '@speckle/shared'
import { OpenSectionType } from '~/lib/projects/helpers/components'
import { useActiveUser } from '~~/lib/auth/composables/activeUser'
import { graphql } from '~~/lib/common/generated/gql'
import type { ProjectPageStatsBlockTeamFragment } from '~~/lib/common/generated/gql/graphql'
const { activeUser } = useActiveUser()
graphql(`
fragment ProjectPageStatsBlockTeam on Project {
id
role
team {
role
user {
...LimitedUserAvatar
}
}
...ProjectPageTeamDialog
}
`)
const props = defineProps<{
project: ProjectPageStatsBlockTeamFragment
}>()
const dialogOpen = ref(false)
const openSection = ref<OpenSectionType | undefined>()
const route = useRoute()
const router = useRouter()
const teamUsers = computed(() => props.project.team.map((t) => t.user))
const readDialogStateFromQuery = async () => {
const newSettings = route.query.settings as Optional<string | true>
let shouldShow = false
if (!newSettings) {
shouldShow = false
} else if (newSettings === 'invite') {
shouldShow = true
openSection.value = OpenSectionType.Invite
} else if (newSettings === 'access') {
shouldShow = true
openSection.value = OpenSectionType.Access
} else {
shouldShow = true
openSection.value = OpenSectionType.Team
}
if (shouldShow) {
dialogOpen.value = true
await router.replace({ query: { ...route.query, settings: undefined } })
}
}
const onButtonClick = () => {
openSection.value = OpenSectionType.Team
dialogOpen.value = true
}
watch(
() => route.query.settings,
(newSettings, oldSettings) => {
if (newSettings !== oldSettings) {
readDialogStateFromQuery()
}
},
{ immediate: true }
)
</script>
@@ -1,33 +0,0 @@
<template>
<ProjectPageStatsBlock>
<template #top>
<div class="flex flex-col sm:flex-row gap-x-1.5 sm:items-center">
<ArrowPathRoundedSquareIcon class="h-5 w-5" />
<span class="text-xs sm:text-sm">Versions</span>
</div>
</template>
<template #bottom>
<span v-if="project.versionCount.totalCount" class="h2 font-bold">
{{ project.versionCount.totalCount }}
</span>
<span v-else class="h2 font-bold text-slate-400 dark:text-neutral-700">0</span>
</template>
</ProjectPageStatsBlock>
</template>
<script setup lang="ts">
import { ArrowPathRoundedSquareIcon } from '@heroicons/vue/24/outline'
import { graphql } from '~~/lib/common/generated/gql'
import type { ProjectPageStatsBlockVersionsFragment } from '~~/lib/common/generated/gql/graphql'
graphql(`
fragment ProjectPageStatsBlockVersions on Project {
versionCount: versions(limit: 0) {
totalCount
}
}
`)
defineProps<{
project: ProjectPageStatsBlockVersionsFragment
}>()
</script>
@@ -0,0 +1,39 @@
<template>
<ProjectPageStatsBlock>
<template #top>
<div class="flex items-center">
<div class="flex items-center justify-between w-full">
<div class="flex items-center gap-1 flex-grow select-none">
<span class="text-foreground text-sm font-semibold">Collaborators</span>
</div>
<div class="flex items-center text-sm capitalize">
{{ project.role?.split(':').reverse()[0] }}
</div>
</div>
</div>
</template>
<template #bottom>
<div class="flex items-center justify-between mt-1">
<UserAvatarGroup :users="teamUsers" class="max-w-[104px]" />
<div v-if="activeUser">
<FormButton class="ml-2" :to="projectCollaboratorsRoute(project.id)">
Manage
</FormButton>
</div>
</div>
</template>
</ProjectPageStatsBlock>
</template>
<script setup lang="ts">
import { useActiveUser } from '~~/lib/auth/composables/activeUser'
import type { ProjectPageTeamInternals_ProjectFragment } from '~~/lib/common/generated/gql/graphql'
import { projectCollaboratorsRoute } from '~~/lib/common/helpers/route'
const props = defineProps<{
project: ProjectPageTeamInternals_ProjectFragment
}>()
const { activeUser } = useActiveUser()
const teamUsers = computed(() => props.project.team.map((t) => t.user))
</script>
@@ -1,32 +1,12 @@
<template>
<LayoutDialog v-model:open="isOpen" max-width="sm">
<template #header>Manage Project</template>
<div class="flex flex-col text-foreground">
<ProjectPageTeamDialogManageUsers
:always-open="openSection === OpenSectionType.Team"
:project="project"
/>
<ProjectPageTeamDialogInviteUser
v-if="isOwner && !isServerGuest"
:project="project"
:default-open="openSection === OpenSectionType.Invite"
/>
<ProjectPageTeamDialogManagePermissions
:project="project"
:default-open="openSection === OpenSectionType.Access"
/>
<ProjectPageTeamDialogWebhooks v-if="isOwner" :project="project" />
<ProjectPageTeamDialogDangerZones
v-if="isOwner || canLeaveProject"
:project="project"
/>
</div>
<div class="flex flex-col text-foreground"></div>
</LayoutDialog>
</template>
<script setup lang="ts">
import type { ProjectPageTeamDialogFragment } from '~~/lib/common/generated/gql/graphql'
import { graphql } from '~~/lib/common/generated/gql'
import { useTeamDialogInternals } from '~~/lib/projects/composables/team'
import { OpenSectionType } from '~~/lib/projects/helpers/components'
graphql(`
@@ -67,10 +47,6 @@ const props = defineProps<{
openSection?: OpenSectionType
}>()
const { isOwner, isServerGuest, canLeaveProject } = useTeamDialogInternals({
props: toRefs(props)
})
const isOpen = computed({
get: () => props.open,
set: (newVal) => emit('update:open', newVal)
@@ -1,134 +0,0 @@
<template>
<div>
<LayoutDialogSection
v-if="canLeaveProject"
border-b
title="Leave Project"
title-color="info"
>
<template #icon>
<ArrowRightOnRectangleIcon class="h-full w-full" />
</template>
<div
class="flex flex-col sm:flex-row sm:items-center gap-4 py-3 px-4 bg-info-lighter rounded-md select-none mb-4 text-info-darker text-sm"
>
<div>
<ExclamationTriangleIcon class="mt-0.5 h-12 w-12 text-info" />
</div>
<div class="">
<p class="text-sm">
As long as you're not the only owner you can remove yourself from this
project's list of collaborators.
</p>
<p class="font-semibold text-info-darker py-2">
Removing yourself from the collaborators list is an irreversible action.
</p>
<p class="text-sm">
The only way you can get back on the list is if a project owner invites you
back.
</p>
</div>
</div>
<div class="flex gap-2 mt-4">
<FormButton color="info" class="text-sm self-start" @click="onLeave">
Leave
</FormButton>
</div>
</LayoutDialogSection>
<LayoutDialogSection
v-if="isOwner && !isServerGuest"
title="Delete Project"
title-color="danger"
>
<template #icon>
<TrashIcon class="h-full w-full" />
</template>
<div
class="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4 py-3 px-4 bg-danger-lighter dark:bg-danger-darker rounded-md select-none mb-4"
>
<div>
<ExclamationTriangleIcon class="mt-0.5 h-12 w-12 text-danger" />
</div>
<div>
<p class="font-semibold text-danger-darker dark:text-danger-lighter">
Deleting a project is an irreversible action!
</p>
<p class="text-sm">
If you are sure you want to proceed, please type in the project name
<strong>{{ project.name }}</strong>
in the input field and press "Delete".
</p>
</div>
</div>
<form class="flex flex-col sm:flex-row gap-2 pb-2" @submit="onDelete">
<FormTextInput
name="projectName"
label="Project name"
placeholder="Project name"
:rules="[stringMatchesProjectName]"
full-width
validate-on-mount
validate-on-value-update
hide-error-message
class="text-sm"
/>
<FormButton
submit
:disabled="!!Object.values(deleteErrors).length"
color="danger"
>
Delete
</FormButton>
</form>
</LayoutDialogSection>
</div>
</template>
<script setup lang="ts">
import {
TrashIcon,
ArrowRightOnRectangleIcon,
ExclamationTriangleIcon
} from '@heroicons/vue/24/outline'
import { LayoutDialogSection } from '@speckle/ui-components'
import { useForm } from 'vee-validate'
import type { GenericValidateFunction } from 'vee-validate'
import type { ProjectPageTeamDialogFragment } from '~~/lib/common/generated/gql/graphql'
import { useMixpanel } from '~~/lib/core/composables/mp'
import {
useDeleteProject,
useLeaveProject
} from '~~/lib/projects/composables/projectManagement'
import { useTeamDialogInternals } from '~~/lib/projects/composables/team'
const stringMatchesProjectName: GenericValidateFunction<string> = (val: string) => {
return val === props.project.name ? true : 'Value must match the project name exactly'
}
const props = defineProps<{
project: ProjectPageTeamDialogFragment
}>()
const { handleSubmit: handleDeleteSubmit, errors: deleteErrors } = useForm<{
projectName: string
}>()
const { isOwner, canLeaveProject, isServerGuest } = useTeamDialogInternals({
props: toRefs(props)
})
const deleteProject = useDeleteProject()
const leaveProject = useLeaveProject()
const mp = useMixpanel()
const onDelete = handleDeleteSubmit(async () => {
if (!isOwner.value) return
await deleteProject(props.project.id, { goHome: true })
mp.track('Stream Action', { type: 'action', name: 'delete' })
})
const onLeave = async () => {
if (!canLeaveProject.value) return
await leaveProject(props.project.id, { goHome: true })
mp.track('Stream Action', { type: 'action', name: 'leave' })
}
</script>
@@ -63,9 +63,9 @@ const props = defineProps<{
defaultOpen: boolean
}>()
const { isOwner, isServerGuest } = useTeamManagePermissionsInternals({
props: toRefs(props)
})
const projectRef = toRef(props, 'project')
const { isOwner, isServerGuest } = useTeamManagePermissionsInternals(projectRef)
const updateProject = useUpdateProject()
const loading = ref(false)
@@ -1,134 +0,0 @@
<template>
<LayoutDialogSection class="-mt-4" title="Team">
<template #icon>
<UsersIcon class="h-full w-full" />
</template>
<div class="flex flex-col gap-2">
<div
class="flex flex-col border border-primary-muted max-h-40 overflow-auto simple-scrollbar"
>
<div
v-for="collaborator in collaboratorListItems"
:key="collaborator.id"
class="flex items-center space-x-2 even:bg-primary-muted py-1.5 px-2"
>
<UserAvatar :user="collaborator.user" size="sm" />
<span class="grow truncate text-xs">{{ collaborator.title }}</span>
<template v-if="!collaborator.inviteId">
<ProjectPageTeamPermissionSelect
v-if="canEdit && activeUser && collaborator.id !== activeUser.id"
class="shrink-0"
:model-value="collaborator.role"
:disabled="loading"
:hide-owner="collaborator.serverRole === Roles.Server.Guest"
@update:model-value="onCollaboratorRoleChange(collaborator, $event)"
@delete="onCollaboratorRoleChange(collaborator, null)"
/>
<span v-else class="shrink-0 text-xs">
{{ roleSelectItems[collaborator.role].title }}
</span>
</template>
<template v-else-if="canEdit">
<span class="shrink-0 text-foreground-2 text-xs">
{{ roleSelectItems[collaborator.role].title }}
</span>
<FormButton
class="shrink-0"
color="danger"
size="xs"
:disabled="loading"
@click="
cancelInvite({
projectId: project.id,
inviteId: collaborator.inviteId || ''
})
"
>
Cancel Invite
</FormButton>
</template>
</div>
</div>
</div>
</LayoutDialogSection>
</template>
<script setup lang="ts">
import { Roles } from '@speckle/shared'
import type { Nullable, StreamRoles } from '@speckle/shared'
import { useApolloClient } from '@vue/apollo-composable'
import { LayoutDialogSection } from '@speckle/ui-components'
import { useActiveUser } from '~~/lib/auth/composables/activeUser'
import type {
Project,
ProjectPageTeamDialogFragment
} from '~~/lib/common/generated/gql/graphql'
import {
getCacheId,
getObjectReference,
modifyObjectFields
} from '~~/lib/common/helpers/graphql'
import {
useCancelProjectInvite,
useUpdateUserRole
} from '~~/lib/projects/composables/projectManagement'
import { useTeamDialogInternals } from '~~/lib/projects/composables/team'
import { roleSelectItems } from '~~/lib/projects/helpers/components'
import type { ProjectCollaboratorListItem } from '~~/lib/projects/helpers/components'
import { UsersIcon } from '@heroicons/vue/24/outline'
import { useMixpanel } from '~~/lib/core/composables/mp'
const props = defineProps<{
project: ProjectPageTeamDialogFragment
}>()
const apollo = useApolloClient().client
const updateRole = useUpdateUserRole()
const cancelInvite = useCancelProjectInvite()
const { activeUser } = useActiveUser()
const { collaboratorListItems, isOwner, isServerGuest } = useTeamDialogInternals({
props: toRefs(props)
})
const mp = useMixpanel()
const loading = ref(false)
const canEdit = computed(() => isOwner.value && !isServerGuest.value)
const onCollaboratorRoleChange = async (
collaborator: ProjectCollaboratorListItem,
newRole: Nullable<StreamRoles>
) => {
if (collaborator.inviteId) return
loading.value = true
await updateRole({
projectId: props.project.id,
userId: collaborator.id,
role: newRole
})
loading.value = false
mp.track('Stream Action', {
type: 'action',
name: 'update',
action: 'team member role'
})
if (!newRole) {
// Remove from team
modifyObjectFields<undefined, Project['team']>(
apollo.cache,
getCacheId('Project', props.project.id),
(fieldName, _variables, value) => {
if (fieldName !== 'team') return
return value.filter(
(t) =>
!t.user ||
t.user.__ref !== getObjectReference('LimitedUser', collaborator.id).__ref
)
}
)
}
}
</script>
@@ -34,7 +34,7 @@
:show-label="false"
placeholder="Search"
color="foundation"
wrapper-classes="grow md:grow-0 md:w-60 hover:shadow rounded-md outline outline-2 outline-primary-muted"
wrapper-classes="grow md:grow-0 md:w-60"
:show-clear="!!search"
@change="updateSearchImmediately"
@update:model-value="updateDebouncedSearch"
@@ -3,7 +3,7 @@
<template #header>Get your colleagues in!</template>
<form @submit="onSubmit">
<div class="flex flex-col space-y-4 text-foreground">
<p class="text-sm mb-3">
<p class="text-sm mb-1">
Speckle will send a server invite link to the email(-s) below. You can also
add a personal message if you want to. To add multiple e-mails, seperate them
with commas.
@@ -13,6 +13,7 @@
<FormTextInput
:custom-icon="EnvelopeIcon"
name="emailsString"
color="foundation"
label="E-mail"
show-label
placeholder="example@example.com, example2@example.com"
@@ -38,6 +39,7 @@
name="message"
show-label
label="Message"
color="foundation"
:disabled="anyMutationsLoading"
:rules="[isStringOfLength({ maxLength: 1024 })]"
placeholder="Write an optional invitation message!"
@@ -7,6 +7,7 @@
v-model="name"
label="This server's public name"
name="serverName"
color="foundation"
placeholder="Server name"
show-label
:show-required="true"
@@ -15,6 +16,7 @@
/>
<FormTextArea
v-model="description"
color="foundation"
label="Description"
name="description"
placeholder="Description"
@@ -22,6 +24,7 @@
/>
<FormTextInput
v-model="company"
color="foundation"
label="Owner"
name="owner"
placeholder="Owner"
@@ -29,6 +32,7 @@
/>
<FormTextInput
v-model="adminContact"
color="foundation"
label="Admin Email"
name="adminEmail"
placeholder="Admin Email"
@@ -37,13 +41,12 @@
/>
<FormTextInput
v-model="termsOfService"
color="foundation"
label="Url pointing to the terms of service page"
name="terms"
show-label
/>
<div
class="rounded-lg px-3 py-2 sm:p-4 bg-primary-muted opacity-70 text-sm flex flex-col gap-2 mt-2"
>
<div class="text-sm flex flex-col gap-2 mt-2">
<FormCheckbox
v-model="inviteOnly"
label="Invite only mode - Only users with an invitation will be able to join"
@@ -8,6 +8,7 @@
<div class="flex flex-col space-y-4 w-full md:w-9/12">
<FormTextInput
v-model="name"
color="foundation"
label="Name"
name="name"
placeholder="John Doe"
@@ -19,6 +20,7 @@
/>
<FormTextInput
v-model="company"
color="foundation"
label="Company"
name="company"
placeholder="Example Ltd."
@@ -2,18 +2,24 @@
<LayoutDialog v-model:open="open" max-width="lg">
<template #header>Add Model</template>
<div class="flex flex-col gap-y-4">
<LayoutTabs v-slot="{ activeItem }" :items="tabItems">
<ViewerResourcesAddModelDialogModelTab
v-if="activeItem.id === 'model'"
@chosen="onModelChosen"
/>
<ViewerResourcesAddModelDialogObjectTab v-else @chosen="onObjectsChosen" />
</LayoutTabs>
<LayoutTabsHoriztonal v-model:active-item="activeTab" :items="tabItems">
<template #default="{ activeItem }">
<ViewerResourcesAddModelDialogModelTab
v-if="activeItem.id === 'model'"
@chosen="onModelChosen"
/>
<ViewerResourcesAddModelDialogObjectTab
v-else-if="activeItem.id === 'object'"
@chosen="onObjectsChosen"
/>
</template>
</LayoutTabsHoriztonal>
</div>
</LayoutDialog>
</template>
<script setup lang="ts">
import { SpeckleViewer } from '@speckle/shared'
import { LayoutTabsHoriztonal } from '@speckle/ui-components'
import { useMixpanel } from '~~/lib/core/composables/mp'
import type { LayoutTabItem } from '~~/lib/layout/helpers/components'
import { useInjectedViewerRequestedResources } from '~~/lib/viewer/composables/setup'
@@ -33,6 +39,8 @@ const tabItems = ref<LayoutTabItem[]>([
{ title: 'By object URL', id: 'object' }
])
const activeTab = ref(tabItems.value[0])
const open = computed({
get: () => props.open,
set: (newVal) => emit('update:open', newVal)
@@ -32,11 +32,9 @@ const documents = {
"\n fragment ProjectsModelPageEmbed_Project on Project {\n id\n ...ProjectsPageTeamDialogManagePermissions_Project\n }\n": types.ProjectsModelPageEmbed_ProjectFragmentDoc,
"\n fragment ProjectModelPageVersionsCardVersion on Version {\n id\n message\n authorUser {\n ...LimitedUserAvatar\n }\n createdAt\n previewUrl\n sourceApplication\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\n }\n ...ProjectModelPageDialogDeleteVersion\n ...ProjectModelPageDialogMoveToVersion\n ...ModelCardAutomationStatus_Version\n }\n": types.ProjectModelPageVersionsCardVersionFragmentDoc,
"\n fragment ProjectPageProjectHeader on Project {\n id\n role\n name\n description\n visibility\n allowPublicComments\n }\n": types.ProjectPageProjectHeaderFragmentDoc,
"\n fragment ProjectPageInviteDialog_Project on Project {\n id\n ...ProjectPageTeamInternals_Project\n }\n": types.ProjectPageInviteDialog_ProjectFragmentDoc,
"\n fragment ProjectDiscussionsPageHeader_Project on Project {\n id\n name\n }\n": types.ProjectDiscussionsPageHeader_ProjectFragmentDoc,
"\n fragment ProjectDiscussionsPageResults_Project on Project {\n id\n }\n": types.ProjectDiscussionsPageResults_ProjectFragmentDoc,
"\n fragment ProjectPageLatestItemsComments on Project {\n id\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\n }\n }\n": types.ProjectPageLatestItemsCommentsFragmentDoc,
"\n fragment ProjectPageLatestItemsCommentItem on Comment {\n id\n author {\n ...FormUsersSelectItem\n }\n screenshot\n rawText\n createdAt\n updatedAt\n archived\n repliesCount: replies(limit: 0) {\n totalCount\n }\n replyAuthors(limit: 4) {\n totalCount\n items {\n ...FormUsersSelectItem\n }\n }\n }\n": types.ProjectPageLatestItemsCommentItemFragmentDoc,
"\n fragment ProjectPageLatestItemsModels on Project {\n id\n role\n visibility\n modelCount: models(limit: 0) {\n totalCount\n }\n ...ProjectPageModelsStructureItem_Project\n }\n": types.ProjectPageLatestItemsModelsFragmentDoc,
"\n fragment ProjectPageModelsActions on Model {\n id\n name\n }\n": types.ProjectPageModelsActionsFragmentDoc,
"\n fragment ProjectPageModelsActions_Project on Project {\n id\n ...ProjectsModelPageEmbed_Project\n }\n": types.ProjectPageModelsActions_ProjectFragmentDoc,
"\n fragment ProjectPageModelsCardProject on Project {\n id\n role\n visibility\n ...ProjectPageModelsActions_Project\n }\n": types.ProjectPageModelsCardProjectFragmentDoc,
@@ -49,10 +47,13 @@ const documents = {
"\n fragment ModelCardAutomationStatus_Version on Version {\n id\n automationStatus {\n ...ModelCardAutomationStatus_AutomationsStatus\n }\n }\n": types.ModelCardAutomationStatus_VersionFragmentDoc,
"\n fragment ProjectPageModelsCardDeleteDialog on Model {\n id\n name\n }\n": types.ProjectPageModelsCardDeleteDialogFragmentDoc,
"\n fragment ProjectPageModelsCardRenameDialog on Model {\n id\n name\n description\n }\n": types.ProjectPageModelsCardRenameDialogFragmentDoc,
"\n fragment ProjectPageStatsBlockComments on Project {\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\n }\n }\n": types.ProjectPageStatsBlockCommentsFragmentDoc,
"\n fragment ProjectPageStatsBlockModels on Project {\n modelCount: models(limit: 0) {\n totalCount\n }\n }\n": types.ProjectPageStatsBlockModelsFragmentDoc,
"\n fragment ProjectPageStatsBlockTeam on Project {\n id\n role\n team {\n role\n user {\n ...LimitedUserAvatar\n }\n }\n ...ProjectPageTeamDialog\n }\n": types.ProjectPageStatsBlockTeamFragmentDoc,
"\n fragment ProjectPageStatsBlockVersions on Project {\n versionCount: versions(limit: 0) {\n totalCount\n }\n }\n": types.ProjectPageStatsBlockVersionsFragmentDoc,
"\n query ProjectPageSettingsCollaborators($projectId: String!) {\n project(id: $projectId) {\n id\n ...ProjectPageTeamInternals_Project\n ...ProjectPageInviteDialog_Project\n }\n }\n": types.ProjectPageSettingsCollaboratorsDocument,
"\n query ProjectPageSettingsGeneral($projectId: String!) {\n project(id: $projectId) {\n id\n role\n ...ProjectPageSettingsGeneralBlockProjectInfo_Project\n ...ProjectPageSettingsGeneralBlockAccess_Project\n ...ProjectPageSettingsGeneralBlockDiscussions_Project\n ...ProjectPageSettingsGeneralBlockLeave_Project\n ...ProjectPageSettingsGeneralBlockDelete_Project\n ...ProjectPageTeamInternals_Project\n }\n }\n": types.ProjectPageSettingsGeneralDocument,
"\n fragment ProjectPageSettingsGeneralBlockAccess_Project on Project {\n id\n visibility\n }\n": types.ProjectPageSettingsGeneralBlockAccess_ProjectFragmentDoc,
"\n fragment ProjectPageSettingsGeneralBlockDelete_Project on Project {\n id\n name\n role\n models(limit: 0) {\n totalCount\n }\n commentThreads(limit: 0) {\n totalCount\n }\n }\n": types.ProjectPageSettingsGeneralBlockDelete_ProjectFragmentDoc,
"\n fragment ProjectPageSettingsGeneralBlockDiscussions_Project on Project {\n id\n visibility\n allowPublicComments\n }\n": types.ProjectPageSettingsGeneralBlockDiscussions_ProjectFragmentDoc,
"\n fragment ProjectPageSettingsGeneralBlockLeave_Project on Project {\n id\n name\n role\n team {\n role\n user {\n ...LimitedUserAvatar\n role\n }\n }\n }\n": types.ProjectPageSettingsGeneralBlockLeave_ProjectFragmentDoc,
"\n fragment ProjectPageSettingsGeneralBlockProjectInfo_Project on Project {\n id\n role\n name\n description\n }\n": types.ProjectPageSettingsGeneralBlockProjectInfo_ProjectFragmentDoc,
"\n fragment ProjectPageTeamDialog on Project {\n id\n name\n role\n allowPublicComments\n visibility\n team {\n role\n user {\n ...LimitedUserAvatar\n role\n }\n }\n invitedTeam {\n id\n title\n inviteId\n role\n user {\n ...LimitedUserAvatar\n role\n }\n }\n ...ProjectsPageTeamDialogManagePermissions_Project\n }\n": types.ProjectPageTeamDialogFragmentDoc,
"\n fragment ProjectsPageTeamDialogManagePermissions_Project on Project {\n id\n visibility\n allowPublicComments\n role\n }\n": types.ProjectsPageTeamDialogManagePermissions_ProjectFragmentDoc,
"\n subscription OnUserProjectsUpdate {\n userProjectsUpdated {\n type\n id\n project {\n ...ProjectDashboardItem\n }\n }\n }\n": types.OnUserProjectsUpdateDocument,
@@ -90,11 +91,15 @@ const documents = {
"\n query DeveloperSettingsApplications {\n activeUser {\n createdApps {\n id\n secret\n name\n description\n redirectUrl\n scopes {\n name\n description\n }\n }\n id\n }\n }\n": types.DeveloperSettingsApplicationsDocument,
"\n query DeveloperSettingsAuthorizedApps {\n activeUser {\n id\n authorizedApps {\n id\n description\n name\n author {\n id\n name\n avatar\n }\n }\n }\n }\n": types.DeveloperSettingsAuthorizedAppsDocument,
"\n query SearchProjects($search: String, $onlyWithRoles: [String!] = null) {\n activeUser {\n projects(limit: 10, filter: { search: $search, onlyWithRoles: $onlyWithRoles }) {\n totalCount\n items {\n ...FormSelectProjects_Project\n }\n }\n }\n }\n": types.SearchProjectsDocument,
"\n fragment ProjectPageTeamInternals_Project on Project {\n id\n role\n invitedTeam {\n id\n title\n role\n inviteId\n user {\n role\n ...LimitedUserAvatar\n }\n }\n team {\n role\n user {\n role\n ...LimitedUserAvatar\n }\n }\n }\n": types.ProjectPageTeamInternals_ProjectFragmentDoc,
"\n fragment ProjectDashboardItemNoModels on Project {\n id\n name\n createdAt\n updatedAt\n role\n team {\n user {\n id\n name\n avatar\n }\n }\n ...ProjectPageModelsCardProject\n }\n": types.ProjectDashboardItemNoModelsFragmentDoc,
"\n fragment ProjectDashboardItem on Project {\n id\n ...ProjectDashboardItemNoModels\n models(limit: 4, filter: { onlyWithVersions: true }) {\n totalCount\n items {\n ...ProjectPageLatestItemsModelItem\n }\n }\n pendingImportedModels(limit: 4) {\n ...PendingFileUpload\n }\n }\n": types.ProjectDashboardItemFragmentDoc,
"\n fragment PendingFileUpload on FileUpload {\n id\n projectId\n modelName\n convertedStatus\n convertedMessage\n uploadDate\n convertedLastUpdate\n fileType\n fileName\n }\n": types.PendingFileUploadFragmentDoc,
"\n fragment ProjectPageLatestItemsModelItem on Model {\n id\n name\n displayName\n versionCount: versions(limit: 0) {\n totalCount\n }\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\n }\n pendingImportedVersions(limit: 1) {\n ...PendingFileUpload\n }\n previewUrl\n createdAt\n updatedAt\n ...ProjectPageModelsCardRenameDialog\n ...ProjectPageModelsCardDeleteDialog\n ...ProjectPageModelsActions\n ...ModelCardAutomationStatus_Model\n }\n": types.ProjectPageLatestItemsModelItemFragmentDoc,
"\n fragment ProjectUpdatableMetadata on Project {\n id\n name\n description\n visibility\n allowPublicComments\n }\n": types.ProjectUpdatableMetadataFragmentDoc,
"\n fragment ProjectPageLatestItemsModels on Project {\n id\n role\n visibility\n modelCount: models(limit: 0) {\n totalCount\n }\n ...ProjectPageModelsStructureItem_Project\n }\n": types.ProjectPageLatestItemsModelsFragmentDoc,
"\n fragment ProjectPageLatestItemsComments on Project {\n id\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\n }\n }\n": types.ProjectPageLatestItemsCommentsFragmentDoc,
"\n fragment ProjectPageLatestItemsCommentItem on Comment {\n id\n author {\n ...FormUsersSelectItem\n }\n screenshot\n rawText\n createdAt\n updatedAt\n archived\n repliesCount: replies(limit: 0) {\n totalCount\n }\n replyAuthors(limit: 4) {\n totalCount\n items {\n ...FormUsersSelectItem\n }\n }\n }\n": types.ProjectPageLatestItemsCommentItemFragmentDoc,
"\n mutation CreateModel($input: CreateModelInput!) {\n modelMutations {\n create(input: $input) {\n ...ProjectPageLatestItemsModelItem\n }\n }\n }\n": types.CreateModelDocument,
"\n mutation CreateProject($input: ProjectCreateInput) {\n projectMutations {\n create(input: $input) {\n ...ProjectPageProject\n ...ProjectDashboardItem\n }\n }\n }\n": types.CreateProjectDocument,
"\n mutation UpdateModel($input: UpdateModelInput!) {\n modelMutations {\n update(input: $input) {\n ...ProjectPageLatestItemsModelItem\n }\n }\n }\n": types.UpdateModelDocument,
@@ -173,7 +178,8 @@ const documents = {
"\n query LegacyBranchRedirectMetadata($streamId: String!, $branchName: String!) {\n stream(id: $streamId) {\n branch(name: $branchName) {\n id\n }\n }\n }\n": types.LegacyBranchRedirectMetadataDocument,
"\n query LegacyViewerCommitRedirectMetadata($streamId: String!, $commitId: String!) {\n stream(id: $streamId) {\n commit(id: $commitId) {\n id\n branch {\n id\n }\n }\n }\n }\n": types.LegacyViewerCommitRedirectMetadataDocument,
"\n query ResolveCommentLink($commentId: String!, $projectId: String!) {\n comment(id: $commentId, streamId: $projectId) {\n ...LinkableComment\n }\n }\n": types.ResolveCommentLinkDocument,
"\n fragment ProjectPageProject on Project {\n id\n createdAt\n ...ProjectPageProjectHeader\n ...ProjectPageStatsBlockTeam\n ...ProjectPageTeamDialog\n ...ProjectPageStatsBlockVersions\n ...ProjectPageStatsBlockModels\n ...ProjectPageStatsBlockComments\n ...ProjectPageLatestItemsModels\n ...ProjectPageLatestItemsComments\n }\n": types.ProjectPageProjectFragmentDoc,
"\n fragment ProjectPageProject on Project {\n id\n createdAt\n modelCount: models(limit: 0) {\n totalCount\n }\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\n }\n ...ProjectPageProjectHeader\n ...ProjectPageTeamDialog\n }\n": types.ProjectPageProjectFragmentDoc,
"\n fragment ProjectPageSettingsTab_Project on Project {\n id\n role\n }\n": types.ProjectPageSettingsTab_ProjectFragmentDoc,
};
/**
@@ -266,6 +272,10 @@ export function graphql(source: "\n fragment ProjectModelPageVersionsCardVersio
* 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 ProjectPageProjectHeader on Project {\n id\n role\n name\n description\n visibility\n allowPublicComments\n }\n"): (typeof documents)["\n fragment ProjectPageProjectHeader on Project {\n id\n role\n name\n description\n visibility\n allowPublicComments\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 ProjectPageInviteDialog_Project on Project {\n id\n ...ProjectPageTeamInternals_Project\n }\n"): (typeof documents)["\n fragment ProjectPageInviteDialog_Project on Project {\n id\n ...ProjectPageTeamInternals_Project\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
@@ -274,18 +284,6 @@ export function graphql(source: "\n fragment ProjectDiscussionsPageHeader_Proje
* 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 ProjectDiscussionsPageResults_Project on Project {\n id\n }\n"): (typeof documents)["\n fragment ProjectDiscussionsPageResults_Project on Project {\n id\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 ProjectPageLatestItemsComments on Project {\n id\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\n }\n }\n"): (typeof documents)["\n fragment ProjectPageLatestItemsComments on Project {\n id\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\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 ProjectPageLatestItemsCommentItem on Comment {\n id\n author {\n ...FormUsersSelectItem\n }\n screenshot\n rawText\n createdAt\n updatedAt\n archived\n repliesCount: replies(limit: 0) {\n totalCount\n }\n replyAuthors(limit: 4) {\n totalCount\n items {\n ...FormUsersSelectItem\n }\n }\n }\n"): (typeof documents)["\n fragment ProjectPageLatestItemsCommentItem on Comment {\n id\n author {\n ...FormUsersSelectItem\n }\n screenshot\n rawText\n createdAt\n updatedAt\n archived\n repliesCount: replies(limit: 0) {\n totalCount\n }\n replyAuthors(limit: 4) {\n totalCount\n items {\n ...FormUsersSelectItem\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 ProjectPageLatestItemsModels on Project {\n id\n role\n visibility\n modelCount: models(limit: 0) {\n totalCount\n }\n ...ProjectPageModelsStructureItem_Project\n }\n"): (typeof documents)["\n fragment ProjectPageLatestItemsModels on Project {\n id\n role\n visibility\n modelCount: models(limit: 0) {\n totalCount\n }\n ...ProjectPageModelsStructureItem_Project\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
@@ -337,19 +335,31 @@ export function graphql(source: "\n fragment ProjectPageModelsCardRenameDialog
/**
* 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 ProjectPageStatsBlockComments on Project {\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\n }\n }\n"): (typeof documents)["\n fragment ProjectPageStatsBlockComments on Project {\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\n }\n }\n"];
export function graphql(source: "\n query ProjectPageSettingsCollaborators($projectId: String!) {\n project(id: $projectId) {\n id\n ...ProjectPageTeamInternals_Project\n ...ProjectPageInviteDialog_Project\n }\n }\n"): (typeof documents)["\n query ProjectPageSettingsCollaborators($projectId: String!) {\n project(id: $projectId) {\n id\n ...ProjectPageTeamInternals_Project\n ...ProjectPageInviteDialog_Project\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 ProjectPageStatsBlockModels on Project {\n modelCount: models(limit: 0) {\n totalCount\n }\n }\n"): (typeof documents)["\n fragment ProjectPageStatsBlockModels on Project {\n modelCount: models(limit: 0) {\n totalCount\n }\n }\n"];
export function graphql(source: "\n query ProjectPageSettingsGeneral($projectId: String!) {\n project(id: $projectId) {\n id\n role\n ...ProjectPageSettingsGeneralBlockProjectInfo_Project\n ...ProjectPageSettingsGeneralBlockAccess_Project\n ...ProjectPageSettingsGeneralBlockDiscussions_Project\n ...ProjectPageSettingsGeneralBlockLeave_Project\n ...ProjectPageSettingsGeneralBlockDelete_Project\n ...ProjectPageTeamInternals_Project\n }\n }\n"): (typeof documents)["\n query ProjectPageSettingsGeneral($projectId: String!) {\n project(id: $projectId) {\n id\n role\n ...ProjectPageSettingsGeneralBlockProjectInfo_Project\n ...ProjectPageSettingsGeneralBlockAccess_Project\n ...ProjectPageSettingsGeneralBlockDiscussions_Project\n ...ProjectPageSettingsGeneralBlockLeave_Project\n ...ProjectPageSettingsGeneralBlockDelete_Project\n ...ProjectPageTeamInternals_Project\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 ProjectPageStatsBlockTeam on Project {\n id\n role\n team {\n role\n user {\n ...LimitedUserAvatar\n }\n }\n ...ProjectPageTeamDialog\n }\n"): (typeof documents)["\n fragment ProjectPageStatsBlockTeam on Project {\n id\n role\n team {\n role\n user {\n ...LimitedUserAvatar\n }\n }\n ...ProjectPageTeamDialog\n }\n"];
export function graphql(source: "\n fragment ProjectPageSettingsGeneralBlockAccess_Project on Project {\n id\n visibility\n }\n"): (typeof documents)["\n fragment ProjectPageSettingsGeneralBlockAccess_Project on Project {\n id\n visibility\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 ProjectPageStatsBlockVersions on Project {\n versionCount: versions(limit: 0) {\n totalCount\n }\n }\n"): (typeof documents)["\n fragment ProjectPageStatsBlockVersions on Project {\n versionCount: versions(limit: 0) {\n totalCount\n }\n }\n"];
export function graphql(source: "\n fragment ProjectPageSettingsGeneralBlockDelete_Project on Project {\n id\n name\n role\n models(limit: 0) {\n totalCount\n }\n commentThreads(limit: 0) {\n totalCount\n }\n }\n"): (typeof documents)["\n fragment ProjectPageSettingsGeneralBlockDelete_Project on Project {\n id\n name\n role\n models(limit: 0) {\n totalCount\n }\n commentThreads(limit: 0) {\n totalCount\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 ProjectPageSettingsGeneralBlockDiscussions_Project on Project {\n id\n visibility\n allowPublicComments\n }\n"): (typeof documents)["\n fragment ProjectPageSettingsGeneralBlockDiscussions_Project on Project {\n id\n visibility\n allowPublicComments\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 ProjectPageSettingsGeneralBlockLeave_Project on Project {\n id\n name\n role\n team {\n role\n user {\n ...LimitedUserAvatar\n role\n }\n }\n }\n"): (typeof documents)["\n fragment ProjectPageSettingsGeneralBlockLeave_Project on Project {\n id\n name\n role\n team {\n role\n user {\n ...LimitedUserAvatar\n role\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 ProjectPageSettingsGeneralBlockProjectInfo_Project on Project {\n id\n role\n name\n description\n }\n"): (typeof documents)["\n fragment ProjectPageSettingsGeneralBlockProjectInfo_Project on Project {\n id\n role\n name\n description\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
@@ -498,6 +508,10 @@ export function graphql(source: "\n query DeveloperSettingsAuthorizedApps {\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 SearchProjects($search: String, $onlyWithRoles: [String!] = null) {\n activeUser {\n projects(limit: 10, filter: { search: $search, onlyWithRoles: $onlyWithRoles }) {\n totalCount\n items {\n ...FormSelectProjects_Project\n }\n }\n }\n }\n"): (typeof documents)["\n query SearchProjects($search: String, $onlyWithRoles: [String!] = null) {\n activeUser {\n projects(limit: 10, filter: { search: $search, onlyWithRoles: $onlyWithRoles }) {\n totalCount\n items {\n ...FormSelectProjects_Project\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 ProjectPageTeamInternals_Project on Project {\n id\n role\n invitedTeam {\n id\n title\n role\n inviteId\n user {\n role\n ...LimitedUserAvatar\n }\n }\n team {\n role\n user {\n role\n ...LimitedUserAvatar\n }\n }\n }\n"): (typeof documents)["\n fragment ProjectPageTeamInternals_Project on Project {\n id\n role\n invitedTeam {\n id\n title\n role\n inviteId\n user {\n role\n ...LimitedUserAvatar\n }\n }\n team {\n role\n user {\n role\n ...LimitedUserAvatar\n }\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
@@ -518,6 +532,18 @@ export function graphql(source: "\n fragment ProjectPageLatestItemsModelItem 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 ProjectUpdatableMetadata on Project {\n id\n name\n description\n visibility\n allowPublicComments\n }\n"): (typeof documents)["\n fragment ProjectUpdatableMetadata on Project {\n id\n name\n description\n visibility\n allowPublicComments\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 ProjectPageLatestItemsModels on Project {\n id\n role\n visibility\n modelCount: models(limit: 0) {\n totalCount\n }\n ...ProjectPageModelsStructureItem_Project\n }\n"): (typeof documents)["\n fragment ProjectPageLatestItemsModels on Project {\n id\n role\n visibility\n modelCount: models(limit: 0) {\n totalCount\n }\n ...ProjectPageModelsStructureItem_Project\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 ProjectPageLatestItemsComments on Project {\n id\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\n }\n }\n"): (typeof documents)["\n fragment ProjectPageLatestItemsComments on Project {\n id\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\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 ProjectPageLatestItemsCommentItem on Comment {\n id\n author {\n ...FormUsersSelectItem\n }\n screenshot\n rawText\n createdAt\n updatedAt\n archived\n repliesCount: replies(limit: 0) {\n totalCount\n }\n replyAuthors(limit: 4) {\n totalCount\n items {\n ...FormUsersSelectItem\n }\n }\n }\n"): (typeof documents)["\n fragment ProjectPageLatestItemsCommentItem on Comment {\n id\n author {\n ...FormUsersSelectItem\n }\n screenshot\n rawText\n createdAt\n updatedAt\n archived\n repliesCount: replies(limit: 0) {\n totalCount\n }\n replyAuthors(limit: 4) {\n totalCount\n items {\n ...FormUsersSelectItem\n }\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
@@ -833,7 +859,11 @@ export function graphql(source: "\n query ResolveCommentLink($commentId: 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 fragment ProjectPageProject on Project {\n id\n createdAt\n ...ProjectPageProjectHeader\n ...ProjectPageStatsBlockTeam\n ...ProjectPageTeamDialog\n ...ProjectPageStatsBlockVersions\n ...ProjectPageStatsBlockModels\n ...ProjectPageStatsBlockComments\n ...ProjectPageLatestItemsModels\n ...ProjectPageLatestItemsComments\n }\n"): (typeof documents)["\n fragment ProjectPageProject on Project {\n id\n createdAt\n ...ProjectPageProjectHeader\n ...ProjectPageStatsBlockTeam\n ...ProjectPageTeamDialog\n ...ProjectPageStatsBlockVersions\n ...ProjectPageStatsBlockModels\n ...ProjectPageStatsBlockComments\n ...ProjectPageLatestItemsModels\n ...ProjectPageLatestItemsComments\n }\n"];
export function graphql(source: "\n fragment ProjectPageProject on Project {\n id\n createdAt\n modelCount: models(limit: 0) {\n totalCount\n }\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\n }\n ...ProjectPageProjectHeader\n ...ProjectPageTeamDialog\n }\n"): (typeof documents)["\n fragment ProjectPageProject on Project {\n id\n createdAt\n modelCount: models(limit: 0) {\n totalCount\n }\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\n }\n ...ProjectPageProjectHeader\n ...ProjectPageTeamDialog\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 ProjectPageSettingsTab_Project on Project {\n id\n role\n }\n"): (typeof documents)["\n fragment ProjectPageSettingsTab_Project on Project {\n id\n role\n }\n"];
export function graphql(source: string) {
return (documents as any)[source] ?? {};
@@ -3007,16 +3007,12 @@ export type ProjectModelPageVersionsCardVersionFragment = { __typename?: 'Versio
export type ProjectPageProjectHeaderFragment = { __typename?: 'Project', id: string, role?: string | null, name: string, description?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean };
export type ProjectPageInviteDialog_ProjectFragment = { __typename?: 'Project', id: string, role?: string | null, invitedTeam?: Array<{ __typename?: 'PendingStreamCollaborator', id: string, title: string, role: string, inviteId: string, user?: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } | null }> | null, team: Array<{ __typename?: 'ProjectCollaborator', role: string, user: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } }> };
export type ProjectDiscussionsPageHeader_ProjectFragment = { __typename?: 'Project', id: string, name: string };
export type ProjectDiscussionsPageResults_ProjectFragment = { __typename?: 'Project', id: string };
export type ProjectPageLatestItemsCommentsFragment = { __typename?: 'Project', id: string, commentThreadCount: { __typename?: 'ProjectCommentCollection', totalCount: number } };
export type ProjectPageLatestItemsCommentItemFragment = { __typename?: 'Comment', id: string, screenshot?: string | null, rawText: string, createdAt: string, updatedAt: string, archived: boolean, author: { __typename?: 'LimitedUser', id: string, name: string, avatar?: string | null }, repliesCount: { __typename?: 'CommentCollection', totalCount: number }, replyAuthors: { __typename?: 'CommentReplyAuthorCollection', totalCount: number, items: Array<{ __typename?: 'LimitedUser', id: string, name: string, avatar?: string | null }> } };
export type ProjectPageLatestItemsModelsFragment = { __typename?: 'Project', id: string, role?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, modelCount: { __typename?: 'ModelCollection', totalCount: number } };
export type ProjectPageModelsActionsFragment = { __typename?: 'Model', id: string, name: string };
export type ProjectPageModelsActions_ProjectFragment = { __typename?: 'Project', id: string, visibility: ProjectVisibility, allowPublicComments: boolean, role?: string | null };
@@ -3041,13 +3037,29 @@ export type ProjectPageModelsCardDeleteDialogFragment = { __typename?: 'Model',
export type ProjectPageModelsCardRenameDialogFragment = { __typename?: 'Model', id: string, name: string, description?: string | null };
export type ProjectPageStatsBlockCommentsFragment = { __typename?: 'Project', commentThreadCount: { __typename?: 'ProjectCommentCollection', totalCount: number } };
export type ProjectPageSettingsCollaboratorsQueryVariables = Exact<{
projectId: Scalars['String'];
}>;
export type ProjectPageStatsBlockModelsFragment = { __typename?: 'Project', modelCount: { __typename?: 'ModelCollection', totalCount: number } };
export type ProjectPageStatsBlockTeamFragment = { __typename?: 'Project', id: string, role?: string | null, name: string, allowPublicComments: boolean, visibility: ProjectVisibility, team: Array<{ __typename?: 'ProjectCollaborator', role: string, user: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } }>, invitedTeam?: Array<{ __typename?: 'PendingStreamCollaborator', id: string, title: string, inviteId: string, role: string, user?: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } | null }> | null };
export type ProjectPageSettingsCollaboratorsQuery = { __typename?: 'Query', project: { __typename?: 'Project', id: string, role?: string | null, invitedTeam?: Array<{ __typename?: 'PendingStreamCollaborator', id: string, title: string, role: string, inviteId: string, user?: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } | null }> | null, team: Array<{ __typename?: 'ProjectCollaborator', role: string, user: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } }> } };
export type ProjectPageStatsBlockVersionsFragment = { __typename?: 'Project', versionCount: { __typename?: 'VersionCollection', totalCount: number } };
export type ProjectPageSettingsGeneralQueryVariables = Exact<{
projectId: Scalars['String'];
}>;
export type ProjectPageSettingsGeneralQuery = { __typename?: 'Query', project: { __typename?: 'Project', id: string, role?: string | null, name: string, description?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, team: Array<{ __typename?: 'ProjectCollaborator', role: string, user: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } }>, models: { __typename?: 'ModelCollection', totalCount: number }, commentThreads: { __typename?: 'ProjectCommentCollection', totalCount: number }, invitedTeam?: Array<{ __typename?: 'PendingStreamCollaborator', id: string, title: string, role: string, inviteId: string, user?: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } | null }> | null } };
export type ProjectPageSettingsGeneralBlockAccess_ProjectFragment = { __typename?: 'Project', id: string, visibility: ProjectVisibility };
export type ProjectPageSettingsGeneralBlockDelete_ProjectFragment = { __typename?: 'Project', id: string, name: string, role?: string | null, models: { __typename?: 'ModelCollection', totalCount: number }, commentThreads: { __typename?: 'ProjectCommentCollection', totalCount: number } };
export type ProjectPageSettingsGeneralBlockDiscussions_ProjectFragment = { __typename?: 'Project', id: string, visibility: ProjectVisibility, allowPublicComments: boolean };
export type ProjectPageSettingsGeneralBlockLeave_ProjectFragment = { __typename?: 'Project', id: string, name: string, role?: string | null, team: Array<{ __typename?: 'ProjectCollaborator', role: string, user: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } }> };
export type ProjectPageSettingsGeneralBlockProjectInfo_ProjectFragment = { __typename?: 'Project', id: string, role?: string | null, name: string, description?: string | null };
export type ProjectPageTeamDialogFragment = { __typename?: 'Project', id: string, name: string, role?: string | null, allowPublicComments: boolean, visibility: ProjectVisibility, team: Array<{ __typename?: 'ProjectCollaborator', role: string, user: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } }>, invitedTeam?: Array<{ __typename?: 'PendingStreamCollaborator', id: string, title: string, inviteId: string, role: string, user?: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } | null }> | null };
@@ -3088,7 +3100,7 @@ export type ActiveUserMainMetadataQuery = { __typename?: 'Query', activeUser?: {
export type CreateOnboardingProjectMutationVariables = Exact<{ [key: string]: never; }>;
export type CreateOnboardingProjectMutation = { __typename?: 'Mutation', projectMutations: { __typename?: 'ProjectMutations', createForOnboarding: { __typename?: 'Project', id: string, createdAt: string, role?: string | null, name: string, description?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, updatedAt: string, models: { __typename?: 'ModelCollection', totalCount: number, items: Array<{ __typename?: 'Model', id: string, name: string, displayName: string, previewUrl?: string | null, createdAt: string, updatedAt: string, description?: string | null, versionCount: { __typename?: 'VersionCollection', totalCount: number }, commentThreadCount: { __typename?: 'CommentCollection', totalCount: number }, pendingImportedVersions: Array<{ __typename?: 'FileUpload', id: string, projectId: string, modelName: string, convertedStatus: number, convertedMessage?: string | null, uploadDate: string, convertedLastUpdate: string, fileType: string, fileName: string }>, automationStatus?: { __typename?: 'AutomationsStatus', id: string, status: AutomationRunStatus, statusMessage?: string | null, automationRuns: Array<{ __typename?: 'AutomationRun', id: string, automationId: string, automationName: string, createdAt: string, status: AutomationRunStatus, functionRuns: Array<{ __typename?: 'AutomationFunctionRun', id: string, functionId: string, functionName: string, functionLogo?: string | null, elapsed: number, status: AutomationRunStatus, statusMessage?: string | null, contextView?: string | null, results?: {} | null, resultVersions: Array<{ __typename?: 'Version', id: string, model: { __typename?: 'Model', id: string, name: string } }> }> }> } | null }> }, pendingImportedModels: Array<{ __typename?: 'FileUpload', id: string, projectId: string, modelName: string, convertedStatus: number, convertedMessage?: string | null, uploadDate: string, convertedLastUpdate: string, fileType: string, fileName: string }>, team: Array<{ __typename?: 'ProjectCollaborator', role: string, user: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } }>, invitedTeam?: Array<{ __typename?: 'PendingStreamCollaborator', id: string, title: string, inviteId: string, role: string, user?: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } | null }> | null, versionCount: { __typename?: 'VersionCollection', totalCount: number }, modelCount: { __typename?: 'ModelCollection', totalCount: number }, commentThreadCount: { __typename?: 'ProjectCommentCollection', totalCount: number } } } };
export type CreateOnboardingProjectMutation = { __typename?: 'Mutation', projectMutations: { __typename?: 'ProjectMutations', createForOnboarding: { __typename?: 'Project', id: string, createdAt: string, role?: string | null, name: string, description?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, updatedAt: string, modelCount: { __typename?: 'ModelCollection', totalCount: number }, commentThreadCount: { __typename?: 'ProjectCommentCollection', totalCount: number }, models: { __typename?: 'ModelCollection', totalCount: number, items: Array<{ __typename?: 'Model', id: string, name: string, displayName: string, previewUrl?: string | null, createdAt: string, updatedAt: string, description?: string | null, versionCount: { __typename?: 'VersionCollection', totalCount: number }, commentThreadCount: { __typename?: 'CommentCollection', totalCount: number }, pendingImportedVersions: Array<{ __typename?: 'FileUpload', id: string, projectId: string, modelName: string, convertedStatus: number, convertedMessage?: string | null, uploadDate: string, convertedLastUpdate: string, fileType: string, fileName: string }>, automationStatus?: { __typename?: 'AutomationsStatus', id: string, status: AutomationRunStatus, statusMessage?: string | null, automationRuns: Array<{ __typename?: 'AutomationRun', id: string, automationId: string, automationName: string, createdAt: string, status: AutomationRunStatus, functionRuns: Array<{ __typename?: 'AutomationFunctionRun', id: string, functionId: string, functionName: string, functionLogo?: string | null, elapsed: number, status: AutomationRunStatus, statusMessage?: string | null, contextView?: string | null, results?: {} | null, resultVersions: Array<{ __typename?: 'Version', id: string, model: { __typename?: 'Model', id: string, name: string } }> }> }> } | null }> }, pendingImportedModels: Array<{ __typename?: 'FileUpload', id: string, projectId: string, modelName: string, convertedStatus: number, convertedMessage?: string | null, uploadDate: string, convertedLastUpdate: string, fileType: string, fileName: string }>, team: Array<{ __typename?: 'ProjectCollaborator', role: string, user: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } }>, invitedTeam?: Array<{ __typename?: 'PendingStreamCollaborator', id: string, title: string, inviteId: string, role: string, user?: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } | null }> | null } } };
export type FinishOnboardingMutationVariables = Exact<{ [key: string]: never; }>;
@@ -3227,6 +3239,8 @@ export type SearchProjectsQueryVariables = Exact<{
export type SearchProjectsQuery = { __typename?: 'Query', activeUser?: { __typename?: 'User', projects: { __typename?: 'ProjectCollection', totalCount: number, items: Array<{ __typename?: 'Project', id: string, name: string }> } } | null };
export type ProjectPageTeamInternals_ProjectFragment = { __typename?: 'Project', id: string, role?: string | null, invitedTeam?: Array<{ __typename?: 'PendingStreamCollaborator', id: string, title: string, role: string, inviteId: string, user?: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } | null }> | null, team: Array<{ __typename?: 'ProjectCollaborator', role: string, user: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } }> };
export type ProjectDashboardItemNoModelsFragment = { __typename?: 'Project', id: string, name: string, createdAt: string, updatedAt: string, role?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, team: Array<{ __typename?: 'ProjectCollaborator', user: { __typename?: 'LimitedUser', id: string, name: string, avatar?: string | null } }> };
export type ProjectDashboardItemFragment = { __typename?: 'Project', id: string, name: string, createdAt: string, updatedAt: string, role?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, models: { __typename?: 'ModelCollection', totalCount: number, items: Array<{ __typename?: 'Model', id: string, name: string, displayName: string, previewUrl?: string | null, createdAt: string, updatedAt: string, description?: string | null, versionCount: { __typename?: 'VersionCollection', totalCount: number }, commentThreadCount: { __typename?: 'CommentCollection', totalCount: number }, pendingImportedVersions: Array<{ __typename?: 'FileUpload', id: string, projectId: string, modelName: string, convertedStatus: number, convertedMessage?: string | null, uploadDate: string, convertedLastUpdate: string, fileType: string, fileName: string }>, automationStatus?: { __typename?: 'AutomationsStatus', id: string, status: AutomationRunStatus, statusMessage?: string | null, automationRuns: Array<{ __typename?: 'AutomationRun', id: string, automationId: string, automationName: string, createdAt: string, status: AutomationRunStatus, functionRuns: Array<{ __typename?: 'AutomationFunctionRun', id: string, functionId: string, functionName: string, functionLogo?: string | null, elapsed: number, status: AutomationRunStatus, statusMessage?: string | null, contextView?: string | null, results?: {} | null, resultVersions: Array<{ __typename?: 'Version', id: string, model: { __typename?: 'Model', id: string, name: string } }> }> }> } | null }> }, pendingImportedModels: Array<{ __typename?: 'FileUpload', id: string, projectId: string, modelName: string, convertedStatus: number, convertedMessage?: string | null, uploadDate: string, convertedLastUpdate: string, fileType: string, fileName: string }>, team: Array<{ __typename?: 'ProjectCollaborator', user: { __typename?: 'LimitedUser', id: string, name: string, avatar?: string | null } }> };
@@ -3237,6 +3251,12 @@ export type ProjectPageLatestItemsModelItemFragment = { __typename?: 'Model', id
export type ProjectUpdatableMetadataFragment = { __typename?: 'Project', id: string, name: string, description?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean };
export type ProjectPageLatestItemsModelsFragment = { __typename?: 'Project', id: string, role?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, modelCount: { __typename?: 'ModelCollection', totalCount: number } };
export type ProjectPageLatestItemsCommentsFragment = { __typename?: 'Project', id: string, commentThreadCount: { __typename?: 'ProjectCommentCollection', totalCount: number } };
export type ProjectPageLatestItemsCommentItemFragment = { __typename?: 'Comment', id: string, screenshot?: string | null, rawText: string, createdAt: string, updatedAt: string, archived: boolean, author: { __typename?: 'LimitedUser', id: string, name: string, avatar?: string | null }, repliesCount: { __typename?: 'CommentCollection', totalCount: number }, replyAuthors: { __typename?: 'CommentReplyAuthorCollection', totalCount: number, items: Array<{ __typename?: 'LimitedUser', id: string, name: string, avatar?: string | null }> } };
export type CreateModelMutationVariables = Exact<{
input: CreateModelInput;
}>;
@@ -3249,7 +3269,7 @@ export type CreateProjectMutationVariables = Exact<{
}>;
export type CreateProjectMutation = { __typename?: 'Mutation', projectMutations: { __typename?: 'ProjectMutations', create: { __typename?: 'Project', id: string, createdAt: string, role?: string | null, name: string, description?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, updatedAt: string, models: { __typename?: 'ModelCollection', totalCount: number, items: Array<{ __typename?: 'Model', id: string, name: string, displayName: string, previewUrl?: string | null, createdAt: string, updatedAt: string, description?: string | null, versionCount: { __typename?: 'VersionCollection', totalCount: number }, commentThreadCount: { __typename?: 'CommentCollection', totalCount: number }, pendingImportedVersions: Array<{ __typename?: 'FileUpload', id: string, projectId: string, modelName: string, convertedStatus: number, convertedMessage?: string | null, uploadDate: string, convertedLastUpdate: string, fileType: string, fileName: string }>, automationStatus?: { __typename?: 'AutomationsStatus', id: string, status: AutomationRunStatus, statusMessage?: string | null, automationRuns: Array<{ __typename?: 'AutomationRun', id: string, automationId: string, automationName: string, createdAt: string, status: AutomationRunStatus, functionRuns: Array<{ __typename?: 'AutomationFunctionRun', id: string, functionId: string, functionName: string, functionLogo?: string | null, elapsed: number, status: AutomationRunStatus, statusMessage?: string | null, contextView?: string | null, results?: {} | null, resultVersions: Array<{ __typename?: 'Version', id: string, model: { __typename?: 'Model', id: string, name: string } }> }> }> } | null }> }, pendingImportedModels: Array<{ __typename?: 'FileUpload', id: string, projectId: string, modelName: string, convertedStatus: number, convertedMessage?: string | null, uploadDate: string, convertedLastUpdate: string, fileType: string, fileName: string }>, team: Array<{ __typename?: 'ProjectCollaborator', role: string, user: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } }>, invitedTeam?: Array<{ __typename?: 'PendingStreamCollaborator', id: string, title: string, inviteId: string, role: string, user?: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } | null }> | null, versionCount: { __typename?: 'VersionCollection', totalCount: number }, modelCount: { __typename?: 'ModelCollection', totalCount: number }, commentThreadCount: { __typename?: 'ProjectCommentCollection', totalCount: number } } } };
export type CreateProjectMutation = { __typename?: 'Mutation', projectMutations: { __typename?: 'ProjectMutations', create: { __typename?: 'Project', id: string, createdAt: string, role?: string | null, name: string, description?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, updatedAt: string, modelCount: { __typename?: 'ModelCollection', totalCount: number }, commentThreadCount: { __typename?: 'ProjectCommentCollection', totalCount: number }, models: { __typename?: 'ModelCollection', totalCount: number, items: Array<{ __typename?: 'Model', id: string, name: string, displayName: string, previewUrl?: string | null, createdAt: string, updatedAt: string, description?: string | null, versionCount: { __typename?: 'VersionCollection', totalCount: number }, commentThreadCount: { __typename?: 'CommentCollection', totalCount: number }, pendingImportedVersions: Array<{ __typename?: 'FileUpload', id: string, projectId: string, modelName: string, convertedStatus: number, convertedMessage?: string | null, uploadDate: string, convertedLastUpdate: string, fileType: string, fileName: string }>, automationStatus?: { __typename?: 'AutomationsStatus', id: string, status: AutomationRunStatus, statusMessage?: string | null, automationRuns: Array<{ __typename?: 'AutomationRun', id: string, automationId: string, automationName: string, createdAt: string, status: AutomationRunStatus, functionRuns: Array<{ __typename?: 'AutomationFunctionRun', id: string, functionId: string, functionName: string, functionLogo?: string | null, elapsed: number, status: AutomationRunStatus, statusMessage?: string | null, contextView?: string | null, results?: {} | null, resultVersions: Array<{ __typename?: 'Version', id: string, model: { __typename?: 'Model', id: string, name: string } }> }> }> } | null }> }, pendingImportedModels: Array<{ __typename?: 'FileUpload', id: string, projectId: string, modelName: string, convertedStatus: number, convertedMessage?: string | null, uploadDate: string, convertedLastUpdate: string, fileType: string, fileName: string }>, team: Array<{ __typename?: 'ProjectCollaborator', role: string, user: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } }>, invitedTeam?: Array<{ __typename?: 'PendingStreamCollaborator', id: string, title: string, inviteId: string, role: string, user?: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } | null }> | null } } };
export type UpdateModelMutationVariables = Exact<{
input: UpdateModelInput;
@@ -3379,7 +3399,7 @@ export type ProjectPageQueryQueryVariables = Exact<{
}>;
export type ProjectPageQueryQuery = { __typename?: 'Query', project: { __typename?: 'Project', id: string, createdAt: string, role?: string | null, name: string, description?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, team: Array<{ __typename?: 'ProjectCollaborator', role: string, user: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } }>, invitedTeam?: Array<{ __typename?: 'PendingStreamCollaborator', id: string, title: string, inviteId: string, role: string, user?: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } | null }> | null, versionCount: { __typename?: 'VersionCollection', totalCount: number }, modelCount: { __typename?: 'ModelCollection', totalCount: number }, commentThreadCount: { __typename?: 'ProjectCommentCollection', totalCount: number } }, projectInvite?: { __typename?: 'PendingStreamCollaborator', id: string, projectId: string, projectName: string, token?: string | null, invitedBy: { __typename?: 'LimitedUser', id: string, name: string, avatar?: string | null } } | null };
export type ProjectPageQueryQuery = { __typename?: 'Query', project: { __typename?: 'Project', id: string, createdAt: string, role?: string | null, name: string, description?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, modelCount: { __typename?: 'ModelCollection', totalCount: number }, commentThreadCount: { __typename?: 'ProjectCommentCollection', totalCount: number }, team: Array<{ __typename?: 'ProjectCollaborator', role: string, user: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } }>, invitedTeam?: Array<{ __typename?: 'PendingStreamCollaborator', id: string, title: string, inviteId: string, role: string, user?: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } | null }> | null }, projectInvite?: { __typename?: 'PendingStreamCollaborator', id: string, projectId: string, projectName: string, token?: string | null, invitedBy: { __typename?: 'LimitedUser', id: string, name: string, avatar?: string | null } } | null };
export type ProjectLatestModelsQueryVariables = Exact<{
projectId: Scalars['String'];
@@ -3500,7 +3520,7 @@ export type OnProjectUpdatedSubscriptionVariables = Exact<{
}>;
export type OnProjectUpdatedSubscription = { __typename?: 'Subscription', projectUpdated: { __typename?: 'ProjectUpdatedMessage', id: string, type: ProjectUpdatedMessageType, project?: { __typename?: 'Project', id: string, createdAt: string, name: string, updatedAt: string, role?: string | null, description?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, team: Array<{ __typename?: 'ProjectCollaborator', role: string, user: { __typename?: 'LimitedUser', id: string, name: string, avatar?: string | null, role?: string | null } }>, invitedTeam?: Array<{ __typename?: 'PendingStreamCollaborator', id: string, title: string, inviteId: string, role: string, user?: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } | null }> | null, versionCount: { __typename?: 'VersionCollection', totalCount: number }, modelCount: { __typename?: 'ModelCollection', totalCount: number }, commentThreadCount: { __typename?: 'ProjectCommentCollection', totalCount: number } } | null } };
export type OnProjectUpdatedSubscription = { __typename?: 'Subscription', projectUpdated: { __typename?: 'ProjectUpdatedMessage', id: string, type: ProjectUpdatedMessageType, project?: { __typename?: 'Project', id: string, createdAt: string, name: string, updatedAt: string, role?: string | null, description?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, modelCount: { __typename?: 'ModelCollection', totalCount: number }, commentThreadCount: { __typename?: 'ProjectCommentCollection', totalCount: number }, team: Array<{ __typename?: 'ProjectCollaborator', role: string, user: { __typename?: 'LimitedUser', id: string, name: string, avatar?: string | null, role?: string | null } }>, invitedTeam?: Array<{ __typename?: 'PendingStreamCollaborator', id: string, title: string, inviteId: string, role: string, user?: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } | null }> | null } | null } };
export type OnProjectModelsUpdateSubscriptionVariables = Exact<{
id: Scalars['String'];
@@ -3788,7 +3808,9 @@ export type ResolveCommentLinkQueryVariables = Exact<{
export type ResolveCommentLinkQuery = { __typename?: 'Query', comment?: { __typename?: 'Comment', id: string, viewerResources: Array<{ __typename?: 'ViewerResourceItem', modelId?: string | null, versionId?: string | null, objectId: string }> } | null };
export type ProjectPageProjectFragment = { __typename?: 'Project', id: string, createdAt: string, role?: string | null, name: string, description?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, team: Array<{ __typename?: 'ProjectCollaborator', role: string, user: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } }>, invitedTeam?: Array<{ __typename?: 'PendingStreamCollaborator', id: string, title: string, inviteId: string, role: string, user?: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } | null }> | null, versionCount: { __typename?: 'VersionCollection', totalCount: number }, modelCount: { __typename?: 'ModelCollection', totalCount: number }, commentThreadCount: { __typename?: 'ProjectCommentCollection', totalCount: number } };
export type ProjectPageProjectFragment = { __typename?: 'Project', id: string, createdAt: string, role?: string | null, name: string, description?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, modelCount: { __typename?: 'ModelCollection', totalCount: number }, commentThreadCount: { __typename?: 'ProjectCommentCollection', totalCount: number }, team: Array<{ __typename?: 'ProjectCollaborator', role: string, user: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } }>, invitedTeam?: Array<{ __typename?: 'PendingStreamCollaborator', id: string, title: string, inviteId: string, role: string, user?: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } | null }> | null };
export type ProjectPageSettingsTab_ProjectFragment = { __typename?: 'Project', id: string, role?: string | null };
export const AuthRegisterPanelServerInfoFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AuthRegisterPanelServerInfo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ServerInfo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"inviteOnly"}}]}}]} as unknown as DocumentNode<AuthRegisterPanelServerInfoFragment, unknown>;
export const ServerTermsOfServicePrivacyPolicyFragmentFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServerTermsOfServicePrivacyPolicyFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ServerInfo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"termsOfService"}}]}}]} as unknown as DocumentNode<ServerTermsOfServicePrivacyPolicyFragmentFragment, unknown>;
@@ -3810,10 +3832,11 @@ export const ProjectModelPageVersionsCardVersionFragmentDoc = {"kind":"Document"
export const ProjectModelPageVersionsPaginationFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectModelPageVersionsPagination"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"Field","name":{"kind":"Name","value":"model"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"modelId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"versions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"16"}},{"kind":"Argument","name":{"kind":"Name","value":"cursor"},"value":{"kind":"Variable","name":{"kind":"Name","value":"versionsCursor"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"cursor"}},{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectModelPageVersionsCardVersion"}}]}}]}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectsModelPageEmbed_Project"}}]}}]} as unknown as DocumentNode<ProjectModelPageVersionsPaginationFragment, unknown>;
export const ProjectModelPageVersionsProjectFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectModelPageVersionsProject"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageProjectHeader"}},{"kind":"Field","name":{"kind":"Name","value":"model"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"modelId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"pendingImportedVersions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"PendingFileUpload"}}]}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectModelPageVersionsPagination"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectsModelPageEmbed_Project"}}]}}]} as unknown as DocumentNode<ProjectModelPageVersionsProjectFragment, unknown>;
export const ProjectModelPageDialogEditMessageVersionFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectModelPageDialogEditMessageVersion"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Version"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]} as unknown as DocumentNode<ProjectModelPageDialogEditMessageVersionFragment, unknown>;
export const ProjectPageTeamInternals_ProjectFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageTeamInternals_Project"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"invitedTeam"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"inviteId"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"LimitedUserAvatar"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"team"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"LimitedUserAvatar"}}]}}]}}]}}]} as unknown as DocumentNode<ProjectPageTeamInternals_ProjectFragment, unknown>;
export const ProjectPageInviteDialog_ProjectFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageInviteDialog_Project"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageTeamInternals_Project"}}]}}]} as unknown as DocumentNode<ProjectPageInviteDialog_ProjectFragment, unknown>;
export const ProjectDiscussionsPageHeader_ProjectFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectDiscussionsPageHeader_Project"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]} as unknown as DocumentNode<ProjectDiscussionsPageHeader_ProjectFragment, unknown>;
export const ProjectDiscussionsPageResults_ProjectFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectDiscussionsPageResults_Project"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]} as unknown as DocumentNode<ProjectDiscussionsPageResults_ProjectFragment, unknown>;
export const FormUsersSelectItemFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"FormUsersSelectItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"LimitedUser"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"}}]}}]} as unknown as DocumentNode<FormUsersSelectItemFragment, unknown>;
export const ProjectPageLatestItemsCommentItemFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageLatestItemsCommentItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Comment"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FormUsersSelectItem"}}]}},{"kind":"Field","name":{"kind":"Name","value":"screenshot"}},{"kind":"Field","name":{"kind":"Name","value":"rawText"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"archived"}},{"kind":"Field","alias":{"kind":"Name","value":"repliesCount"},"name":{"kind":"Name","value":"replies"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"0"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}},{"kind":"Field","name":{"kind":"Name","value":"replyAuthors"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"4"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FormUsersSelectItem"}}]}}]}}]}}]} as unknown as DocumentNode<ProjectPageLatestItemsCommentItemFragment, unknown>;
export const ProjectModelsPageHeader_ProjectFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectModelsPageHeader_Project"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"sourceApps"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"team"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FormUsersSelectItem"}}]}}]}}]}}]} as unknown as DocumentNode<ProjectModelsPageHeader_ProjectFragment, unknown>;
export const ProjectPageModelsActions_ProjectFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageModelsActions_Project"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectsModelPageEmbed_Project"}}]}}]} as unknown as DocumentNode<ProjectPageModelsActions_ProjectFragment, unknown>;
export const ProjectPageModelsStructureItem_ProjectFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageModelsStructureItem_Project"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageModelsActions_Project"}}]}}]} as unknown as DocumentNode<ProjectPageModelsStructureItem_ProjectFragment, unknown>;
@@ -3825,6 +3848,11 @@ export const ProjectPageModelsActionsFragmentDoc = {"kind":"Document","definitio
export const ModelCardAutomationStatus_ModelFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ModelCardAutomationStatus_Model"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Model"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"automationStatus"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ModelCardAutomationStatus_AutomationsStatus"}}]}}]}}]} as unknown as DocumentNode<ModelCardAutomationStatus_ModelFragment, unknown>;
export const ProjectPageLatestItemsModelItemFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageLatestItemsModelItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Model"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","alias":{"kind":"Name","value":"versionCount"},"name":{"kind":"Name","value":"versions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"0"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}},{"kind":"Field","alias":{"kind":"Name","value":"commentThreadCount"},"name":{"kind":"Name","value":"commentThreads"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"0"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}},{"kind":"Field","name":{"kind":"Name","value":"pendingImportedVersions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"1"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"PendingFileUpload"}}]}},{"kind":"Field","name":{"kind":"Name","value":"previewUrl"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageModelsCardRenameDialog"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageModelsCardDeleteDialog"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageModelsActions"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ModelCardAutomationStatus_Model"}}]}}]} as unknown as DocumentNode<ProjectPageLatestItemsModelItemFragment, unknown>;
export const SingleLevelModelTreeItemFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SingleLevelModelTreeItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ModelsTreeItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"fullName"}},{"kind":"Field","name":{"kind":"Name","value":"model"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageLatestItemsModelItem"}}]}},{"kind":"Field","name":{"kind":"Name","value":"hasChildren"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode<SingleLevelModelTreeItemFragment, unknown>;
export const ProjectPageSettingsGeneralBlockAccess_ProjectFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageSettingsGeneralBlockAccess_Project"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}}]}}]} as unknown as DocumentNode<ProjectPageSettingsGeneralBlockAccess_ProjectFragment, unknown>;
export const ProjectPageSettingsGeneralBlockDelete_ProjectFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageSettingsGeneralBlockDelete_Project"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"models"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"0"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}},{"kind":"Field","name":{"kind":"Name","value":"commentThreads"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"0"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}}]}}]} as unknown as DocumentNode<ProjectPageSettingsGeneralBlockDelete_ProjectFragment, unknown>;
export const ProjectPageSettingsGeneralBlockDiscussions_ProjectFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageSettingsGeneralBlockDiscussions_Project"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"Field","name":{"kind":"Name","value":"allowPublicComments"}}]}}]} as unknown as DocumentNode<ProjectPageSettingsGeneralBlockDiscussions_ProjectFragment, unknown>;
export const ProjectPageSettingsGeneralBlockLeave_ProjectFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageSettingsGeneralBlockLeave_Project"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"team"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"LimitedUserAvatar"}},{"kind":"Field","name":{"kind":"Name","value":"role"}}]}}]}}]}}]} as unknown as DocumentNode<ProjectPageSettingsGeneralBlockLeave_ProjectFragment, unknown>;
export const ProjectPageSettingsGeneralBlockProjectInfo_ProjectFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageSettingsGeneralBlockProjectInfo_Project"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}}]}}]} as unknown as DocumentNode<ProjectPageSettingsGeneralBlockProjectInfo_ProjectFragment, unknown>;
export const ProjectPageModelsCardProjectFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageModelsCardProject"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageModelsActions_Project"}}]}}]} as unknown as DocumentNode<ProjectPageModelsCardProjectFragment, unknown>;
export const ProjectDashboardItemNoModelsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectDashboardItemNoModels"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"team"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"}}]}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageModelsCardProject"}}]}}]} as unknown as DocumentNode<ProjectDashboardItemNoModelsFragment, unknown>;
export const ProjectDashboardItemFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectDashboardItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectDashboardItemNoModels"}},{"kind":"Field","name":{"kind":"Name","value":"models"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"4"}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"onlyWithVersions"},"value":{"kind":"BooleanValue","value":true}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageLatestItemsModelItem"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"pendingImportedModels"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"4"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"PendingFileUpload"}}]}}]}}]} as unknown as DocumentNode<ProjectDashboardItemFragment, unknown>;
@@ -3839,6 +3867,8 @@ export const UserProfileEditDialogNotificationPreferences_UserFragmentDoc = {"ki
export const ModelPageProjectFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ModelPageProject"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}}]}}]} as unknown as DocumentNode<ModelPageProjectFragment, unknown>;
export const ViewerModelVersionCardItemFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewerModelVersionCardItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Version"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"referencedObject"}},{"kind":"Field","name":{"kind":"Name","value":"sourceApplication"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"previewUrl"}},{"kind":"Field","name":{"kind":"Name","value":"authorUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"LimitedUserAvatar"}}]}}]}}]} as unknown as DocumentNode<ViewerModelVersionCardItemFragment, unknown>;
export const ProjectUpdatableMetadataFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectUpdatableMetadata"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"Field","name":{"kind":"Name","value":"allowPublicComments"}}]}}]} as unknown as DocumentNode<ProjectUpdatableMetadataFragment, unknown>;
export const ProjectPageLatestItemsCommentsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageLatestItemsComments"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","alias":{"kind":"Name","value":"commentThreadCount"},"name":{"kind":"Name","value":"commentThreads"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"0"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}}]}}]} as unknown as DocumentNode<ProjectPageLatestItemsCommentsFragment, unknown>;
export const ProjectPageLatestItemsCommentItemFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageLatestItemsCommentItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Comment"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FormUsersSelectItem"}}]}},{"kind":"Field","name":{"kind":"Name","value":"screenshot"}},{"kind":"Field","name":{"kind":"Name","value":"rawText"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"archived"}},{"kind":"Field","alias":{"kind":"Name","value":"repliesCount"},"name":{"kind":"Name","value":"replies"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"0"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}},{"kind":"Field","name":{"kind":"Name","value":"replyAuthors"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"4"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FormUsersSelectItem"}}]}}]}}]}}]} as unknown as DocumentNode<ProjectPageLatestItemsCommentItemFragment, unknown>;
export const AppAuthorAvatarFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AppAuthorAvatar"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AppAuthor"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"}}]}}]} as unknown as DocumentNode<AppAuthorAvatarFragment, unknown>;
export const ThreadCommentAttachmentFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ThreadCommentAttachment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Comment"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"text"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"attachments"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"fileName"}},{"kind":"Field","name":{"kind":"Name","value":"fileType"}},{"kind":"Field","name":{"kind":"Name","value":"fileSize"}}]}}]}}]}}]} as unknown as DocumentNode<ThreadCommentAttachmentFragment, unknown>;
export const ViewerCommentsReplyItemFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewerCommentsReplyItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Comment"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"archived"}},{"kind":"Field","name":{"kind":"Name","value":"rawText"}},{"kind":"Field","name":{"kind":"Name","value":"text"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"doc"}}]}},{"kind":"Field","name":{"kind":"Name","value":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"LimitedUserAvatar"}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ThreadCommentAttachment"}}]}}]} as unknown as DocumentNode<ViewerCommentsReplyItemFragment, unknown>;
@@ -3847,18 +3877,16 @@ export const ViewerCommentBubblesDataFragmentDoc = {"kind":"Document","definitio
export const ViewerCommentThreadFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewerCommentThread"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Comment"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewerCommentsListItem"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewerCommentBubblesData"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewerCommentsReplyItem"}}]}}]} as unknown as DocumentNode<ViewerCommentThreadFragment, unknown>;
export const LinkableCommentFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"LinkableComment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Comment"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"viewerResources"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"modelId"}},{"kind":"Field","name":{"kind":"Name","value":"versionId"}},{"kind":"Field","name":{"kind":"Name","value":"objectId"}}]}}]}}]} as unknown as DocumentNode<LinkableCommentFragment, unknown>;
export const ProjectPageTeamDialogFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageTeamDialog"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"allowPublicComments"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"Field","name":{"kind":"Name","value":"team"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"LimitedUserAvatar"}},{"kind":"Field","name":{"kind":"Name","value":"role"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"invitedTeam"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"inviteId"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"LimitedUserAvatar"}},{"kind":"Field","name":{"kind":"Name","value":"role"}}]}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectsPageTeamDialogManagePermissions_Project"}}]}}]} as unknown as DocumentNode<ProjectPageTeamDialogFragment, unknown>;
export const ProjectPageStatsBlockTeamFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageStatsBlockTeam"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"team"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"LimitedUserAvatar"}}]}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageTeamDialog"}}]}}]} as unknown as DocumentNode<ProjectPageStatsBlockTeamFragment, unknown>;
export const ProjectPageStatsBlockVersionsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageStatsBlockVersions"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"versionCount"},"name":{"kind":"Name","value":"versions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"0"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}}]}}]} as unknown as DocumentNode<ProjectPageStatsBlockVersionsFragment, unknown>;
export const ProjectPageStatsBlockModelsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageStatsBlockModels"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"modelCount"},"name":{"kind":"Name","value":"models"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"0"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}}]}}]} as unknown as DocumentNode<ProjectPageStatsBlockModelsFragment, unknown>;
export const ProjectPageStatsBlockCommentsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageStatsBlockComments"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"commentThreadCount"},"name":{"kind":"Name","value":"commentThreads"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"0"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}}]}}]} as unknown as DocumentNode<ProjectPageStatsBlockCommentsFragment, unknown>;
export const ProjectPageLatestItemsCommentsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageLatestItemsComments"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","alias":{"kind":"Name","value":"commentThreadCount"},"name":{"kind":"Name","value":"commentThreads"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"0"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}}]}}]} as unknown as DocumentNode<ProjectPageLatestItemsCommentsFragment, unknown>;
export const ProjectPageProjectFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageProject"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageProjectHeader"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageStatsBlockTeam"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageTeamDialog"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageStatsBlockVersions"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageStatsBlockModels"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageStatsBlockComments"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageLatestItemsModels"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageLatestItemsComments"}}]}}]} as unknown as DocumentNode<ProjectPageProjectFragment, unknown>;
export const ProjectPageProjectFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageProject"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","alias":{"kind":"Name","value":"modelCount"},"name":{"kind":"Name","value":"models"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"0"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}},{"kind":"Field","alias":{"kind":"Name","value":"commentThreadCount"},"name":{"kind":"Name","value":"commentThreads"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"0"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageProjectHeader"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageTeamDialog"}}]}}]} as unknown as DocumentNode<ProjectPageProjectFragment, unknown>;
export const ProjectPageSettingsTab_ProjectFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageSettingsTab_Project"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"role"}}]}}]} as unknown as DocumentNode<ProjectPageSettingsTab_ProjectFragment, unknown>;
export const RegisterPanelServerInviteDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"RegisterPanelServerInvite"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"token"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"serverInviteByToken"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"token"},"value":{"kind":"Variable","name":{"kind":"Name","value":"token"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}}]}}]}}]} as unknown as DocumentNode<RegisterPanelServerInviteQuery, RegisterPanelServerInviteQueryVariables>;
export const EmailVerificationBannerStateDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"EmailVerificationBannerState"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"verified"}},{"kind":"Field","name":{"kind":"Name","value":"hasPendingVerification"}}]}}]}}]} as unknown as DocumentNode<EmailVerificationBannerStateQuery, EmailVerificationBannerStateQueryVariables>;
export const RequestVerificationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"RequestVerification"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"requestVerification"}}]}}]} as unknown as DocumentNode<RequestVerificationMutation, RequestVerificationMutationVariables>;
export const ProjectPageSettingsCollaboratorsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ProjectPageSettingsCollaborators"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageTeamInternals_Project"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageInviteDialog_Project"}}]}}]}},...ProjectPageTeamInternals_ProjectFragmentDoc.definitions,...LimitedUserAvatarFragmentDoc.definitions,...ProjectPageInviteDialog_ProjectFragmentDoc.definitions]} as unknown as DocumentNode<ProjectPageSettingsCollaboratorsQuery, ProjectPageSettingsCollaboratorsQueryVariables>;
export const ProjectPageSettingsGeneralDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ProjectPageSettingsGeneral"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageSettingsGeneralBlockProjectInfo_Project"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageSettingsGeneralBlockAccess_Project"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageSettingsGeneralBlockDiscussions_Project"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageSettingsGeneralBlockLeave_Project"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageSettingsGeneralBlockDelete_Project"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageTeamInternals_Project"}}]}}]}},...ProjectPageSettingsGeneralBlockProjectInfo_ProjectFragmentDoc.definitions,...ProjectPageSettingsGeneralBlockAccess_ProjectFragmentDoc.definitions,...ProjectPageSettingsGeneralBlockDiscussions_ProjectFragmentDoc.definitions,...ProjectPageSettingsGeneralBlockLeave_ProjectFragmentDoc.definitions,...LimitedUserAvatarFragmentDoc.definitions,...ProjectPageSettingsGeneralBlockDelete_ProjectFragmentDoc.definitions,...ProjectPageTeamInternals_ProjectFragmentDoc.definitions]} as unknown as DocumentNode<ProjectPageSettingsGeneralQuery, ProjectPageSettingsGeneralQueryVariables>;
export const OnUserProjectsUpdateDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"subscription","name":{"kind":"Name","value":"OnUserProjectsUpdate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userProjectsUpdated"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"project"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectDashboardItem"}}]}}]}}]}},...ProjectDashboardItemFragmentDoc.definitions,...ProjectDashboardItemNoModelsFragmentDoc.definitions,...ProjectPageModelsCardProjectFragmentDoc.definitions,...ProjectPageModelsActions_ProjectFragmentDoc.definitions,...ProjectsModelPageEmbed_ProjectFragmentDoc.definitions,...ProjectsPageTeamDialogManagePermissions_ProjectFragmentDoc.definitions,...ProjectPageLatestItemsModelItemFragmentDoc.definitions,...PendingFileUploadFragmentDoc.definitions,...ProjectPageModelsCardRenameDialogFragmentDoc.definitions,...ProjectPageModelsCardDeleteDialogFragmentDoc.definitions,...ProjectPageModelsActionsFragmentDoc.definitions,...ModelCardAutomationStatus_ModelFragmentDoc.definitions,...ModelCardAutomationStatus_AutomationsStatusFragmentDoc.definitions]} as unknown as DocumentNode<OnUserProjectsUpdateSubscription, OnUserProjectsUpdateSubscriptionVariables>;
export const ActiveUserMainMetadataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ActiveUserMainMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"company"}},{"kind":"Field","name":{"kind":"Name","value":"bio"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"}},{"kind":"Field","name":{"kind":"Name","value":"isOnboardingFinished"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"verified"}},{"kind":"Field","name":{"kind":"Name","value":"notificationPreferences"}},{"kind":"Field","name":{"kind":"Name","value":"versions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"0"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}}]}}]}}]} as unknown as DocumentNode<ActiveUserMainMetadataQuery, ActiveUserMainMetadataQueryVariables>;
export const CreateOnboardingProjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOnboardingProject"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createForOnboarding"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageProject"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectDashboardItem"}}]}}]}}]}},...ProjectPageProjectFragmentDoc.definitions,...ProjectPageProjectHeaderFragmentDoc.definitions,...ProjectPageStatsBlockTeamFragmentDoc.definitions,...LimitedUserAvatarFragmentDoc.definitions,...ProjectPageTeamDialogFragmentDoc.definitions,...ProjectsPageTeamDialogManagePermissions_ProjectFragmentDoc.definitions,...ProjectPageStatsBlockVersionsFragmentDoc.definitions,...ProjectPageStatsBlockModelsFragmentDoc.definitions,...ProjectPageStatsBlockCommentsFragmentDoc.definitions,...ProjectPageLatestItemsModelsFragmentDoc.definitions,...ProjectPageModelsStructureItem_ProjectFragmentDoc.definitions,...ProjectPageModelsActions_ProjectFragmentDoc.definitions,...ProjectsModelPageEmbed_ProjectFragmentDoc.definitions,...ProjectPageLatestItemsCommentsFragmentDoc.definitions,...ProjectDashboardItemFragmentDoc.definitions,...ProjectDashboardItemNoModelsFragmentDoc.definitions,...ProjectPageModelsCardProjectFragmentDoc.definitions,...ProjectPageLatestItemsModelItemFragmentDoc.definitions,...PendingFileUploadFragmentDoc.definitions,...ProjectPageModelsCardRenameDialogFragmentDoc.definitions,...ProjectPageModelsCardDeleteDialogFragmentDoc.definitions,...ProjectPageModelsActionsFragmentDoc.definitions,...ModelCardAutomationStatus_ModelFragmentDoc.definitions,...ModelCardAutomationStatus_AutomationsStatusFragmentDoc.definitions]} as unknown as DocumentNode<CreateOnboardingProjectMutation, CreateOnboardingProjectMutationVariables>;
export const CreateOnboardingProjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOnboardingProject"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createForOnboarding"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageProject"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectDashboardItem"}}]}}]}}]}},...ProjectPageProjectFragmentDoc.definitions,...ProjectPageProjectHeaderFragmentDoc.definitions,...ProjectPageTeamDialogFragmentDoc.definitions,...LimitedUserAvatarFragmentDoc.definitions,...ProjectsPageTeamDialogManagePermissions_ProjectFragmentDoc.definitions,...ProjectDashboardItemFragmentDoc.definitions,...ProjectDashboardItemNoModelsFragmentDoc.definitions,...ProjectPageModelsCardProjectFragmentDoc.definitions,...ProjectPageModelsActions_ProjectFragmentDoc.definitions,...ProjectsModelPageEmbed_ProjectFragmentDoc.definitions,...ProjectPageLatestItemsModelItemFragmentDoc.definitions,...PendingFileUploadFragmentDoc.definitions,...ProjectPageModelsCardRenameDialogFragmentDoc.definitions,...ProjectPageModelsCardDeleteDialogFragmentDoc.definitions,...ProjectPageModelsActionsFragmentDoc.definitions,...ModelCardAutomationStatus_ModelFragmentDoc.definitions,...ModelCardAutomationStatus_AutomationsStatusFragmentDoc.definitions]} as unknown as DocumentNode<CreateOnboardingProjectMutation, CreateOnboardingProjectMutationVariables>;
export const FinishOnboardingDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"FinishOnboarding"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUserMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"finishOnboarding"}}]}}]}}]} as unknown as DocumentNode<FinishOnboardingMutation, FinishOnboardingMutationVariables>;
export const RequestVerificationByEmailDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"RequestVerificationByEmail"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"email"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"requestVerificationByEmail"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"email"},"value":{"kind":"Variable","name":{"kind":"Name","value":"email"}}}]}]}}]} as unknown as DocumentNode<RequestVerificationByEmailMutation, RequestVerificationByEmailMutationVariables>;
export const AuthServerInfoDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"AuthServerInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"serverInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"AuthStategiesServerInfoFragment"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServerTermsOfServicePrivacyPolicyFragment"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AuthRegisterPanelServerInfo"}}]}}]}},...AuthStategiesServerInfoFragmentFragmentDoc.definitions,...ServerTermsOfServicePrivacyPolicyFragmentFragmentDoc.definitions,...AuthRegisterPanelServerInfoFragmentDoc.definitions]} as unknown as DocumentNode<AuthServerInfoQuery, AuthServerInfoQueryVariables>;
@@ -3881,7 +3909,7 @@ export const DeveloperSettingsApplicationsDocument = {"kind":"Document","definit
export const DeveloperSettingsAuthorizedAppsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"DeveloperSettingsAuthorizedApps"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"authorizedApps"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"}}]}}]}}]}}]}}]} as unknown as DocumentNode<DeveloperSettingsAuthorizedAppsQuery, DeveloperSettingsAuthorizedAppsQueryVariables>;
export const SearchProjectsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"SearchProjects"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"search"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"onlyWithRoles"}},"type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},"defaultValue":{"kind":"NullValue"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projects"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"10"}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"search"},"value":{"kind":"Variable","name":{"kind":"Name","value":"search"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"onlyWithRoles"},"value":{"kind":"Variable","name":{"kind":"Name","value":"onlyWithRoles"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FormSelectProjects_Project"}}]}}]}}]}}]}},...FormSelectProjects_ProjectFragmentDoc.definitions]} as unknown as DocumentNode<SearchProjectsQuery, SearchProjectsQueryVariables>;
export const CreateModelDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateModel"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateModelInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"modelMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"create"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageLatestItemsModelItem"}}]}}]}}]}},...ProjectPageLatestItemsModelItemFragmentDoc.definitions,...PendingFileUploadFragmentDoc.definitions,...ProjectPageModelsCardRenameDialogFragmentDoc.definitions,...ProjectPageModelsCardDeleteDialogFragmentDoc.definitions,...ProjectPageModelsActionsFragmentDoc.definitions,...ModelCardAutomationStatus_ModelFragmentDoc.definitions,...ModelCardAutomationStatus_AutomationsStatusFragmentDoc.definitions]} as unknown as DocumentNode<CreateModelMutation, CreateModelMutationVariables>;
export const CreateProjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateProject"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ProjectCreateInput"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"create"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageProject"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectDashboardItem"}}]}}]}}]}},...ProjectPageProjectFragmentDoc.definitions,...ProjectPageProjectHeaderFragmentDoc.definitions,...ProjectPageStatsBlockTeamFragmentDoc.definitions,...LimitedUserAvatarFragmentDoc.definitions,...ProjectPageTeamDialogFragmentDoc.definitions,...ProjectsPageTeamDialogManagePermissions_ProjectFragmentDoc.definitions,...ProjectPageStatsBlockVersionsFragmentDoc.definitions,...ProjectPageStatsBlockModelsFragmentDoc.definitions,...ProjectPageStatsBlockCommentsFragmentDoc.definitions,...ProjectPageLatestItemsModelsFragmentDoc.definitions,...ProjectPageModelsStructureItem_ProjectFragmentDoc.definitions,...ProjectPageModelsActions_ProjectFragmentDoc.definitions,...ProjectsModelPageEmbed_ProjectFragmentDoc.definitions,...ProjectPageLatestItemsCommentsFragmentDoc.definitions,...ProjectDashboardItemFragmentDoc.definitions,...ProjectDashboardItemNoModelsFragmentDoc.definitions,...ProjectPageModelsCardProjectFragmentDoc.definitions,...ProjectPageLatestItemsModelItemFragmentDoc.definitions,...PendingFileUploadFragmentDoc.definitions,...ProjectPageModelsCardRenameDialogFragmentDoc.definitions,...ProjectPageModelsCardDeleteDialogFragmentDoc.definitions,...ProjectPageModelsActionsFragmentDoc.definitions,...ModelCardAutomationStatus_ModelFragmentDoc.definitions,...ModelCardAutomationStatus_AutomationsStatusFragmentDoc.definitions]} as unknown as DocumentNode<CreateProjectMutation, CreateProjectMutationVariables>;
export const CreateProjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateProject"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ProjectCreateInput"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"create"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageProject"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectDashboardItem"}}]}}]}}]}},...ProjectPageProjectFragmentDoc.definitions,...ProjectPageProjectHeaderFragmentDoc.definitions,...ProjectPageTeamDialogFragmentDoc.definitions,...LimitedUserAvatarFragmentDoc.definitions,...ProjectsPageTeamDialogManagePermissions_ProjectFragmentDoc.definitions,...ProjectDashboardItemFragmentDoc.definitions,...ProjectDashboardItemNoModelsFragmentDoc.definitions,...ProjectPageModelsCardProjectFragmentDoc.definitions,...ProjectPageModelsActions_ProjectFragmentDoc.definitions,...ProjectsModelPageEmbed_ProjectFragmentDoc.definitions,...ProjectPageLatestItemsModelItemFragmentDoc.definitions,...PendingFileUploadFragmentDoc.definitions,...ProjectPageModelsCardRenameDialogFragmentDoc.definitions,...ProjectPageModelsCardDeleteDialogFragmentDoc.definitions,...ProjectPageModelsActionsFragmentDoc.definitions,...ModelCardAutomationStatus_ModelFragmentDoc.definitions,...ModelCardAutomationStatus_AutomationsStatusFragmentDoc.definitions]} as unknown as DocumentNode<CreateProjectMutation, CreateProjectMutationVariables>;
export const UpdateModelDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateModel"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateModelInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"modelMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"update"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageLatestItemsModelItem"}}]}}]}}]}},...ProjectPageLatestItemsModelItemFragmentDoc.definitions,...PendingFileUploadFragmentDoc.definitions,...ProjectPageModelsCardRenameDialogFragmentDoc.definitions,...ProjectPageModelsCardDeleteDialogFragmentDoc.definitions,...ProjectPageModelsActionsFragmentDoc.definitions,...ModelCardAutomationStatus_ModelFragmentDoc.definitions,...ModelCardAutomationStatus_AutomationsStatusFragmentDoc.definitions]} as unknown as DocumentNode<UpdateModelMutation, UpdateModelMutationVariables>;
export const DeleteModelDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteModel"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"DeleteModelInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"modelMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"delete"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]}}]} as unknown as DocumentNode<DeleteModelMutation, DeleteModelMutationVariables>;
export const UpdateProjectRoleDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateProjectRole"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ProjectUpdateRoleInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateRole"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"team"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"LimitedUserAvatar"}}]}}]}}]}}]}}]}},...LimitedUserAvatarFragmentDoc.definitions]} as unknown as DocumentNode<UpdateProjectRoleMutation, UpdateProjectRoleMutationVariables>;
@@ -3899,7 +3927,7 @@ export const CreateWebhookDocument = {"kind":"Document","definitions":[{"kind":"
export const UpdateWebhookDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"updateWebhook"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"webhook"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"WebhookUpdateInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"webhookUpdate"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"webhook"},"value":{"kind":"Variable","name":{"kind":"Name","value":"webhook"}}}]}]}}]} as unknown as DocumentNode<UpdateWebhookMutation, UpdateWebhookMutationVariables>;
export const ProjectAccessCheckDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ProjectAccessCheck"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} as unknown as DocumentNode<ProjectAccessCheckQuery, ProjectAccessCheckQueryVariables>;
export const ProjectsDashboardQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ProjectsDashboardQuery"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"UserProjectsFilter"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"projects"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}},{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"6"}},{"kind":"Argument","name":{"kind":"Name","value":"cursor"},"value":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"cursor"}},{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectDashboardItem"}}]}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectsInviteBanners"}}]}}]}},...ProjectDashboardItemFragmentDoc.definitions,...ProjectDashboardItemNoModelsFragmentDoc.definitions,...ProjectPageModelsCardProjectFragmentDoc.definitions,...ProjectPageModelsActions_ProjectFragmentDoc.definitions,...ProjectsModelPageEmbed_ProjectFragmentDoc.definitions,...ProjectsPageTeamDialogManagePermissions_ProjectFragmentDoc.definitions,...ProjectPageLatestItemsModelItemFragmentDoc.definitions,...PendingFileUploadFragmentDoc.definitions,...ProjectPageModelsCardRenameDialogFragmentDoc.definitions,...ProjectPageModelsCardDeleteDialogFragmentDoc.definitions,...ProjectPageModelsActionsFragmentDoc.definitions,...ModelCardAutomationStatus_ModelFragmentDoc.definitions,...ModelCardAutomationStatus_AutomationsStatusFragmentDoc.definitions,...ProjectsInviteBannersFragmentDoc.definitions,...ProjectsInviteBannerFragmentDoc.definitions,...LimitedUserAvatarFragmentDoc.definitions]} as unknown as DocumentNode<ProjectsDashboardQueryQuery, ProjectsDashboardQueryQueryVariables>;
export const ProjectPageQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ProjectPageQuery"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"token"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageProject"}}]}},{"kind":"Field","name":{"kind":"Name","value":"projectInvite"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"projectId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}},{"kind":"Argument","name":{"kind":"Name","value":"token"},"value":{"kind":"Variable","name":{"kind":"Name","value":"token"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectsInviteBanner"}}]}}]}},...ProjectPageProjectFragmentDoc.definitions,...ProjectPageProjectHeaderFragmentDoc.definitions,...ProjectPageStatsBlockTeamFragmentDoc.definitions,...LimitedUserAvatarFragmentDoc.definitions,...ProjectPageTeamDialogFragmentDoc.definitions,...ProjectsPageTeamDialogManagePermissions_ProjectFragmentDoc.definitions,...ProjectPageStatsBlockVersionsFragmentDoc.definitions,...ProjectPageStatsBlockModelsFragmentDoc.definitions,...ProjectPageStatsBlockCommentsFragmentDoc.definitions,...ProjectPageLatestItemsModelsFragmentDoc.definitions,...ProjectPageModelsStructureItem_ProjectFragmentDoc.definitions,...ProjectPageModelsActions_ProjectFragmentDoc.definitions,...ProjectsModelPageEmbed_ProjectFragmentDoc.definitions,...ProjectPageLatestItemsCommentsFragmentDoc.definitions,...ProjectsInviteBannerFragmentDoc.definitions]} as unknown as DocumentNode<ProjectPageQueryQuery, ProjectPageQueryQueryVariables>;
export const ProjectPageQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ProjectPageQuery"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"token"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageProject"}}]}},{"kind":"Field","name":{"kind":"Name","value":"projectInvite"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"projectId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}},{"kind":"Argument","name":{"kind":"Name","value":"token"},"value":{"kind":"Variable","name":{"kind":"Name","value":"token"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectsInviteBanner"}}]}}]}},...ProjectPageProjectFragmentDoc.definitions,...ProjectPageProjectHeaderFragmentDoc.definitions,...ProjectPageTeamDialogFragmentDoc.definitions,...LimitedUserAvatarFragmentDoc.definitions,...ProjectsPageTeamDialogManagePermissions_ProjectFragmentDoc.definitions,...ProjectsInviteBannerFragmentDoc.definitions]} as unknown as DocumentNode<ProjectPageQueryQuery, ProjectPageQueryQueryVariables>;
export const ProjectLatestModelsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ProjectLatestModels"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ProjectModelsFilter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"models"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"cursor"},"value":{"kind":"NullValue"}},{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"16"}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageLatestItemsModelItem"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"pendingImportedModels"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"PendingFileUpload"}}]}}]}}]}},...ProjectPageLatestItemsModelItemFragmentDoc.definitions,...PendingFileUploadFragmentDoc.definitions,...ProjectPageModelsCardRenameDialogFragmentDoc.definitions,...ProjectPageModelsCardDeleteDialogFragmentDoc.definitions,...ProjectPageModelsActionsFragmentDoc.definitions,...ModelCardAutomationStatus_ModelFragmentDoc.definitions,...ModelCardAutomationStatus_AutomationsStatusFragmentDoc.definitions]} as unknown as DocumentNode<ProjectLatestModelsQuery, ProjectLatestModelsQueryVariables>;
export const ProjectLatestModelsPaginationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ProjectLatestModelsPagination"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ProjectModelsFilter"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}},"defaultValue":{"kind":"NullValue"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"models"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"cursor"},"value":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}}},{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"16"}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageLatestItemsModelItem"}}]}}]}}]}}]}},...ProjectPageLatestItemsModelItemFragmentDoc.definitions,...PendingFileUploadFragmentDoc.definitions,...ProjectPageModelsCardRenameDialogFragmentDoc.definitions,...ProjectPageModelsCardDeleteDialogFragmentDoc.definitions,...ProjectPageModelsActionsFragmentDoc.definitions,...ModelCardAutomationStatus_ModelFragmentDoc.definitions,...ModelCardAutomationStatus_AutomationsStatusFragmentDoc.definitions]} as unknown as DocumentNode<ProjectLatestModelsPaginationQuery, ProjectLatestModelsPaginationQueryVariables>;
export const ProjectModelsTreeTopLevelDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ProjectModelsTreeTopLevel"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ProjectModelsTreeFilter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"modelsTree"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"cursor"},"value":{"kind":"NullValue"}},{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"8"}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SingleLevelModelTreeItem"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"pendingImportedModels"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"PendingFileUpload"}}]}}]}}]}},...SingleLevelModelTreeItemFragmentDoc.definitions,...ProjectPageLatestItemsModelItemFragmentDoc.definitions,...PendingFileUploadFragmentDoc.definitions,...ProjectPageModelsCardRenameDialogFragmentDoc.definitions,...ProjectPageModelsCardDeleteDialogFragmentDoc.definitions,...ProjectPageModelsActionsFragmentDoc.definitions,...ModelCardAutomationStatus_ModelFragmentDoc.definitions,...ModelCardAutomationStatus_AutomationsStatusFragmentDoc.definitions]} as unknown as DocumentNode<ProjectModelsTreeTopLevelQuery, ProjectModelsTreeTopLevelQueryVariables>;
@@ -3914,7 +3942,7 @@ export const ProjectModelsPageDocument = {"kind":"Document","definitions":[{"kin
export const ProjectDiscussionsPageDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ProjectDiscussionsPage"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectDiscussionsPageHeader_Project"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectDiscussionsPageResults_Project"}}]}}]}},...ProjectDiscussionsPageHeader_ProjectFragmentDoc.definitions,...ProjectDiscussionsPageResults_ProjectFragmentDoc.definitions]} as unknown as DocumentNode<ProjectDiscussionsPageQuery, ProjectDiscussionsPageQueryVariables>;
export const ProjectWebhooksDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ProjectWebhooks"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"webhooks"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"streamId"}},{"kind":"Field","name":{"kind":"Name","value":"triggers"}},{"kind":"Field","name":{"kind":"Name","value":"enabled"}},{"kind":"Field","name":{"kind":"Name","value":"url"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"history"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"5"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"statusInfo"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}}]}}]}}]} as unknown as DocumentNode<ProjectWebhooksQuery, ProjectWebhooksQueryVariables>;
export const BlobDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Blob"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"blobId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"streamId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"stream"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"streamId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"blob"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"blobId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"fileName"}},{"kind":"Field","name":{"kind":"Name","value":"fileType"}},{"kind":"Field","name":{"kind":"Name","value":"fileSize"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}}]}}]}}]} as unknown as DocumentNode<BlobQuery, BlobQueryVariables>;
export const OnProjectUpdatedDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"subscription","name":{"kind":"Name","value":"OnProjectUpdated"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectUpdated"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"project"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageProject"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectDashboardItemNoModels"}}]}}]}}]}},...ProjectPageProjectFragmentDoc.definitions,...ProjectPageProjectHeaderFragmentDoc.definitions,...ProjectPageStatsBlockTeamFragmentDoc.definitions,...LimitedUserAvatarFragmentDoc.definitions,...ProjectPageTeamDialogFragmentDoc.definitions,...ProjectsPageTeamDialogManagePermissions_ProjectFragmentDoc.definitions,...ProjectPageStatsBlockVersionsFragmentDoc.definitions,...ProjectPageStatsBlockModelsFragmentDoc.definitions,...ProjectPageStatsBlockCommentsFragmentDoc.definitions,...ProjectPageLatestItemsModelsFragmentDoc.definitions,...ProjectPageModelsStructureItem_ProjectFragmentDoc.definitions,...ProjectPageModelsActions_ProjectFragmentDoc.definitions,...ProjectsModelPageEmbed_ProjectFragmentDoc.definitions,...ProjectPageLatestItemsCommentsFragmentDoc.definitions,...ProjectDashboardItemNoModelsFragmentDoc.definitions,...ProjectPageModelsCardProjectFragmentDoc.definitions]} as unknown as DocumentNode<OnProjectUpdatedSubscription, OnProjectUpdatedSubscriptionVariables>;
export const OnProjectUpdatedDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"subscription","name":{"kind":"Name","value":"OnProjectUpdated"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectUpdated"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"project"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageProject"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectDashboardItemNoModels"}}]}}]}}]}},...ProjectPageProjectFragmentDoc.definitions,...ProjectPageProjectHeaderFragmentDoc.definitions,...ProjectPageTeamDialogFragmentDoc.definitions,...LimitedUserAvatarFragmentDoc.definitions,...ProjectsPageTeamDialogManagePermissions_ProjectFragmentDoc.definitions,...ProjectDashboardItemNoModelsFragmentDoc.definitions,...ProjectPageModelsCardProjectFragmentDoc.definitions,...ProjectPageModelsActions_ProjectFragmentDoc.definitions,...ProjectsModelPageEmbed_ProjectFragmentDoc.definitions]} as unknown as DocumentNode<OnProjectUpdatedSubscription, OnProjectUpdatedSubscriptionVariables>;
export const OnProjectModelsUpdateDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"subscription","name":{"kind":"Name","value":"OnProjectModelsUpdate"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectModelsUpdated"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"model"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"versions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"1"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"referencedObject"}}]}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageLatestItemsModelItem"}}]}}]}}]}},...ProjectPageLatestItemsModelItemFragmentDoc.definitions,...PendingFileUploadFragmentDoc.definitions,...ProjectPageModelsCardRenameDialogFragmentDoc.definitions,...ProjectPageModelsCardDeleteDialogFragmentDoc.definitions,...ProjectPageModelsActionsFragmentDoc.definitions,...ModelCardAutomationStatus_ModelFragmentDoc.definitions,...ModelCardAutomationStatus_AutomationsStatusFragmentDoc.definitions]} as unknown as DocumentNode<OnProjectModelsUpdateSubscription, OnProjectModelsUpdateSubscriptionVariables>;
export const OnProjectVersionsUpdateDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"subscription","name":{"kind":"Name","value":"OnProjectVersionsUpdate"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectVersionsUpdated"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"modelId"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"version"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewerModelVersionCardItem"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectModelPageVersionsCardVersion"}},{"kind":"Field","name":{"kind":"Name","value":"model"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageLatestItemsModelItem"}}]}}]}}]}}]}},...ViewerModelVersionCardItemFragmentDoc.definitions,...LimitedUserAvatarFragmentDoc.definitions,...ProjectModelPageVersionsCardVersionFragmentDoc.definitions,...ProjectModelPageDialogDeleteVersionFragmentDoc.definitions,...ProjectModelPageDialogMoveToVersionFragmentDoc.definitions,...ModelCardAutomationStatus_VersionFragmentDoc.definitions,...ModelCardAutomationStatus_AutomationsStatusFragmentDoc.definitions,...ProjectPageLatestItemsModelItemFragmentDoc.definitions,...PendingFileUploadFragmentDoc.definitions,...ProjectPageModelsCardRenameDialogFragmentDoc.definitions,...ProjectPageModelsCardDeleteDialogFragmentDoc.definitions,...ProjectPageModelsActionsFragmentDoc.definitions,...ModelCardAutomationStatus_ModelFragmentDoc.definitions]} as unknown as DocumentNode<OnProjectVersionsUpdateSubscription, OnProjectVersionsUpdateSubscriptionVariables>;
export const OnProjectVersionsPreviewGeneratedDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"subscription","name":{"kind":"Name","value":"OnProjectVersionsPreviewGenerated"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectVersionsPreviewGenerated"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectId"}},{"kind":"Field","name":{"kind":"Name","value":"objectId"}},{"kind":"Field","name":{"kind":"Name","value":"versionId"}}]}}]}}]} as unknown as DocumentNode<OnProjectVersionsPreviewGeneratedSubscription, OnProjectVersionsPreviewGeneratedSubscriptionVariables>;
@@ -13,7 +13,7 @@ export const downloadManagerRoute = '/download-manager'
export const serverManagementRoute = '/server-management'
export const projectRoute = (
id: string,
tab?: 'models' | 'discussions' | 'automations'
tab?: 'models' | 'discussions' | 'automations' | 'settings'
) => {
let res = `/projects/${id}`
if (tab && tab !== 'models') {
@@ -39,8 +39,14 @@ export const allProjectModelsRoute = (projectId: string) => `/projects/${project
// Temp change to projectDiscussionsRoute until tab routing is implemented
export const projectDiscussionsRoute = (projectId: string) => `/projects/${projectId}`
export const projectSettingsRoute = (projectId: string) =>
`/projects/${projectId}/settings`
export const projectCollaboratorsRoute = (projectId: string) =>
`/projects/${projectId}/settings/collaborators`
export const projectWebhooksRoute = (projectId: string) =>
`/projects/${projectId}/webhooks`
`/projects/${projectId}/settings/webhooks`
export const automationDataPageRoute = (baseUrl: string, automationId: string) =>
new URL(`/automations/${automationId}`, baseUrl).toString()
@@ -268,16 +268,19 @@ export function useUpdateProject() {
return async (
update: ProjectUpdateInput,
options?: Partial<{ optimisticResponse: UpdateProjectMetadataMutation }>
options?: Partial<{
customSuccessMessage?: string
optimisticResponse: UpdateProjectMetadataMutation
}>
) => {
if (!activeUser.value) return
const successMessage = options?.customSuccessMessage || 'Project updated'
const result = await apollo
.mutate({
mutation: updateProjectMetadataMutation,
variables: {
update
},
variables: { update },
optimisticResponse: options?.optimisticResponse
})
.catch(convertThrowIntoFetchResult)
@@ -285,7 +288,7 @@ export function useUpdateProject() {
if (result?.data?.projectMutations.update?.id) {
triggerNotification({
type: ToastNotificationType.Success,
title: 'Project updated'
title: successMessage
})
} else {
const errMsg = getFirstErrorMessage(result.errors)
@@ -1,24 +1,47 @@
import { Roles } from '@speckle/shared'
import type { Nullable, ServerRoles } from '@speckle/shared'
import { graphql } from '~/lib/common/generated/gql/gql'
import { useActiveUser } from '~~/lib/auth/composables/activeUser'
import type {
ProjectPageTeamDialogFragment,
ProjectPageTeamInternals_ProjectFragment,
ProjectsPageTeamDialogManagePermissions_ProjectFragment
} from '~~/lib/common/generated/gql/graphql'
import type { ProjectCollaboratorListItem } from '~~/lib/projects/helpers/components'
export function useTeamManagePermissionsInternals(params: {
props: {
project: Ref<ProjectsPageTeamDialogManagePermissions_ProjectFragment>
graphql(`
fragment ProjectPageTeamInternals_Project on Project {
id
role
invitedTeam {
id
title
role
inviteId
user {
role
...LimitedUserAvatar
}
}
team {
role
user {
role
...LimitedUserAvatar
}
}
}
}) {
const {
props: { project }
} = params
`)
export function useTeamManagePermissionsInternals(
project: Ref<
| ProjectsPageTeamDialogManagePermissions_ProjectFragment
| ProjectPageTeamInternals_ProjectFragment
| undefined
>
) {
const { isGuest: isServerGuest, activeUser } = useActiveUser()
const isOwner = computed(() => project.value.role === Roles.Stream.Owner)
const isOwner = computed(() => project.value?.role === Roles.Stream.Owner)
return {
activeUser,
@@ -27,22 +50,16 @@ export function useTeamManagePermissionsInternals(params: {
}
}
export function useTeamDialogInternals(params: {
props: {
project: Ref<ProjectPageTeamDialogFragment>
}
}) {
const {
props: { project }
} = params
const { isOwner, isServerGuest, activeUser } =
useTeamManagePermissionsInternals(params)
export function useTeamInternals(
projectData: ComputedRef<ProjectPageTeamInternals_ProjectFragment | undefined>
) {
const { isOwner, activeUser, isServerGuest } =
useTeamManagePermissionsInternals(projectData)
const collaboratorListItems = computed((): ProjectCollaboratorListItem[] => {
const results: ProjectCollaboratorListItem[] = []
for (const invitedUser of project.value.invitedTeam || []) {
for (const invitedUser of projectData.value?.invitedTeam || []) {
results.push({
id: invitedUser.id,
title: invitedUser.title,
@@ -53,7 +70,7 @@ export function useTeamDialogInternals(params: {
})
}
for (const collaborator of project.value.team) {
for (const collaborator of projectData.value?.team ?? []) {
results.push({
id: collaborator.user.id,
title: collaborator.user.name,
@@ -68,11 +85,12 @@ export function useTeamDialogInternals(params: {
})
const canLeaveProject = computed(() => {
if (!activeUser.value) return false
if (!project.value.role) return false
if (!activeUser.value || !projectData.value?.role) {
return false
}
const userId = activeUser.value.id
const owners = project.value.team.filter((t) => t.role === Roles.Stream.Owner)
const owners = projectData.value.team.filter((t) => t.role === Roles.Stream.Owner)
return owners.length !== 1 || owners[0].user.id !== userId
})
@@ -81,3 +81,47 @@ export const projectUpdatableMetadataFragment = graphql(`
allowPublicComments
}
`)
export const projectPageLatestItemsModelsFragment = graphql(`
fragment ProjectPageLatestItemsModels on Project {
id
role
visibility
modelCount: models(limit: 0) {
totalCount
}
...ProjectPageModelsStructureItem_Project
}
`)
export const projectPageLatestItemsCommentsFragment = graphql(`
fragment ProjectPageLatestItemsComments on Project {
id
commentThreadCount: commentThreads(limit: 0) {
totalCount
}
}
`)
export const projectPageLatestItemsCommentItemFragment = graphql(`
fragment ProjectPageLatestItemsCommentItem on Comment {
id
author {
...FormUsersSelectItem
}
screenshot
rawText
createdAt
updatedAt
archived
repliesCount: replies(limit: 0) {
totalCount
}
replyAuthors(limit: 4) {
totalCount
items {
...FormUsersSelectItem
}
}
}
`)
@@ -50,7 +50,7 @@ export const commentPermissionsSelectItems: Record<
},
[CommentPermissions.TeamMembersOnly]: {
id: CommentPermissions.TeamMembersOnly,
title: 'Only team members can comment'
title: 'Only collaborators can comment'
}
}
@@ -11,14 +11,11 @@
class="flex flex-col md:flex-row md:justify-between md:items-start gap-8 sm:gap-4 my-8"
>
<ProjectPageHeader :project="project" />
<ProjectPageStatsBlockSettings
:project="project"
class="w-full md:w-72 shrink-0"
/>
<ProjectPageTeamBlock :project="project" class="w-full md:w-72 shrink-0" />
</div>
<LayoutPageTabs v-model:active-item="activePageTab" :items="pageTabItems">
<NuxtPage />
</LayoutPageTabs>
<LayoutTabsHoriztonal v-model:active-item="activePageTab" :items="pageTabItems">
<NuxtPage :project="project" />
</LayoutTabsHoriztonal>
</div>
</div>
</template>
@@ -32,23 +29,27 @@ import {
projectPageQuery
} from '~~/lib/projects/graphql/queries'
import { useGeneralProjectPageUpdateTracking } from '~~/lib/projects/composables/projectPages'
import { LayoutPageTabs, type LayoutPageTabItem } from '@speckle/ui-components'
import { CubeIcon, ChatBubbleLeftRightIcon } from '@heroicons/vue/24/outline'
import { projectRoute } from '~/lib/common/helpers/route'
import { LayoutTabsHoriztonal, type LayoutPageTabItem } from '@speckle/ui-components'
import {
CubeIcon,
ChatBubbleLeftRightIcon,
Cog6ToothIcon
} from '@heroicons/vue/24/outline'
import { projectRoute, projectWebhooksRoute } from '~/lib/common/helpers/route'
import { convertThrowIntoFetchResult } from '~/lib/common/helpers/graphql'
graphql(`
fragment ProjectPageProject on Project {
id
createdAt
modelCount: models(limit: 0) {
totalCount
}
commentThreadCount: commentThreads(limit: 0) {
totalCount
}
...ProjectPageProjectHeader
...ProjectPageStatsBlockTeam
...ProjectPageTeamDialog
...ProjectPageStatsBlockVersions
...ProjectPageStatsBlockModels
...ProjectPageStatsBlockComments
...ProjectPageLatestItemsModels
...ProjectPageLatestItemsComments
}
`)
@@ -61,9 +62,14 @@ definePageMeta({
if (/\/models\/?$/i.test(to.path)) {
return navigateTo(projectRoute(projectId))
}
// Redirect from /projects/:id/webhooks to /projects/:id/settings/webhooks
if (/\/projects\/\w*?\/webhooks/i.test(to.path)) {
return navigateTo(projectWebhooksRoute(projectId))
}
}
],
alias: '/projects/:id/models'
alias: ['/projects/:id/models', '/projects/:id/webhooks']
})
const route = useRoute()
@@ -115,28 +121,34 @@ const pageTabItems = computed((): LayoutPageTabItem[] => [
{
title: 'Models',
id: 'models',
icon: CubeIcon,
count: modelCount.value
count: modelCount.value,
icon: CubeIcon
},
{
title: 'Discussions',
id: 'discussions',
icon: ChatBubbleLeftRightIcon,
count: commentCount.value
}
// {
count: commentCount.value,
icon: ChatBubbleLeftRightIcon
},
// {
// title: 'Automations',
// id: 'automations',
// icon: BoltIcon,
// tag: 'New'
// }
// tag: 'New',
// icon: BoltIcon
// },
{
title: 'Settings',
id: 'settings',
icon: Cog6ToothIcon
}
])
const activePageTab = computed({
get: () => {
const path = router.currentRoute.value.path
if (/\/discussions\/?$/i.test(path)) return pageTabItems.value[1]
if (/\/automations\/?$/i.test(path)) return pageTabItems.value[2]
// if (/\/automations\/?$/i.test(path)) return pageTabItems.value[2]
if (/\/settings\/?/i.test(path)) return pageTabItems.value[2]
return pageTabItems.value[0]
},
set: (val: LayoutPageTabItem) => {
@@ -150,6 +162,9 @@ const activePageTab = computed({
case 'automations':
router.push({ path: projectRoute(projectId.value, 'automations') })
break
case 'settings':
router.push({ path: projectRoute(projectId.value, 'settings') })
break
}
}
})
@@ -0,0 +1,79 @@
<template>
<div>
<h1 class="block h4 font-bold mb-4 sm:mb-8">Settings</h1>
<LayoutTabsVertical
v-model:active-item="activeSettingsPageTab"
:items="settingsTabItems"
>
<NuxtPage />
</LayoutTabsVertical>
</div>
</template>
<script setup lang="ts">
import { LayoutTabsVertical, type LayoutPageTabItem } from '@speckle/ui-components'
import {
projectCollaboratorsRoute,
projectSettingsRoute,
projectWebhooksRoute
} from '~~/lib/common/helpers/route'
import { graphql } from '~~/lib/common/generated/gql'
import type { ProjectPageProjectFragment } from '~~/lib/common/generated/gql/graphql'
import { Roles } from '@speckle/shared'
graphql(`
fragment ProjectPageSettingsTab_Project on Project {
id
role
}
`)
const attrs = useAttrs() as {
project: ProjectPageProjectFragment
}
const route = useRoute()
const router = useRouter()
const isOwner = computed(() => attrs.project.role === Roles.Stream.Owner)
const settingsTabItems = computed((): LayoutPageTabItem[] => [
{
title: 'General',
id: 'general'
},
{
title: 'Collaborators',
id: 'collaborators'
},
{
title: 'Webhooks',
id: 'webhooks',
disabled: !isOwner.value,
disabledMessage: !isOwner.value ? 'You must be the project owner' : undefined
}
])
const projectId = computed(() => route.params.id as string)
const activeSettingsPageTab = computed({
get: () => {
const path = route.path
if (path.includes('/settings/collaborators')) return settingsTabItems.value[1]
if (path.includes('/settings/webhooks')) return settingsTabItems.value[2]
return settingsTabItems.value[0]
},
set: (val: LayoutPageTabItem) => {
switch (val.id) {
case 'collaborators':
router.push(projectCollaboratorsRoute(projectId.value))
break
case 'webhooks':
router.push(projectWebhooksRoute(projectId.value))
break
case 'general':
default:
router.push(projectSettingsRoute(projectId.value))
break
}
}
})
</script>
@@ -0,0 +1,3 @@
<template>
<ProjectPageSettingsCollaborators />
</template>
@@ -0,0 +1,3 @@
<template>
<ProjectPageSettingsGeneral />
</template>
@@ -0,0 +1,3 @@
<template>
<ProjectPageSettingsWebhooks />
</template>
@@ -0,0 +1,77 @@
import type { Meta, StoryObj } from '@storybook/vue3'
import RadioGroup from './RadioGroup.vue'
import { ChartBarIcon, WrenchIcon, WalletIcon } from '@heroicons/vue/24/outline'
import type { ConcreteComponent } from 'vue'
import { useStorybookVmodel } from '~~/src/composables/testing' // Adjust this path to match your project structure
type RadioGroupStoryType = StoryObj<{
'update:modelValue'?: (val: string) => void
modelValue: string
options: Array<{
value: string
title: string
introduction: string
icon: ConcreteComponent
help?: string
}>
}>
export default {
title: 'Components/Form/RadioGroup',
component: RadioGroup,
argTypes: {
'update:modelValue': {
action: 'update:modelValue',
type: 'function'
}
},
parameters: {
docs: {
description: {
component:
'A customizable radio group component with titles, icons, and introductions for each option.'
}
}
}
} as Meta
export const Default: RadioGroupStoryType = {
render: (args, { ...ctx }) => ({
components: { RadioGroup },
setup() {
// Use the custom composable to create a two-way binding and log actions
const { model } = useStorybookVmodel({ args, prop: 'modelValue', ctx })
return { args, model }
},
template: `
<div>
<RadioGroup v-bind="args" v-model:modelValue="model" />
</div>
`
}),
args: {
modelValue: 'option1',
options: [
{
value: 'option1',
title: 'Option 1',
introduction: 'Introduction for Option 1',
icon: ChartBarIcon
},
{
value: 'option2',
title: 'Option 2',
introduction: 'Introduction for Option 2',
icon: WalletIcon
},
{
value: 'option3',
title: 'Option 3',
introduction:
'Introduction for Option 3 but a bit longer so it drops onto 2 lines',
icon: WrenchIcon,
help: 'This is an example helper'
}
]
}
}
@@ -0,0 +1,93 @@
<template>
<div>
<div class="flex flex-col sm:flex-row items-stretch gap-3 w-full">
<div v-for="option in options" :key="option.value" class="w-full flex flex-col">
<button
class="relative w-full h-full select-none rounded-md shadow border"
:class="[
selected === option.value
? 'bg-foundation-page border-outline-1'
: 'bg-foundation border-outline-3',
disabled ? 'opacity-60 cursor-not-allowed' : 'hover:border-outline-1'
]"
:disabled="disabled"
@click="selectItem(option.value)"
>
<div
class="absolute top-4 right-3 h-6 w-6 rounded-full"
:class="[selected === option.value ? '' : 'border border-outline-3']"
>
<div
v-if="selected === option.value"
class="h-full w-full rounded-full bg-primary flex items-center justify-center"
>
<CheckIcon class="w-4 h-4 text-white" />
</div>
</div>
<div class="px-3 py-4 flex flex-col gap-3 h-full">
<component
:is="option.icon"
class="text-foreground h-8 w-8 -mt-1 stroke-[1px]"
></component>
<div class="flex flex-col items-start text-left">
<h4
class="font-bold text-base"
:class="option.introduction ? 'text-base' : 'text-sm'"
>
{{ option.title }}
</h4>
<div
v-if="option.introduction"
class="text-xs text-foreground-2 py-1 select-none"
>
{{ option.introduction }}
</div>
</div>
</div>
</button>
<div
v-if="option.help"
class="sm:hidden text-xs flex gap-0.5 mt-2 text-foreground"
>
<InformationCircleIcon class="h-4 w-4" />
{{ option.help }}
</div>
</div>
</div>
<div class="hidden sm:flex flex-col sm:flex-row gap-3 w-full">
<div v-for="option in options" :key="option.value" class="w-full">
<div
v-if="option.help"
class="text-xs flex gap-0.5 mt-2 text-foreground select-none"
>
<InformationCircleIcon class="h-4 w-4" />
{{ option.help }}
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { CheckIcon, InformationCircleIcon } from '@heroicons/vue/24/outline'
import type { ConcreteComponent } from 'vue'
type OptionType = {
value: string
title: string
introduction?: string
icon: ConcreteComponent
help?: string
}
defineProps<{
options: OptionType[]
disabled?: boolean
}>()
const selected = defineModel<string>()
const selectItem = (value: string) => {
selected.value = value
}
</script>
@@ -13,7 +13,7 @@
coreClasses,
iconClasses,
textareaClasses || '',
'min-h-[3rem] simple-scrollbar text-sm'
'min-h-[6rem] sm:min-h-[3rem] simple-scrollbar text-sm'
]"
:placeholder="placeholder"
:disabled="disabled"
@@ -31,6 +31,10 @@ export default {
'update:modelValue': {
type: 'function',
action: 'v-model'
},
size: {
control: { type: 'select' },
options: ['sm', 'lg', 'base', 'xl']
}
}
} as Meta
@@ -2,6 +2,7 @@
<div :class="[fullWidth ? 'w-full' : '', wrapperClasses]">
<label :for="name" :class="labelClasses">
<span>{{ title }}</span>
<div v-if="showRequired" class="text-danger text-xs opacity-80">*</div>
</label>
<div class="relative">
<div
@@ -64,7 +65,7 @@
<ExclamationCircleIcon class="h-4 w-4 text-danger" aria-hidden="true" />
</div>
<div
v-if="showRequired && !errorMessage"
v-if="!showLabel && showRequired && !errorMessage"
class="pointer-events-none absolute inset-y-0 mt-3 text-4xl right-0 flex items-center text-danger opacity-50"
:class="[showClear ? 'pr-8' : 'pr-2']"
>
@@ -11,11 +11,12 @@
>
<ListboxLabel
:id="labelId"
class="block label text-foreground-2 mb-2"
class="flex label text-foreground mb-1.5"
:class="{ 'sr-only': !showLabel }"
:for="buttonId"
>
{{ label }}
<div v-if="showRequired" class="text-danger text-xs opacity-80">*</div>
</ListboxLabel>
<div :class="buttonsWrapperClasses">
<!-- <div class="relative flex"> -->
@@ -47,7 +48,7 @@
aria-hidden="true"
/>
<div
v-else-if="showRequired"
v-else-if="!showLabel && showRequired"
class="text-4xl text-danger opacity-50 h-4 w-4 leading-6"
>
*
@@ -64,6 +65,8 @@
/>
</div>
</div>
<!-- Sync isOpen with dropdown open state -->
<template v-if="(isOpen = open)"></template>
</ListboxButton>
<!-- </div> -->
<!-- Clear Button -->
@@ -171,12 +174,7 @@
</Transition>
</div>
</Listbox>
<p
v-if="helpTipId"
:id="helpTipId"
class="mt-2 text-xs sm:text-sm"
:class="helpTipClasses"
>
<p v-if="helpTipId" :id="helpTipId" class="mt-2 text-xs" :class="helpTipClasses">
{{ helpTip }}
</p>
</div>
@@ -421,6 +419,7 @@ const currentItems = ref([]) as Ref<SingleItem[]>
const isAsyncLoading = ref(false)
const forceUpdateKey = ref(1)
const internalHelpTipId = ref(nanoid())
const isOpen = ref(false)
const listboxButtonBounding = useElementBounding(
computed(() => listboxButton.value?.el),
@@ -466,8 +465,12 @@ const buttonsWrapperClasses = computed(() => {
classParts.push('outline outline-2 outline-danger')
}
} else if (props.buttonStyle !== 'simple') {
classParts.push('hover:shadow rounded-md')
classParts.push('outline outline-2 outline-primary-muted')
classParts.push('rounded-md border')
if (isOpen.value) {
classParts.push('border-outline-1')
} else {
classParts.push('border-outline-3')
}
}
if (props.fixedHeight) {
@@ -56,7 +56,7 @@
<XMarkIcon class="h-5 sm:h-6 w-5 sm:w-6" />
</button>
<div
class="flex-1 simple-scrollbar overflow-y-auto"
class="flex-1 simple-scrollbar overflow-y-auto text-sm sm:text-base"
:class="hasTitle ? 'p-3 sm:py-6 sm:px-8' : 'p-6 pt-10 sm:p-10'"
@scroll="onScroll"
>
@@ -1,108 +0,0 @@
import type { Meta, StoryObj } from '@storybook/vue3'
import LayoutPageTabs from '~~/src/components/layout/PageTabs.vue'
import type { LayoutPageTabItem } from '~~/src/helpers/layout/components'
import {
CubeIcon,
Cog6ToothIcon,
BoltIcon,
ChatBubbleLeftRightIcon
} from '@heroicons/vue/24/outline'
import { useStorybookVmodel } from '~~/src/composables/testing'
const items: LayoutPageTabItem[] = [
{ title: 'Models', id: 'models', icon: CubeIcon, count: 300 },
{ title: 'Discussions', id: 'discussions', icon: ChatBubbleLeftRightIcon },
{ title: 'Automations', id: 'automations', icon: BoltIcon, tag: 'New' },
{ title: 'Settings', id: 'settings', icon: Cog6ToothIcon }
]
export default {
component: LayoutPageTabs,
parameters: {
docs: {
description: {
component: 'Page tabs component'
}
}
},
argTypes: {
items: {
description: 'Array of items to display in the tab'
},
title: {
description: 'Title of the tab'
},
vertical: {
description: 'Whether to display the tabs vertically'
},
activeItem: {
description: 'The active item model. Not required.'
},
'update:activeItem': {
description: 'Event emitted when the active item changes',
type: 'function',
action: 'v-model:activeItem'
}
}
} as Meta
export const Default: StoryObj = {
render: (args, ctx) => ({
components: { LayoutPageTabs },
setup() {
const { model } = useStorybookVmodel({ args, prop: 'activeItem', ctx })
return { args, model }
},
template: `
<div>
<LayoutPageTabs v-slot="{ activeItem }" v-bind="args" v-model:activeItem="model">
<div>Title: {{ activeItem?.title }}</div>
<div>ID: {{ activeItem?.id }}</div>
</LayoutPageTabs>
</div>`
}),
args: {
items,
title: 'Settings',
activeItem: items[0]
}
}
export const Vertical: StoryObj = {
...Default,
args: {
...Default.args,
vertical: true
}
}
export const WithActiveItemModel: StoryObj = {
...Default,
args: {
...Default.args,
activeItem: items[2]
}
}
export const WithActiveItemModelBlocked: StoryObj = {
...WithActiveItemModel,
render: (args, ctx) => ({
components: { LayoutPageTabs },
setup() {
const { model } = useStorybookVmodel({
args,
prop: 'activeItem',
ctx,
blockChanges: true
})
return { args, model }
},
template: `
<div>
<LayoutPageTabs v-slot="{ activeItem }" v-bind="args" v-model:activeItem="model">
<div>Title: {{ activeItem?.title }}</div>
<div>ID: {{ activeItem?.id }}</div>
</LayoutPageTabs>
</div>`
})
}
@@ -1,138 +0,0 @@
<template>
<div
class="relative z-10 flex gap-4"
:class="vertical ? 'sm:gap-8 flex-col sm:flex-row' : 'sm:gap-10 flex-col'"
>
<div
class="relative flex sm:justify-between overflow-x-auto"
:class="
vertical
? 'items-center sm:items-start sm:flex-col sm:w-2/12 border-r border-outline gap-4 pl-4'
: 'border-b border-outline-3 lg:border-none gap-8 w-full'
"
>
<template v-if="!vertical">
<div
class="hidden lg:block absolute bottom-0 left-0 h-px w-full bg-outline-3"
></div>
<div
:style="borderStyle"
class="h-[2px] absolute bottom-0 z-20 bg-primary transition-all duration-300"
></div>
</template>
<div
ref="buttonContainer"
class="flex"
:class="
vertical ? 'flex-wrap sm:flex-nowrap flex-row sm:flex-col gap-4' : 'gap-6'
"
>
<h1
v-if="title"
class="font-bold h4"
:class="vertical ? 'w-full sm:w-auto -ml-4 mb-4' : 'mb-2'"
>
{{ title }}
</h1>
<button
v-for="item in items"
:key="item.id"
:data-tab-id="item.id"
class="tab-button relative z-10 flex items-center gap-1.5 pb-2 border-b-[2px] border-transparent text-base max-w-max px-2"
:class="[
activeItem?.id === item.id
? 'text-primary hover:text-primary'
: 'text-foreground',
vertical ? 'hover:border-outline' : 'hover:border-outline-2'
]"
@click="setActiveItem(item)"
>
<Component
:is="item.icon"
v-if="item.icon"
class="shrink-0 h-4 w-4 stroke-[2px]"
/>
<span class="min-w-6">{{ item.title }}</span>
<div
v-if="item.count"
class="rounded-full px-2 text-[11px] transition-all min-w-6"
:class="
activeItem?.id === item.id
? 'text-primary bg-blue-100'
: 'text-foreground-2 bg-gray-200 dark:bg-foundation'
"
>
<span>{{ item.count }}</span>
</div>
<div
v-if="item.tag"
class="text-[10px] leading-tight py-0.5 text-foreground-on-primary font-medium px-1.5 rounded-full bg-gradient-to-tr from-[#7025EB] to-primary select-none mt-0.5"
>
{{ item.tag }}
</div>
</button>
</div>
</div>
<div :class="vertical ? 'sm:w-10/12' : ''">
<slot :active-item="activeItem" />
</div>
</div>
</template>
<script setup lang="ts">
import { computed, ref, type CSSProperties, onMounted, watch } from 'vue'
import type { LayoutPageTabItem } from '~~/src/helpers/layout/components'
import type { Nullable } from '@speckle/shared'
import { isClient } from '@vueuse/core'
const props = defineProps<{
items: LayoutPageTabItem[]
vertical?: boolean
title?: string
}>()
const activeItem = defineModel<LayoutPageTabItem>('activeItem', { required: true })
const buttonContainer = ref(null as Nullable<HTMLDivElement>)
const activeItemRef = computed(() => {
const id = activeItem.value?.id
if (!id) return null
const parent = buttonContainer.value
if (!parent) return null
const btns = [...parent.getElementsByClassName('tab-button')] as HTMLButtonElement[]
return btns.find((b) => b.dataset['tabId'] === id) || null
})
const borderStyle = computed(() => {
const element = activeItemRef.value
const style: CSSProperties = {
left: `${element?.offsetLeft || 0}px`,
width: `${element?.clientWidth || 0}px`
}
return style
})
const setActiveItem = (item: LayoutPageTabItem) => {
activeItem.value = item
}
if (isClient) {
// Doing onMounted & watch separately to avoid hydration mismatch
onMounted(() => {
if (props.items.length && !activeItem.value) {
setActiveItem(props.items[0])
}
})
watch(
() => [props.items, activeItem.value] as const,
([newItems, activeItem]) => {
if (newItems.length && !activeItem) {
setActiveItem(newItems[0])
}
}
)
}
</script>
@@ -1,9 +1,11 @@
<template>
<div class="text-foreground">
<div class="w-full text-sm overflow-x-auto overflow-y-visible simple-scrollbar">
<div
class="w-full text-sm overflow-x-auto overflow-y-visible simple-scrollbar border border-outline-3 rounded-lg"
>
<div
v-if="items.length > 0"
class="grid z-10 grid-cols-12 items-center gap-6 font-semibold bg-foundation rounded-t-lg w-full border-b border-outline-3 pb-2 pt-4 px-4 min-w-[900px]"
class="grid z-10 grid-cols-12 items-center gap-6 font-semibold bg-foundation-page rounded-t-lg w-full border-b border-outline-3 pb-2 pt-4 px-4 min-w-[900px]"
:style="{ paddingRight: paddingRightStyle }"
>
<div
@@ -1,38 +0,0 @@
import type { Meta, StoryObj } from '@storybook/vue3'
import LayoutTabs from '~~/src/components/layout/Tabs.vue'
import type { LayoutTabItem } from '~~/src/helpers/layout/components'
export default {
component: LayoutTabs,
parameters: {
docs: {
description: {
component: 'Standard tabs component'
}
}
}
} as Meta
const defaultItems: LayoutTabItem[] = [
{ title: 'First tab', id: 'first' },
{ title: 'Second tab', id: 'second' }
]
export const Default: StoryObj = {
render: (args) => ({
components: { LayoutTabs },
setup() {
return { args }
},
template: `
<div>
<LayoutTabs v-slot="{ activeItem }" v-bind="args">
<div>Title: {{ activeItem.title }}</div>
<div>ID: {{ activeItem.id }}</div>
</LayoutTabs>
</div>`
}),
args: {
items: defaultItems
}
}
@@ -1,37 +0,0 @@
<template>
<div class="flex flex-col gap-y-0 sm:gap-y-4">
<div class="flex gap-x-6">
<FormButton
v-for="item in items"
:key="item.id"
link
:color="activeItem.id === item.id ? 'default' : 'secondary'"
@click="onTabClick(item)"
>
{{ item.title }}
</FormButton>
</div>
<slot :active-item="activeItem" />
</div>
</template>
<script setup lang="ts">
/* eslint-disable @typescript-eslint/no-explicit-any */
import type { Nullable } from '@speckle/shared'
import { computed, ref } from 'vue'
import type { LayoutTabItem } from '~~/src/helpers/layout/components'
import FormButton from '~~/src/components/form/Button.vue'
const props = defineProps<{
items: LayoutTabItem<any>[]
}>()
const activeItemId = ref(null as Nullable<string>)
const activeItem = computed(() => {
if (!activeItemId.value) return props.items[0]
return props.items.find((i) => i.id === activeItemId.value) || props.items[0]
})
const onTabClick = (item: LayoutTabItem) => {
activeItemId.value = item.id
}
</script>
@@ -0,0 +1,67 @@
import type { Meta, StoryObj } from '@storybook/vue3'
import LayoutTabsHorizontal from '~~/src/components/layout/tabs/Horizontal.vue'
import type { LayoutPageTabItem } from '~~/src/helpers/layout/components'
import { useStorybookVmodel } from '~~/src/composables/testing'
const items: LayoutPageTabItem[] = [
{ title: 'Models', id: 'models', count: 300 },
{ title: 'Discussions', id: 'discussions' },
{ title: 'Automations', id: 'automations', tag: 'New' },
{ title: 'Settings', id: 'settings' },
{
title: 'Disabled Item',
id: 'disabled',
disabled: true,
disabledMessage: 'Example disabled message'
}
]
export default {
component: LayoutTabsHorizontal,
parameters: {
docs: {
description: {
component:
'This component displays a set of horizontal tabs, allowing user interaction and selection.'
}
}
},
argTypes: {
items: {
description: 'Array of items to display in the tabs'
},
title: {
description: 'Title of the tabs, displayed above the tabs if provided'
},
activeItem: {
description: 'The active item model. Not required.'
},
'update:activeItem': {
description: 'Event emitted when the active item changes',
type: 'function',
action: 'v-model:activeItem'
}
}
} as Meta
export const Default: StoryObj = {
render: (args, ctx) => ({
components: { LayoutTabsHorizontal },
setup() {
const { model } = useStorybookVmodel({ args, prop: 'activeItem', ctx })
return { args, model }
},
template: `
<div>
<LayoutTabsHorizontal v-slot="{ activeItem }" v-bind="args" v-model:activeItem="model">
<div>Title: {{ activeItem?.title }}</div>
<div>ID: {{ activeItem?.id }}</div>
</LayoutTabsHorizontal>
</div>`
}),
args: {
items,
title: 'Tab Example',
activeItem: items[2]
}
}
@@ -0,0 +1,241 @@
<template>
<div class="relative z-10 flex gap-4 md:gap-6 flex-col">
<!-- Left Arrow Button -->
<div
class="absolute left-[-2px] top-[-2px] z-20 pr-8 bg-gradient-to-r from-foundation-page to-transparent"
>
<button
v-if="showLeftArrow"
class="bg-foundation p-1 rounded-full border border-outline-4 shadow"
@click="scrollLeft"
>
<ArrowLongLeftIcon class="h-4 w-4" />
</button>
</div>
<div class="absolute left-0 z-10 w-full h-[1px] mt-px bg-outline-3 top-8"></div>
<div
ref="scrollContainer"
class="relative flex overflow-x-auto hide-scrollbar gap-8 w-full"
@scroll="handleScroll"
>
<div
:style="borderStyle"
class="h-[2px] absolute bottom-0 z-20 transition-[left,width] duration-300"
:class="isInitialSetup ? 'bg-transparent' : 'bg-primary'"
></div>
<div ref="buttonContainer" class="flex w-full gap-2 sm:gap-3">
<button
v-for="item in items"
:key="item.id"
:data-tab-id="item.id"
:class="[
buttonClass(item),
{ '!border-primary': isActiveItem(item) && isInitialSetup }
]"
class="tab-button"
:disabled="item.disabled"
@click="setActiveItem(item)"
>
<div
v-tippy="
item.disabled && item.disabledMessage ? item.disabledMessage : undefined
"
class="absolute inset-0"
></div>
<div class="flex gap-2 items-center px-2">
<component
:is="item.icon"
v-if="item.icon"
class="shrink-0 h-4 w-4 stroke-[2px]"
></component>
<span class="min-w-6">{{ item.title }}</span>
<div
v-if="item.count"
class="rounded-full px-2 text-[11px] transition-all min-w-6"
:class="
activeItem?.id === item.id
? 'text-primary bg-blue-100'
: 'text-foreground-2 bg-gray-200 dark:bg-foundation'
"
>
<span>{{ item.count }}</span>
</div>
<div
v-if="item.tag"
class="text-[10px] leading-tight py-0.5 text-foreground-on-primary font-medium px-1.5 rounded-full bg-gradient-to-tr from-[#7025EB] to-primary select-none mt-0.5"
>
{{ item.tag }}
</div>
</div>
</button>
</div>
</div>
<!-- Right Arrow Button -->
<div
class="absolute right-[-2px] top-[-2px] z-20 pl-8 bg-gradient-to-l from-foundation-page to-transparent"
>
<button
v-if="showRightArrow"
class="bg-foundation p-1 rounded-full border border-outline-3 shadow"
@click="scrollRight"
>
<ArrowLongRightIcon class="h-4 w-4" />
</button>
</div>
<div>
<slot :active-item="activeItem" />
</div>
</div>
</template>
<script setup lang="ts">
import { computed, ref, onMounted, watch, onBeforeUnmount } from 'vue'
import type { CSSProperties } from 'vue'
import type { LayoutPageTabItem } from '~~/src/helpers/layout/components'
import { isClient } from '@vueuse/core'
import { ArrowLongRightIcon, ArrowLongLeftIcon } from '@heroicons/vue/24/outline'
import type { Nullable } from '@speckle/shared'
import { throttle } from 'lodash-es'
const props = defineProps<{
items: LayoutPageTabItem[]
}>()
const activeItem = defineModel<LayoutPageTabItem>('activeItem', { required: true })
const buttonContainer = ref(null as Nullable<HTMLDivElement>)
const scrollContainer = ref<HTMLElement | null>(null)
const showLeftArrow = ref(false)
const showRightArrow = ref(false)
const isInitialSetup = ref(true)
const buttonClass = computed(() => {
return (item: LayoutPageTabItem) => {
const isActive = activeItem.value?.id === item.id
const baseClasses = [
'relative',
'z-10',
'flex',
'items-center',
'disabled:opacity-60 disabled:hover:border-transparent disabled:cursor-not-allowed disabled:hover:bg-transparent',
'text-base',
'gap-1.5',
'hover:sm:border-outline-2',
'pb-2',
'border-b-[2px]',
'border-transparent',
'max-w-max',
'last:mr-6',
'whitespace-nowrap'
]
if (isActive) baseClasses.push('text-primary', 'hover:text-primary')
else baseClasses.push('text-foreground')
return baseClasses
}
})
const activeItemRef = computed(() => {
const id = activeItem.value?.id
if (!id) return null
const parent = buttonContainer.value
if (!parent) return null
const btns = [...parent.getElementsByClassName('tab-button')] as HTMLElement[]
return btns.find((b) => b.dataset['tabId'] === id) || null
})
const borderStyle = computed<CSSProperties>(() => {
const element = activeItemRef.value
return {
left: `${element?.offsetLeft || 0}px`,
width: `${element?.clientWidth || 0}px`
}
})
const setActiveItem = (item: LayoutPageTabItem) => {
activeItem.value = item
isInitialSetup.value = false
}
const isActiveItem = (item: LayoutPageTabItem) => {
return activeItem.value?.id === item.id
}
const checkArrowsVisibility = () => {
const container = scrollContainer.value
if (!container) return
const scrollWidth = container.scrollWidth
const clientWidth = container.clientWidth
const scrollLeft = container.scrollLeft
const buffer = 1
showLeftArrow.value = scrollLeft > buffer
showRightArrow.value = scrollLeft < scrollWidth - clientWidth - buffer
}
const scrollLeft = () => {
scrollContainer.value?.scrollBy({ left: -100, behavior: 'smooth' }) // Adjust the scroll amount as needed
checkArrowsVisibility()
}
const scrollRight = () => {
scrollContainer.value?.scrollBy({ left: 100, behavior: 'smooth' }) // Adjust the scroll amount as needed
checkArrowsVisibility()
}
const handleScroll = throttle(() => {
checkArrowsVisibility()
}, 250)
const ensureActiveItemVisible = () => {
const activeButton = activeItemRef.value
if (activeButton && scrollContainer.value) {
activeButton.scrollIntoView({
behavior: 'smooth',
block: 'nearest',
inline: 'center'
})
}
}
onMounted(() => {
if (isClient) {
if (props.items.length && !activeItem.value) {
setActiveItem(props.items[0])
}
checkArrowsVisibility()
ensureActiveItemVisible()
}
})
watch(
() => [props.items, activeItem.value] as const,
([newItems]) => {
if (Array.isArray(newItems) && newItems.length && !activeItem.value) {
setActiveItem(newItems[0] as LayoutPageTabItem)
}
checkArrowsVisibility()
}
)
onBeforeUnmount(() => {
handleScroll.cancel()
})
</script>
<style>
/* Hide scrollbar for Chrome, Safari and Opera */
.hide-scrollbar::-webkit-scrollbar {
display: none;
}
/* Hide scrollbar for IE, Edge and Firefox */
.hide-scrollbar {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
</style>
@@ -0,0 +1,67 @@
import type { Meta, StoryObj } from '@storybook/vue3'
import LayoutTabsVertical from '~~/src/components/layout/tabs/Vertical.vue'
import type { LayoutPageTabItem } from '~~/src/helpers/layout/components'
import { useStorybookVmodel } from '~~/src/composables/testing'
const items: LayoutPageTabItem[] = [
{ title: 'Models', id: 'models', count: 300 },
{ title: 'Discussions', id: 'discussions' },
{ title: 'Automations', id: 'automations', tag: 'New' },
{ title: 'Settings', id: 'settings' },
{
title: 'Disabled Item',
id: 'disabled',
disabled: true,
disabledMessage: 'Example disabled message'
}
]
export default {
component: LayoutTabsVertical,
parameters: {
docs: {
description: {
component:
'This component displays a set of vertical tabs, allowing user interaction and selection.'
}
}
},
argTypes: {
items: {
description: 'Array of items to display in the tabs'
},
title: {
description: 'Title of the tabs, displayed above the tabs if provided'
},
activeItem: {
description: 'The active item model. Not required.'
},
'update:activeItem': {
description: 'Event emitted when the active item changes',
type: 'function',
action: 'v-model:activeItem'
}
}
} as Meta
export const Default: StoryObj = {
render: (args, ctx) => ({
components: { LayoutTabsVertical },
setup() {
const { model } = useStorybookVmodel({ args, prop: 'activeItem', ctx })
return { args, model }
},
template: `
<div>
<LayoutTabsVertical v-slot="{ activeItem }" v-bind="args" v-model:activeItem="model">
<div>Title: {{ activeItem?.title }}</div>
<div>ID: {{ activeItem?.id }}</div>
</LayoutTabsVertical>
</div>`
}),
args: {
items,
title: 'Tab Example',
activeItem: items[2]
}
}
@@ -0,0 +1,107 @@
<template>
<div class="flex gap-8 flex-col lg:flex-row">
<div class="lg:w-2/12">
<div class="flex w-full flex-col gap-1">
<button
v-for="item in items"
:key="item.id"
:data-tab-id="item.id"
:class="[buttonClass(item)]"
:disabled="item.disabled"
@click="setActiveItem(item)"
>
<div
v-tippy="
item.disabled && item.disabledMessage ? item.disabledMessage : undefined
"
class="absolute inset-0"
></div>
<div class="flex gap-2 items-center px-2">
<component
:is="item.icon"
v-if="item.icon"
class="shrink-0 h-4 w-4 stroke-[2px]"
></component>
<span class="min-w-6">{{ item.title }}</span>
<div
v-if="item.count"
class="rounded-full px-2 text-[11px] transition-all min-w-6"
:class="
activeItem?.id === item.id
? 'text-primary bg-blue-100'
: 'text-foreground-2 bg-gray-200 dark:bg-foundation'
"
>
<span>{{ item.count }}</span>
</div>
<div
v-if="item.tag"
class="text-[10px] leading-tight py-0.5 text-foreground-on-primary font-medium px-1.5 rounded-full bg-gradient-to-tr from-[#7025EB] to-primary select-none mt-0.5"
>
{{ item.tag }}
</div>
</div>
</button>
</div>
</div>
<div class="lg:w-10/12">
<slot :active-item="activeItem" />
</div>
</div>
</template>
<script setup lang="ts">
import { computed, onMounted, watch } from 'vue'
import type { LayoutPageTabItem } from '~~/src/helpers/layout/components'
import { isClient } from '@vueuse/core'
const props = defineProps<{
items: LayoutPageTabItem[]
}>()
const activeItem = defineModel<LayoutPageTabItem>('activeItem', { required: true })
const buttonClass = computed(() => {
return (item: LayoutPageTabItem) => {
const isActive = activeItem.value?.id === item.id
const baseClasses = [
'relative',
'flex items-center gap-1.5',
'disabled:opacity-60 disabled:hover:border-transparent disabled:cursor-not-allowed disabled:hover:bg-transparent',
'text-base',
'border-l-2',
'py-1'
]
if (isActive)
baseClasses.push(
'text-primary hover:text-primary bg-primary-muted border-primary'
)
else baseClasses.push('border-transparent text-foreground')
return baseClasses
}
})
const setActiveItem = (item: LayoutPageTabItem) => {
activeItem.value = item
}
onMounted(() => {
if (isClient) {
if (props.items.length && !activeItem.value) {
setActiveItem(props.items[0])
}
}
})
watch(
() => [props.items, activeItem.value],
([newItems]) => {
if (Array.isArray(newItems) && newItems.length && !activeItem.value) {
setActiveItem(newItems[0])
}
}
)
</script>
@@ -46,7 +46,10 @@ export function useTextInputCore<V extends string | string[] = string>(params: {
})
const labelClasses = computed(() => {
const classParts = ['block label text-foreground-2 mb-2']
const classParts = [
'flex label mb-1.5',
unref(props.color) === 'foundation' ? 'text-foreground' : 'text-foreground-2'
]
if (!unref(props.showLabel)) {
classParts.push('sr-only')
}
@@ -58,7 +61,7 @@ export function useTextInputCore<V extends string | string[] = string>(params: {
const classParts: string[] = [
'focus:outline-none disabled:cursor-not-allowed disabled:bg-foundation-disabled',
'disabled:text-disabled-muted placeholder:text-foreground-2',
'rounded'
'rounded-md'
]
return classParts.join(' ')
@@ -80,7 +83,9 @@ export function useTextInputCore<V extends string | string[] = string>(params: {
const color = unref(props.color)
if (color === 'foundation') {
classParts.push('bg-foundation shadow-sm hover:shadow')
classParts.push(
'bg-foundation !border border-outline-3 focus:border-outline-1 focus:!outline-0 focus:!ring-0'
)
} else if (color === 'transparent') {
classParts.push('bg-transparent')
} else {
@@ -108,7 +113,7 @@ export function useTextInputCore<V extends string | string[] = string>(params: {
hasHelpTip.value ? `${unref(props.name)}-${internalHelpTipId.value}` : undefined
)
const helpTipClasses = computed((): string => {
const classParts = ['mt-2 text-xs sm:text-sm']
const classParts = ['mt-2 text-xs']
classParts.push(error.value ? 'text-danger' : 'text-foreground-2')
return classParts.join(' ')
})
@@ -1,4 +1,5 @@
import type { ConcreteComponent } from 'vue'
import type { PropAnyComponent } from '~~/src/helpers/common/components'
export enum GridListToggleValue {
Grid = 'grid',
@@ -13,9 +14,11 @@ export type LayoutTabItem<I extends string = string> = {
export type LayoutPageTabItem<I extends string = string> = {
title: string
id: I
icon?: ConcreteComponent
count?: number
tag?: string
icon?: PropAnyComponent
disabled?: boolean
disabledMessage?: string
}
export type LayoutMenuItem<I extends string = string> = {
+9 -5
View File
@@ -20,6 +20,7 @@ import CommonVimeoEmbed from '~~/src/components/common/VimeoEmbed.vue'
import FormCardButton from '~~/src/components/form/CardButton.vue'
import FormCheckbox from '~~/src/components/form/Checkbox.vue'
import FormRadio from '~~/src/components/form/Radio.vue'
import FormRadioGroup from '~~/src/components/form/RadioGroup.vue'
import FormTextArea from '~~/src/components/form/TextArea.vue'
import FormTextInput from '~~/src/components/form/TextInput.vue'
import * as ValidationHelpers from '~~/src/helpers/common/validation'
@@ -53,8 +54,8 @@ import {
} from '~~/src/composables/common/window'
import LayoutMenu from '~~/src/components/layout/Menu.vue'
import type { LayoutMenuItem, LayoutTabItem } from '~~/src/helpers/layout/components'
import LayoutTabs from '~~/src/components/layout/Tabs.vue'
import LayoutPageTabs from '~~/src/components/layout/PageTabs.vue'
import LayoutTabsHoriztonal from '~~/src/components/layout/tabs/Horizontal.vue'
import LayoutTabsVertical from '~~/src/components/layout/tabs/Vertical.vue'
import LayoutTable from '~~/src/components/layout/Table.vue'
import InfiniteLoading from '~~/src/components/InfiniteLoading.vue'
import type { InfiniteLoaderState } from '~~/src/helpers/global/components'
@@ -81,6 +82,7 @@ import type {
} from '~~/src/composables/form/fileUpload'
import { UniqueFileTypeSpecifier, prettyFileSize } from '~~/src/helpers/form/file'
import type { FileTypeSpecifier } from '~~/src/helpers/form/file'
import type { PropAnyComponent } from '~~/src/helpers/common/components'
export * from '~~/src/helpers/common/error'
import CommonLoadingIcon from '~~/src/components/common/loading/Icon.vue'
import type { AvatarUser, AvatarUserWithId } from '~~/src/composables/user/avatar'
@@ -107,6 +109,7 @@ export {
FormCardButton,
FormCheckbox,
FormRadio,
FormRadioGroup,
FormTextArea,
FormTextInput,
FormSwitch,
@@ -134,8 +137,8 @@ export {
useOnBeforeWindowUnload,
useResponsiveHorizontalDirectionCalculation,
LayoutMenu,
LayoutTabs,
LayoutPageTabs,
LayoutTabsHoriztonal,
LayoutTabsVertical,
LayoutTable,
InfiniteLoading,
LayoutPanel,
@@ -162,5 +165,6 @@ export type {
FileTypeSpecifier,
AvatarUser,
AvatarUserWithId,
LayoutPageTabItem
LayoutPageTabItem,
PropAnyComponent
}
+3 -1
View File
@@ -126,7 +126,9 @@
"Vue.volar",
"bradlc.vscode-tailwindcss",
"stylelint.vscode-stylelint",
"cpylua.language-postcss"
"cpylua.language-postcss",
"graphql.vscode-graphql",
"graphql.vscode-graphql-syntax"
],
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
"unwantedRecommendations": ["octref.vetur", "vscode.typescript-language-features"]