From 2be1592341beff3dba79f1c5433ed2d16d1d1005 Mon Sep 17 00:00:00 2001 From: Kristaps Fabians Geikins Date: Wed, 18 Jun 2025 10:56:33 +0300 Subject: [PATCH] feat: show historical model uploads (#4954) * ensure modelId is always filled * BE seems fine * frontendd * pagination fix * table max height * lint fix * unset tiny limit * test fix --- .../project/page/models/Actions.vue | 28 ++- .../project/page/models/UploadsDialog.vue | 206 ++++++++++++++++++ .../lib/common/composables/graphql.ts | 36 ++- .../lib/common/generated/gql/gql.ts | 12 + .../lib/common/generated/gql/graphql.ts | 42 ++++ .../frontend-2/lib/core/configs/apollo.ts | 4 + packages/frontend-2/package.json | 4 +- .../fileuploads/typedefs/fileuploads.graphql | 22 ++ .../modules/core/graph/generated/graphql.ts | 34 +++ .../graph/generated/graphql.ts | 21 ++ .../modules/fileuploads/domain/operations.ts | 38 +++- .../graph/resolvers/fileUploads.ts | 31 ++- packages/server/modules/fileuploads/index.ts | 4 +- ...616114012_drop_metadata_in_file_uploads.ts | 16 ++ .../fileuploads/repositories/fileUploads.ts | 87 ++++++-- .../modules/fileuploads/rest/nextGenRouter.ts | 4 +- .../server/modules/fileuploads/rest/router.ts | 10 +- .../fileuploads/services/management.ts | 23 ++ .../fileuploads/services/resultHandler.ts | 20 +- .../fileuploads/services/resultListener.ts | 15 +- .../fileuploads/tests/helpers/creation.ts | 3 +- .../tests/unit/fileuploads.spec.ts | 9 +- .../modules/shared/helpers/graphqlHelper.ts | 94 +++++++- .../server/test/graphql/generated/graphql.ts | 21 ++ packages/shared/src/blobs/index.ts | 19 ++ .../src/components/common/Badge.stories.ts | 4 + .../src/components/layout/Table.stories.ts | 17 +- .../src/components/layout/Table.vue | 35 ++- yarn.lock | 30 +-- 29 files changed, 796 insertions(+), 93 deletions(-) create mode 100644 packages/frontend-2/components/project/page/models/UploadsDialog.vue create mode 100644 packages/server/modules/fileuploads/migrations/20250616114012_drop_metadata_in_file_uploads.ts diff --git a/packages/frontend-2/components/project/page/models/Actions.vue b/packages/frontend-2/components/project/page/models/Actions.vue index 15010ca71..b27d042f0 100644 --- a/packages/frontend-2/components/project/page/models/Actions.vue +++ b/packages/frontend-2/components/project/page/models/Actions.vue @@ -30,10 +30,15 @@ @deleted="$emit('model-updated')" /> + diff --git a/packages/frontend-2/lib/common/composables/graphql.ts b/packages/frontend-2/lib/common/composables/graphql.ts index 0c2010ddc..e06ed12ea 100644 --- a/packages/frontend-2/lib/common/composables/graphql.ts +++ b/packages/frontend-2/lib/common/composables/graphql.ts @@ -136,10 +136,10 @@ export const usePaginatedQuery = < options, resolveCurrentResult, resolveNextPageVariables, - resolveInitialResult, - resolveCursorFromVariables + resolveInitialResult } = params const cacheBusterKey = ref(0) + const loadingCompleted = ref(false) // can't be a computed, because we have to invoke it on the result of the fetchMore call, // before the result has been merged into the cache and the results become merged with results @@ -164,6 +164,10 @@ export const usePaginatedQuery = < resolveCurrentResult(useQueryReturn.result.value) ) + const isVeryFirstLoading = computed( + () => useQueryReturn.loading.value && !currentResult.value?.items.length + ) + const getCursorForNextPage = () => { const currRes = currentResult.value const initRes = resolveInitialResult?.() @@ -174,9 +178,14 @@ export const usePaginatedQuery = < } const onInfiniteLoad = async (state: InfiniteLoaderState) => { + const loadComplete = () => { + state.complete() + loadingCompleted.value = true + } + const cursor = getCursorForNextPage() let loadMore = hasMoreToLoad(currentResult.value) - if (!loadMore || !cursor) return state.complete() + if (!loadMore || !cursor) return loadComplete() try { const res = await useQueryReturn.fetchMore({ @@ -191,22 +200,24 @@ export const usePaginatedQuery = < state.loaded() if (!loadMore) { - state.complete() + loadComplete() } } const bustCache = () => { cacheBusterKey.value++ + loadingCompleted.value = false } - // If for some reason the query is invoked w/ baseVariables & null cursor, we should bust the cache, - // & reset loader state, cause a refetch was triggered for some reason (maybe a cache eviction) - useQueryReturn.onResult(() => { - const vars = useQueryReturn.variables.value - const cursor = vars ? resolveCursorFromVariables(vars) : undefined + // If after the query runs there is still more to load, but loading is marked as complete (which can happen + // if cache is evicted and initial query reruns) - we should bust the cache, + // & reset loader state, so infinite loader restarts + useQueryReturn.onResult((res) => { + if (res.loading) return - if (!cursor) { - // TODO: Maybe add check to skip this on initial result? Lets see how well this works first + // If more to load & loading completed, bust cache + const moreToLoad = hasMoreToLoad(resolveCurrentResult(res?.data)) + if (moreToLoad && loadingCompleted.value) { bustCache() } }) @@ -215,7 +226,8 @@ export const usePaginatedQuery = < query: useQueryReturn, identifier: queryKey, onInfiniteLoad, - bustCache + bustCache, + isVeryFirstLoading } } diff --git a/packages/frontend-2/lib/common/generated/gql/gql.ts b/packages/frontend-2/lib/common/generated/gql/gql.ts index c2e97f95d..a7afe02d9 100644 --- a/packages/frontend-2/lib/common/generated/gql/gql.ts +++ b/packages/frontend-2/lib/common/generated/gql/gql.ts @@ -92,6 +92,8 @@ type Documents = { "\n fragment ProjectModelsPageResults_Project on Project {\n ...ProjectPageLatestItemsModels\n }\n": typeof types.ProjectModelsPageResults_ProjectFragmentDoc, "\n fragment ProjectPageModelsStructureItem_Project on Project {\n id\n ...ProjectPageModelsActions_Project\n ...ProjectCardImportFileArea_Project\n ...UseCanCreateModel_Project\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\n }\n }\n }\n": typeof types.ProjectPageModelsStructureItem_ProjectFragmentDoc, "\n fragment SingleLevelModelTreeItem on ModelsTreeItem {\n id\n name\n fullName\n model {\n ...ProjectPageLatestItemsModelItem\n ...ProjectCardImportFileArea_Model\n }\n hasChildren\n updatedAt\n }\n": typeof types.SingleLevelModelTreeItemFragmentDoc, + "\n fragment ProjectPageModelsUploadsDialog_FileUpload on FileUpload {\n id\n convertedStatus\n convertedMessage\n fileName\n fileSize\n convertedLastUpdate\n uploadDate\n uploadComplete\n branchName\n }\n": typeof types.ProjectPageModelsUploadsDialog_FileUploadFragmentDoc, + "\n query GetModelUploads(\n $projectId: String!\n $modelId: String!\n $input: GetModelUploadsInput!\n ) {\n project(id: $projectId) {\n id\n model(id: $modelId) {\n id\n uploads(input: $input) {\n totalCount\n cursor\n items {\n id\n ...ProjectPageModelsUploadsDialog_FileUpload\n }\n }\n }\n }\n }\n": typeof types.GetModelUploadsDocument, "\n fragment ProjectPageModelsCardDeleteDialog on Model {\n id\n name\n }\n": typeof types.ProjectPageModelsCardDeleteDialogFragmentDoc, "\n fragment ProjectPageModelsCardRenameDialog on Model {\n id\n name\n description\n }\n": typeof types.ProjectPageModelsCardRenameDialogFragmentDoc, "\n query ProjectPageSettingsGeneral($projectId: String!) {\n project(id: $projectId) {\n id\n ...ProjectPageSettingsGeneralBlockProjectInfo_Project\n ...ProjectPageSettingsGeneralBlockAccess_Project\n ...ProjectPageSettingsGeneralBlockDiscussions_Project\n ...ProjectPageSettingsGeneralBlockLeave_Project\n ...ProjectPageSettingsGeneralBlockDelete_Project\n ...ProjectPageTeamInternals_Project\n }\n }\n": typeof types.ProjectPageSettingsGeneralDocument, @@ -540,6 +542,8 @@ const documents: Documents = { "\n fragment ProjectModelsPageResults_Project on Project {\n ...ProjectPageLatestItemsModels\n }\n": types.ProjectModelsPageResults_ProjectFragmentDoc, "\n fragment ProjectPageModelsStructureItem_Project on Project {\n id\n ...ProjectPageModelsActions_Project\n ...ProjectCardImportFileArea_Project\n ...UseCanCreateModel_Project\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\n }\n }\n }\n": types.ProjectPageModelsStructureItem_ProjectFragmentDoc, "\n fragment SingleLevelModelTreeItem on ModelsTreeItem {\n id\n name\n fullName\n model {\n ...ProjectPageLatestItemsModelItem\n ...ProjectCardImportFileArea_Model\n }\n hasChildren\n updatedAt\n }\n": types.SingleLevelModelTreeItemFragmentDoc, + "\n fragment ProjectPageModelsUploadsDialog_FileUpload on FileUpload {\n id\n convertedStatus\n convertedMessage\n fileName\n fileSize\n convertedLastUpdate\n uploadDate\n uploadComplete\n branchName\n }\n": types.ProjectPageModelsUploadsDialog_FileUploadFragmentDoc, + "\n query GetModelUploads(\n $projectId: String!\n $modelId: String!\n $input: GetModelUploadsInput!\n ) {\n project(id: $projectId) {\n id\n model(id: $modelId) {\n id\n uploads(input: $input) {\n totalCount\n cursor\n items {\n id\n ...ProjectPageModelsUploadsDialog_FileUpload\n }\n }\n }\n }\n }\n": types.GetModelUploadsDocument, "\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 query ProjectPageSettingsGeneral($projectId: String!) {\n project(id: $projectId) {\n id\n ...ProjectPageSettingsGeneralBlockProjectInfo_Project\n ...ProjectPageSettingsGeneralBlockAccess_Project\n ...ProjectPageSettingsGeneralBlockDiscussions_Project\n ...ProjectPageSettingsGeneralBlockLeave_Project\n ...ProjectPageSettingsGeneralBlockDelete_Project\n ...ProjectPageTeamInternals_Project\n }\n }\n": types.ProjectPageSettingsGeneralDocument, @@ -1236,6 +1240,14 @@ export function graphql(source: "\n fragment ProjectPageModelsStructureItem_Pro * 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 SingleLevelModelTreeItem on ModelsTreeItem {\n id\n name\n fullName\n model {\n ...ProjectPageLatestItemsModelItem\n ...ProjectCardImportFileArea_Model\n }\n hasChildren\n updatedAt\n }\n"): (typeof documents)["\n fragment SingleLevelModelTreeItem on ModelsTreeItem {\n id\n name\n fullName\n model {\n ...ProjectPageLatestItemsModelItem\n ...ProjectCardImportFileArea_Model\n }\n hasChildren\n updatedAt\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 ProjectPageModelsUploadsDialog_FileUpload on FileUpload {\n id\n convertedStatus\n convertedMessage\n fileName\n fileSize\n convertedLastUpdate\n uploadDate\n uploadComplete\n branchName\n }\n"): (typeof documents)["\n fragment ProjectPageModelsUploadsDialog_FileUpload on FileUpload {\n id\n convertedStatus\n convertedMessage\n fileName\n fileSize\n convertedLastUpdate\n uploadDate\n uploadComplete\n branchName\n }\n"]; +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql(source: "\n query GetModelUploads(\n $projectId: String!\n $modelId: String!\n $input: GetModelUploadsInput!\n ) {\n project(id: $projectId) {\n id\n model(id: $modelId) {\n id\n uploads(input: $input) {\n totalCount\n cursor\n items {\n id\n ...ProjectPageModelsUploadsDialog_FileUpload\n }\n }\n }\n }\n }\n"): (typeof documents)["\n query GetModelUploads(\n $projectId: String!\n $modelId: String!\n $input: GetModelUploadsInput!\n ) {\n project(id: $projectId) {\n id\n model(id: $modelId) {\n id\n uploads(input: $input) {\n totalCount\n cursor\n items {\n id\n ...ProjectPageModelsUploadsDialog_FileUpload\n }\n }\n }\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/packages/frontend-2/lib/common/generated/gql/graphql.ts b/packages/frontend-2/lib/common/generated/gql/graphql.ts index c0c5c203f..f8ca9b394 100644 --- a/packages/frontend-2/lib/common/generated/gql/graphql.ts +++ b/packages/frontend-2/lib/common/generated/gql/graphql.ts @@ -1029,6 +1029,13 @@ export type FileUpload = { userId: Scalars['String']['output']; }; +export type FileUploadCollection = { + __typename?: 'FileUploadCollection'; + cursor?: Maybe; + items: Array; + totalCount: Scalars['Int']['output']; +}; + export type FileUploadMutations = { __typename?: 'FileUploadMutations'; /** @@ -1101,6 +1108,13 @@ export type GenerateFileUploadUrlOutput = { url: Scalars['String']['output']; }; +export type GetModelUploadsInput = { + /** The cursor for pagination. */ + cursor?: InputMaybe; + /** The maximum number of uploads to return. */ + limit?: InputMaybe; +}; + export type InvitableCollaboratorsFilter = { search?: InputMaybe; }; @@ -1319,6 +1333,8 @@ export type Model = { permissions: ModelPermissionChecks; previewUrl?: Maybe; updatedAt: Scalars['DateTime']['output']; + /** Get all file uploads ever done in this model */ + uploads: FileUploadCollection; version: Version; versions: VersionCollection; }; @@ -1335,6 +1351,11 @@ export type ModelPendingImportedVersionsArgs = { }; +export type ModelUploadsArgs = { + input?: InputMaybe; +}; + + export type ModelVersionArgs = { id: Scalars['String']['input']; }; @@ -5407,6 +5428,17 @@ export type ProjectPageModelsStructureItem_ProjectFragment = { __typename?: 'Pro export type SingleLevelModelTreeItemFragment = { __typename?: 'ModelsTreeItem', id: string, name: string, fullName: string, hasChildren: boolean, updatedAt: string, model?: { __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 }>, automationsStatus?: { __typename?: 'TriggeredAutomationsStatus', id: string, automationRuns: Array<{ __typename?: 'AutomateRun', id: string, functionRuns: Array<{ __typename?: 'AutomateFunctionRun', id: string, updatedAt: string, status: AutomateRunStatus, results?: {} | null, statusMessage?: string | null, contextView?: string | null, createdAt: string, function?: { __typename?: 'AutomateFunction', id: string, logo?: string | null, name: string } | null }>, automation: { __typename?: 'Automation', id: string, name: string } }> } | null, permissions: { __typename?: 'ModelPermissionChecks', canUpdate: { __typename?: 'PermissionCheckResult', authorized: boolean, code: string, message: string, payload?: {} | null }, canDelete: { __typename?: 'PermissionCheckResult', authorized: boolean, code: string, message: string, payload?: {} | null }, canCreateVersion: { __typename?: 'PermissionCheckResult', authorized: boolean, code: string, message: string, payload?: {} | null } } } | null }; +export type ProjectPageModelsUploadsDialog_FileUploadFragment = { __typename?: 'FileUpload', id: string, convertedStatus: number, convertedMessage?: string | null, fileName: string, fileSize: number, convertedLastUpdate: string, uploadDate: string, uploadComplete: boolean, branchName: string }; + +export type GetModelUploadsQueryVariables = Exact<{ + projectId: Scalars['String']['input']; + modelId: Scalars['String']['input']; + input: GetModelUploadsInput; +}>; + + +export type GetModelUploadsQuery = { __typename?: 'Query', project: { __typename?: 'Project', id: string, model: { __typename?: 'Model', id: string, uploads: { __typename?: 'FileUploadCollection', totalCount: number, cursor?: string | null, items: Array<{ __typename?: 'FileUpload', id: string, convertedStatus: number, convertedMessage?: string | null, fileName: string, fileSize: number, convertedLastUpdate: string, uploadDate: string, uploadComplete: boolean, branchName: string }> } } } }; + export type ProjectPageModelsCardDeleteDialogFragment = { __typename?: 'Model', id: string, name: string }; export type ProjectPageModelsCardRenameDialogFragment = { __typename?: 'Model', id: string, name: string, description?: string | null }; @@ -7398,6 +7430,7 @@ export const ProjectPageModelsCardDeleteDialogFragmentDoc = {"kind":"Document"," export const ProjectPageModelsActionsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageModelsActions"},"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":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canUpdate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}},{"kind":"Field","name":{"kind":"Name","value":"canDelete"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}},{"kind":"Field","name":{"kind":"Name","value":"canCreateVersion"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"FullPermissionCheckResult"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"PermissionCheckResult"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authorized"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"payload"}}]}}]} as unknown as DocumentNode; 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":"ProjectCardImportFileArea_Model"}},{"kind":"Field","name":{"kind":"Name","value":"automationsStatus"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateRunsTriggerStatus_TriggeredAutomationsStatus"}}]}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canUpdate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}},{"kind":"Field","name":{"kind":"Name","value":"canDelete"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"FullPermissionCheckResult"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"PermissionCheckResult"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authorized"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"payload"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"UseFileImport_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":"name"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"FunctionRunStatusForSummary"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateFunctionRun"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"status"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"TriggeredAutomationsStatusSummary"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"TriggeredAutomationsStatus"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"automationRuns"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"functionRuns"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"FunctionRunStatusForSummary"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateRunsTriggerStatusDialogFunctionRun_AutomateFunctionRun"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateFunctionRun"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"results"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"statusMessage"}},{"kind":"Field","name":{"kind":"Name","value":"contextView"}},{"kind":"Field","name":{"kind":"Name","value":"function"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomationsStatusOrderedRuns_AutomationRun"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateRun"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"automation"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"functionRuns"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateRunsTriggerStatusDialogRunsRows_AutomateRun"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateRun"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"functionRuns"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateRunsTriggerStatusDialogFunctionRun_AutomateFunctionRun"}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomationsStatusOrderedRuns_AutomationRun"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateRunsTriggerStatusDialog_TriggeredAutomationsStatus"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"TriggeredAutomationsStatus"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"automationRuns"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateRunsTriggerStatusDialogRunsRows_AutomateRun"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"PendingFileUpload"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"FileUpload"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"projectId"}},{"kind":"Field","name":{"kind":"Name","value":"modelName"}},{"kind":"Field","name":{"kind":"Name","value":"convertedStatus"}},{"kind":"Field","name":{"kind":"Name","value":"convertedMessage"}},{"kind":"Field","name":{"kind":"Name","value":"uploadDate"}},{"kind":"Field","name":{"kind":"Name","value":"convertedLastUpdate"}},{"kind":"Field","name":{"kind":"Name","value":"fileType"}},{"kind":"Field","name":{"kind":"Name","value":"fileName"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageModelsCardRenameDialog"},"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":"description"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageModelsCardDeleteDialog"},"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":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageModelsActions"},"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":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canUpdate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}},{"kind":"Field","name":{"kind":"Name","value":"canDelete"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}},{"kind":"Field","name":{"kind":"Name","value":"canCreateVersion"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectCardImportFileArea_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":"name"}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canCreateVersion"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"UseFileImport_Model"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateRunsTriggerStatus_TriggeredAutomationsStatus"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"TriggeredAutomationsStatus"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"TriggeredAutomationsStatusSummary"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateRunsTriggerStatusDialog_TriggeredAutomationsStatus"}}]}}]} as unknown as DocumentNode; 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":"FragmentSpread","name":{"kind":"Name","value":"ProjectCardImportFileArea_Model"}}]}},{"kind":"Field","name":{"kind":"Name","value":"hasChildren"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"PendingFileUpload"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"FileUpload"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"projectId"}},{"kind":"Field","name":{"kind":"Name","value":"modelName"}},{"kind":"Field","name":{"kind":"Name","value":"convertedStatus"}},{"kind":"Field","name":{"kind":"Name","value":"convertedMessage"}},{"kind":"Field","name":{"kind":"Name","value":"uploadDate"}},{"kind":"Field","name":{"kind":"Name","value":"convertedLastUpdate"}},{"kind":"Field","name":{"kind":"Name","value":"fileType"}},{"kind":"Field","name":{"kind":"Name","value":"fileName"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageModelsCardRenameDialog"},"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":"description"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageModelsCardDeleteDialog"},"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":"FragmentDefinition","name":{"kind":"Name","value":"FullPermissionCheckResult"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"PermissionCheckResult"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authorized"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"payload"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageModelsActions"},"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":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canUpdate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}},{"kind":"Field","name":{"kind":"Name","value":"canDelete"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}},{"kind":"Field","name":{"kind":"Name","value":"canCreateVersion"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"UseFileImport_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":"name"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectCardImportFileArea_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":"name"}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canCreateVersion"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"UseFileImport_Model"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"FunctionRunStatusForSummary"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateFunctionRun"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"status"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"TriggeredAutomationsStatusSummary"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"TriggeredAutomationsStatus"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"automationRuns"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"functionRuns"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"FunctionRunStatusForSummary"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateRunsTriggerStatusDialogFunctionRun_AutomateFunctionRun"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateFunctionRun"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"results"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"statusMessage"}},{"kind":"Field","name":{"kind":"Name","value":"contextView"}},{"kind":"Field","name":{"kind":"Name","value":"function"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomationsStatusOrderedRuns_AutomationRun"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateRun"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"automation"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"functionRuns"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateRunsTriggerStatusDialogRunsRows_AutomateRun"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateRun"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"functionRuns"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateRunsTriggerStatusDialogFunctionRun_AutomateFunctionRun"}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomationsStatusOrderedRuns_AutomationRun"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateRunsTriggerStatusDialog_TriggeredAutomationsStatus"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"TriggeredAutomationsStatus"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"automationRuns"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateRunsTriggerStatusDialogRunsRows_AutomateRun"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateRunsTriggerStatus_TriggeredAutomationsStatus"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"TriggeredAutomationsStatus"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"TriggeredAutomationsStatusSummary"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateRunsTriggerStatusDialog_TriggeredAutomationsStatus"}}]}},{"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":"ProjectCardImportFileArea_Model"}},{"kind":"Field","name":{"kind":"Name","value":"automationsStatus"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateRunsTriggerStatus_TriggeredAutomationsStatus"}}]}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canUpdate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}},{"kind":"Field","name":{"kind":"Name","value":"canDelete"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}}]}}]} as unknown as DocumentNode; +export const ProjectPageModelsUploadsDialog_FileUploadFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageModelsUploadsDialog_FileUpload"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"FileUpload"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"convertedStatus"}},{"kind":"Field","name":{"kind":"Name","value":"convertedMessage"}},{"kind":"Field","name":{"kind":"Name","value":"fileName"}},{"kind":"Field","name":{"kind":"Name","value":"fileSize"}},{"kind":"Field","name":{"kind":"Name","value":"convertedLastUpdate"}},{"kind":"Field","name":{"kind":"Name","value":"uploadDate"}},{"kind":"Field","name":{"kind":"Name","value":"uploadComplete"}},{"kind":"Field","name":{"kind":"Name","value":"branchName"}}]}}]} as unknown as DocumentNode; 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"}},{"kind":"Field","name":{"kind":"Name","value":"workspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canUpdate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"FullPermissionCheckResult"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"PermissionCheckResult"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authorized"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"payload"}}]}}]} as unknown as DocumentNode; export const ProjectsDeleteDialog_ProjectFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectsDeleteDialog_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":"workspace"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"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":"0"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canDelete"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"FullPermissionCheckResult"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"PermissionCheckResult"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authorized"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"payload"}}]}}]} as unknown as DocumentNode; 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":"FragmentSpread","name":{"kind":"Name","value":"ProjectsDeleteDialog_Project"}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canUpdate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"FullPermissionCheckResult"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"PermissionCheckResult"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authorized"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"payload"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectsDeleteDialog_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":"workspace"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"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":"0"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canDelete"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}}]}}]} as unknown as DocumentNode; @@ -7541,6 +7574,7 @@ export const AutomationCreateDialogFunctionsSearchDocument = {"kind":"Document", export const InviteDialogProjectRowProjectCollaboratorsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"InviteDialogProjectRowProjectCollaborators"},"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":"InvitableCollaboratorsFilter"}}}],"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":"invitableCollaborators"},"arguments":[{"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":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"InviteProjectItem_WorkspaceCollaborator"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"InviteProjectItem_WorkspaceCollaborator"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkspaceCollaborator"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"seatType"}},{"kind":"Field","name":{"kind":"Name","value":"role"}}]}}]} as unknown as DocumentNode; export const ProjectPageCollaboratorsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ProjectPageCollaborators"},"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":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"WorkspaceTeamFilter"}}}}],"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":"visibility"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageTeamInternals_Project"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"InviteDialogProject_Project"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageCollaborators_Project"}},{"kind":"Field","name":{"kind":"Name","value":"workspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canInvite"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"workspace"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SettingsWorkspacesMembersTableHeader_Workspace"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"team"},"arguments":[{"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":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageCollaborators_WorkspaceCollaborator"}}]}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"LimitedUserAvatar"},"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"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkspacesPlan_Workspace"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"plan"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"paymentMethod"}},{"kind":"Field","name":{"kind":"Name","value":"usage"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectCount"}},{"kind":"Field","name":{"kind":"Name","value":"modelCount"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"seats"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"editors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"assigned"}},{"kind":"Field","name":{"kind":"Name","value":"available"}}]}},{"kind":"Field","name":{"kind":"Name","value":"viewers"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"assigned"}},{"kind":"Field","name":{"kind":"Name","value":"available"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"subscription"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"billingInterval"}},{"kind":"Field","name":{"kind":"Name","value":"currentBillingCycleEnd"}},{"kind":"Field","name":{"kind":"Name","value":"currency"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"InviteDialogProjectRow_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":"workspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"workspace"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"role"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"FullPermissionCheckResult"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"PermissionCheckResult"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authorized"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"payload"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"InviteDialogProject_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":"workspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"workspace"},"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":"domainBasedMembershipProtectionEnabled"}},{"kind":"Field","name":{"kind":"Name","value":"domains"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"domain"}},{"kind":"Field","name":{"kind":"Name","value":"id"}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkspacesPlan_Workspace"}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"InviteDialogProjectRow_Project"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"UseCanInviteToProject_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":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canInvite"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"UseCanMoveProjectIntoWorkspace_Project"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canMoveToWorkspace"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkspaceMoveProject_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":"workspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canMoveToWorkspace"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"UseCanMoveProjectIntoWorkspace_Project"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectInviteAdd_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":"InviteDialogProject_Project"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"UseCanInviteToProject_Project"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkspaceMoveProject_Project"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"InviteDialogSharedSelectUsers_Workspace"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"defaultSeatType"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"InviteDialogWorkspace_Workspace"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"domainBasedMembershipProtectionEnabled"}},{"kind":"Field","name":{"kind":"Name","value":"defaultSeatType"}},{"kind":"Field","name":{"kind":"Name","value":"domains"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"domain"}},{"kind":"Field","name":{"kind":"Name","value":"id"}}]}},{"kind":"Field","name":{"kind":"Name","value":"seats"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"editors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"available"}}]}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"InviteDialogSharedSelectUsers_Workspace"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkspacesPlan_Workspace"}}]}},{"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":"seatType"}},{"kind":"Field","name":{"kind":"Name","value":"workspaceRole"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"LimitedUserAvatar"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageCollaborators_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":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canUpdate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectInviteAdd_Project"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SettingsWorkspacesMembersTableHeader_Workspace"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"InviteDialogWorkspace_Workspace"}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canInvite"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageCollaborators_WorkspaceCollaborator"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkspaceCollaborator"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"}}]}}]}}]} as unknown as DocumentNode; export const InvitableCollaboratorsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"InvitableCollaborators"},"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":"InvitableCollaboratorsFilter"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"limit"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}},"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":"invitableCollaborators"},"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":"Variable","name":{"kind":"Name","value":"limit"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"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":"avatar"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"workspaceRole"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"workspaceId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}}}]}]}}]}}]}}]}}]}}]} as unknown as DocumentNode; +export const GetModelUploadsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetModelUploads"},"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":"modelId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"GetModelUploadsInput"}}}}],"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":"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":"uploads"},"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":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageModelsUploadsDialog_FileUpload"}}]}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageModelsUploadsDialog_FileUpload"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"FileUpload"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"convertedStatus"}},{"kind":"Field","name":{"kind":"Name","value":"convertedMessage"}},{"kind":"Field","name":{"kind":"Name","value":"fileName"}},{"kind":"Field","name":{"kind":"Name","value":"fileSize"}},{"kind":"Field","name":{"kind":"Name","value":"convertedLastUpdate"}},{"kind":"Field","name":{"kind":"Name","value":"uploadDate"}},{"kind":"Field","name":{"kind":"Name","value":"uploadComplete"}},{"kind":"Field","name":{"kind":"Name","value":"branchName"}}]}}]} as unknown as DocumentNode; 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":"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"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"FullPermissionCheckResult"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"PermissionCheckResult"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authorized"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"payload"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"LimitedUserAvatar"},"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"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectsDeleteDialog_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":"workspace"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"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":"0"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canDelete"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}}]}},{"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":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canUpdate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}}]}},{"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"}},{"kind":"Field","name":{"kind":"Name","value":"workspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canUpdate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}}]}},{"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"}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canUpdateAllowPublicComments"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}}]}},{"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"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"workspace"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canLeave"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageSettingsGeneralBlockDelete_Project"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectsDeleteDialog_Project"}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canUpdate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}}]}},{"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":"seatType"}},{"kind":"Field","name":{"kind":"Name","value":"workspaceRole"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"LimitedUserAvatar"}}]}}]}}]}}]} as unknown as DocumentNode; export const WorkspaceAvailableEditorSeatsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"WorkspaceAvailableEditorSeats"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"slug"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspaceBySlug"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"slug"},"value":{"kind":"Variable","name":{"kind":"Name","value":"slug"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"seats"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"editors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"available"}}]}}]}}]}}]}}]} as unknown as DocumentNode; 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":"emails"},"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":"primary"}}]}},{"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"}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectsAdd_User"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"FullPermissionCheckResult"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"PermissionCheckResult"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authorized"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"payload"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"UseCanCreatePersonalProject_User"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"User"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canCreatePersonalProject"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectsAdd_User"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"User"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canCreatePersonalProject"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FullPermissionCheckResult"}}]}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"UseCanCreatePersonalProject_User"}}]}}]} as unknown as DocumentNode; @@ -7813,6 +7847,7 @@ export type AllObjectTypes = { CountOnlyCollection: CountOnlyCollection, CurrencyBasedPrices: CurrencyBasedPrices, FileUpload: FileUpload, + FileUploadCollection: FileUploadCollection, FileUploadMutations: FileUploadMutations, GendoAIRender: GendoAiRender, GendoAIRenderCollection: GendoAiRenderCollection, @@ -8292,6 +8327,11 @@ export type FileUploadFieldArgs = { uploadDate: {}, userId: {}, } +export type FileUploadCollectionFieldArgs = { + cursor: {}, + items: {}, + totalCount: {}, +} export type FileUploadMutationsFieldArgs = { generateUploadUrl: FileUploadMutationsGenerateUploadUrlArgs, startFileImport: FileUploadMutationsStartFileImportArgs, @@ -8386,6 +8426,7 @@ export type ModelFieldArgs = { permissions: {}, previewUrl: {}, updatedAt: {}, + uploads: ModelUploadsArgs, version: ModelVersionArgs, versions: ModelVersionsArgs, } @@ -9431,6 +9472,7 @@ export type AllObjectFieldArgTypes = { CountOnlyCollection: CountOnlyCollectionFieldArgs, CurrencyBasedPrices: CurrencyBasedPricesFieldArgs, FileUpload: FileUploadFieldArgs, + FileUploadCollection: FileUploadCollectionFieldArgs, FileUploadMutations: FileUploadMutationsFieldArgs, GendoAIRender: GendoAiRenderFieldArgs, GendoAIRenderCollection: GendoAiRenderCollectionFieldArgs, diff --git a/packages/frontend-2/lib/core/configs/apollo.ts b/packages/frontend-2/lib/core/configs/apollo.ts index 193e0fc9e..735acd4bd 100644 --- a/packages/frontend-2/lib/core/configs/apollo.ts +++ b/packages/frontend-2/lib/core/configs/apollo.ts @@ -230,6 +230,10 @@ function createCache(): InMemoryCache { }, permissions: { merge: mergeAsObjectsFunction + }, + uploads: { + keyArgs: ['input', ['limit']], + merge: buildAbstractCollectionMergeFunction('FileUploadCollection') } } }, diff --git a/packages/frontend-2/package.json b/packages/frontend-2/package.json index a749c7138..5890fe873 100644 --- a/packages/frontend-2/package.json +++ b/packages/frontend-2/package.json @@ -24,7 +24,7 @@ "datadog:publish-sourcemaps:dev": "DATADOG_SITE=\"datadoghq.eu\" datadog-ci sourcemaps upload ./.output/public/_nuxt --service=\"fe2-dev/test\" --release-version=\"unknown\" --minified-path-prefix=/_nuxt" }, "dependencies": { - "@apollo/client": "^3.12.4", + "@apollo/client": "^3.13.8", "@artmizu/nuxt-prometheus": "^2.2.1", "@datadog/browser-rum": "^5.11.0", "@headlessui/vue": "^1.7.13", @@ -55,7 +55,7 @@ "@tiptap/suggestion": "2.10.3", "@tiptap/vue-3": "2.10.3", "@tryghost/content-api": "^1.11.21", - "@vue/apollo-composable": "npm:@speckle/apollo-composable@4.2.1-patch.1", + "@vue/apollo-composable": "^4.2.2", "@vue/apollo-ssr": "4.0.0", "@vueuse/core": "^10.9.0", "apollo-upload-client": "^18.0.1", diff --git a/packages/server/assets/fileuploads/typedefs/fileuploads.graphql b/packages/server/assets/fileuploads/typedefs/fileuploads.graphql index 61a915ec3..a53515e5f 100644 --- a/packages/server/assets/fileuploads/typedefs/fileuploads.graphql +++ b/packages/server/assets/fileuploads/typedefs/fileuploads.graphql @@ -23,11 +23,33 @@ extend type Project { pendingImportedModels(limit: Int = 25): [FileUpload!]! } +type FileUploadCollection { + totalCount: Int! + cursor: String + items: [FileUpload!]! +} + +input GetModelUploadsInput { + """ + The maximum number of uploads to return. + """ + limit: Int = 25 + """ + The cursor for pagination. + """ + cursor: String +} + extend type Model { """ Returns a list of versions that are being created from a file import """ pendingImportedVersions(limit: Int = 25): [FileUpload!]! + + """ + Get all file uploads ever done in this model + """ + uploads(input: GetModelUploadsInput): FileUploadCollection! } type FileUpload { diff --git a/packages/server/modules/core/graph/generated/graphql.ts b/packages/server/modules/core/graph/generated/graphql.ts index 86cc9606b..fddceae88 100644 --- a/packages/server/modules/core/graph/generated/graphql.ts +++ b/packages/server/modules/core/graph/generated/graphql.ts @@ -1052,6 +1052,13 @@ export type FileUpload = { userId: Scalars['String']['output']; }; +export type FileUploadCollection = { + __typename?: 'FileUploadCollection'; + cursor?: Maybe; + items: Array; + totalCount: Scalars['Int']['output']; +}; + export type FileUploadMutations = { __typename?: 'FileUploadMutations'; /** @@ -1124,6 +1131,13 @@ export type GenerateFileUploadUrlOutput = { url: Scalars['String']['output']; }; +export type GetModelUploadsInput = { + /** The cursor for pagination. */ + cursor?: InputMaybe; + /** The maximum number of uploads to return. */ + limit?: InputMaybe; +}; + export type InvitableCollaboratorsFilter = { search?: InputMaybe; }; @@ -1342,6 +1356,8 @@ export type Model = { permissions: ModelPermissionChecks; previewUrl?: Maybe; updatedAt: Scalars['DateTime']['output']; + /** Get all file uploads ever done in this model */ + uploads: FileUploadCollection; version: Version; versions: VersionCollection; }; @@ -1358,6 +1374,11 @@ export type ModelPendingImportedVersionsArgs = { }; +export type ModelUploadsArgs = { + input?: InputMaybe; +}; + + export type ModelVersionArgs = { id: Scalars['String']['input']; }; @@ -5417,6 +5438,7 @@ export type ResolversTypes = { EditCommentInput: EditCommentInput; EmailVerificationRequestInput: EmailVerificationRequestInput; FileUpload: ResolverTypeWrapper; + FileUploadCollection: ResolverTypeWrapper & { items: Array }>; FileUploadMutations: ResolverTypeWrapper; Float: ResolverTypeWrapper; GendoAIRender: ResolverTypeWrapper; @@ -5424,6 +5446,7 @@ export type ResolversTypes = { GendoAIRenderInput: GendoAiRenderInput; GenerateFileUploadUrlInput: GenerateFileUploadUrlInput; GenerateFileUploadUrlOutput: ResolverTypeWrapper; + GetModelUploadsInput: GetModelUploadsInput; ID: ResolverTypeWrapper; Int: ResolverTypeWrapper; InvitableCollaboratorsFilter: InvitableCollaboratorsFilter; @@ -5757,6 +5780,7 @@ export type ResolversParentTypes = { EditCommentInput: EditCommentInput; EmailVerificationRequestInput: EmailVerificationRequestInput; FileUpload: FileUploadGraphQLReturn; + FileUploadCollection: Omit & { items: Array }; FileUploadMutations: MutationsObjectGraphQLReturn; Float: Scalars['Float']['output']; GendoAIRender: GendoAIRenderGraphQLReturn; @@ -5764,6 +5788,7 @@ export type ResolversParentTypes = { GendoAIRenderInput: GendoAiRenderInput; GenerateFileUploadUrlInput: GenerateFileUploadUrlInput; GenerateFileUploadUrlOutput: GenerateFileUploadUrlOutput; + GetModelUploadsInput: GetModelUploadsInput; ID: Scalars['ID']['output']; Int: Scalars['Int']['output']; InvitableCollaboratorsFilter: InvitableCollaboratorsFilter; @@ -6457,6 +6482,13 @@ export type FileUploadResolvers; }; +export type FileUploadCollectionResolvers = { + cursor?: Resolver, ParentType, ContextType>; + items?: Resolver, ParentType, ContextType>; + totalCount?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}; + export type FileUploadMutationsResolvers = { generateUploadUrl?: Resolver>; startFileImport?: Resolver>; @@ -6577,6 +6609,7 @@ export type ModelResolvers; previewUrl?: Resolver, ParentType, ContextType>; updatedAt?: Resolver; + uploads?: Resolver>; version?: Resolver>; versions?: Resolver>; __isTypeOf?: IsTypeOfResolverFn; @@ -7871,6 +7904,7 @@ export type Resolvers = { CurrencyBasedPrices?: CurrencyBasedPricesResolvers; DateTime?: GraphQLScalarType; FileUpload?: FileUploadResolvers; + FileUploadCollection?: FileUploadCollectionResolvers; FileUploadMutations?: FileUploadMutationsResolvers; GendoAIRender?: GendoAiRenderResolvers; GendoAIRenderCollection?: GendoAiRenderCollectionResolvers; diff --git a/packages/server/modules/cross-server-sync/graph/generated/graphql.ts b/packages/server/modules/cross-server-sync/graph/generated/graphql.ts index 171921e06..67c8b55b3 100644 --- a/packages/server/modules/cross-server-sync/graph/generated/graphql.ts +++ b/packages/server/modules/cross-server-sync/graph/generated/graphql.ts @@ -1032,6 +1032,13 @@ export type FileUpload = { userId: Scalars['String']['output']; }; +export type FileUploadCollection = { + __typename?: 'FileUploadCollection'; + cursor?: Maybe; + items: Array; + totalCount: Scalars['Int']['output']; +}; + export type FileUploadMutations = { __typename?: 'FileUploadMutations'; /** @@ -1104,6 +1111,13 @@ export type GenerateFileUploadUrlOutput = { url: Scalars['String']['output']; }; +export type GetModelUploadsInput = { + /** The cursor for pagination. */ + cursor?: InputMaybe; + /** The maximum number of uploads to return. */ + limit?: InputMaybe; +}; + export type InvitableCollaboratorsFilter = { search?: InputMaybe; }; @@ -1322,6 +1336,8 @@ export type Model = { permissions: ModelPermissionChecks; previewUrl?: Maybe; updatedAt: Scalars['DateTime']['output']; + /** Get all file uploads ever done in this model */ + uploads: FileUploadCollection; version: Version; versions: VersionCollection; }; @@ -1338,6 +1354,11 @@ export type ModelPendingImportedVersionsArgs = { }; +export type ModelUploadsArgs = { + input?: InputMaybe; +}; + + export type ModelVersionArgs = { id: Scalars['String']['input']; }; diff --git a/packages/server/modules/fileuploads/domain/operations.ts b/packages/server/modules/fileuploads/domain/operations.ts index 0c2a4b48c..d865dda3e 100644 --- a/packages/server/modules/fileuploads/domain/operations.ts +++ b/packages/server/modules/fileuploads/domain/operations.ts @@ -18,7 +18,13 @@ export type GetFileInfoV2 = (args: { export type SaveUploadFileInput = Pick< FileUploadRecord, - 'streamId' | 'branchName' | 'userId' | 'fileName' | 'fileType' | 'fileSize' + | 'streamId' + | 'branchName' + | 'userId' + | 'fileName' + | 'fileType' + | 'fileSize' + | 'modelId' > & { fileId: string } export type SaveUploadFileInputV2 = Pick< @@ -40,6 +46,11 @@ export type SaveUploadFileV2 = ( args: SaveUploadFileInputV2 ) => Promise +export type UpdateFileUpload = (args: { + id: string + upload: Partial +}) => Promise + export type GarbageCollectPendingUploadedFiles = (args: { timeoutThresholdSeconds: number }) => Promise @@ -79,3 +90,28 @@ export type RegisterUploadCompleteAndStartFileImport = (args: { expectedETag: string maximumFileSize: number }) => Promise + +export type GetModelUploadsBaseArgs = { + projectId: string + modelId: string +} + +export type GetModelUploadsArgs = GetModelUploadsBaseArgs & { + limit?: number + cursor?: string | null +} + +export type GetModelUploadsItems = (params: GetModelUploadsArgs) => Promise<{ + items: FileUploadRecord[] + cursor: string | null +}> + +export type GetModelUploadsTotalCount = ( + params: GetModelUploadsBaseArgs +) => Promise + +export type GetModelUploads = (params: GetModelUploadsArgs) => Promise<{ + items: FileUploadRecord[] + totalCount: number + cursor: string | null +}> diff --git a/packages/server/modules/fileuploads/graph/resolvers/fileUploads.ts b/packages/server/modules/fileuploads/graph/resolvers/fileUploads.ts index 5e45b72e3..5b81cb4d9 100644 --- a/packages/server/modules/fileuploads/graph/resolvers/fileUploads.ts +++ b/packages/server/modules/fileuploads/graph/resolvers/fileUploads.ts @@ -4,6 +4,8 @@ import { getBranchPendingVersionsFactory, getFileInfoFactory, getFileInfoFactoryV2, + getModelUploadsItemsFactory, + getModelUploadsTotalCountFactory, getStreamFileUploadsFactory, getStreamPendingModelsFactory, saveUploadFileFactory, @@ -232,6 +234,7 @@ const fileUploadMutations: Resolvers['FileUploadMutations'] = { } } } +import { getModelUploadsFactory } from '@/modules/fileuploads/services/management' export = { Stream: { @@ -260,6 +263,20 @@ export = { parent.name, args ) + }, + async uploads(parent, args) { + const projectDb = await getProjectDbClient({ projectId: parent.streamId }) + const getModelUploads = getModelUploadsFactory({ + getModelUploadsItems: getModelUploadsItemsFactory({ db: projectDb }), + getModelUploadsTotalCount: getModelUploadsTotalCountFactory({ db: projectDb }) + }) + + return await getModelUploads({ + modelId: parent.id, + projectId: parent.streamId, + limit: args.input?.limit ?? 25, + cursor: args.input?.cursor + }) } }, FileUpload: { @@ -267,11 +284,19 @@ export = { modelName: (parent) => parent.branchName, convertedVersionId: (parent) => parent.convertedCommitId, async model(parent, _args, ctx) { - const projectDb = await getProjectDbClient({ projectId: parent.streamId }) + const { streamId, modelId, branchName } = parent + + const projectDb = await getProjectDbClient({ projectId: streamId }) + if (modelId) { + return await ctx.loaders + .forRegion({ db: projectDb }) + .branches.getById.load(modelId) + } + return await ctx.loaders .forRegion({ db: projectDb }) - .streams.getStreamBranchByName.forStream(parent.streamId) - .load(parent.branchName.toLowerCase()) + .streams.getStreamBranchByName.forStream(streamId) + .load(branchName.toLowerCase()) } }, Mutation: { diff --git a/packages/server/modules/fileuploads/index.ts b/packages/server/modules/fileuploads/index.ts index f9ba7a46a..3411fc340 100644 --- a/packages/server/modules/fileuploads/index.ts +++ b/packages/server/modules/fileuploads/index.ts @@ -18,7 +18,8 @@ import { listenFor } from '@/modules/core/utils/dbNotificationListener' import { getEventBus } from '@/modules/shared/services/eventBus' import { expireOldPendingUploadsFactory, - getFileInfoFactory + getFileInfoFactory, + updateFileUploadFactory } from '@/modules/fileuploads/repositories/fileUploads' import { db } from '@/db/knex' import { getFileImportTimeLimitMinutes } from '@/modules/shared/helpers/envHelper' @@ -137,6 +138,7 @@ export const init: SpeckleModule['init'] = async ({ app, isInitial }) => { getFileInfo: getFileInfoFactory({ db: projectDb }), publish, getStreamBranchByName: getStreamBranchByNameFactory({ db: projectDb }), + updateFileUpload: updateFileUploadFactory({ db: projectDb }), eventEmit: getEventBus().emit })(parsedMessage) }) diff --git a/packages/server/modules/fileuploads/migrations/20250616114012_drop_metadata_in_file_uploads.ts b/packages/server/modules/fileuploads/migrations/20250616114012_drop_metadata_in_file_uploads.ts new file mode 100644 index 000000000..36baa6208 --- /dev/null +++ b/packages/server/modules/fileuploads/migrations/20250616114012_drop_metadata_in_file_uploads.ts @@ -0,0 +1,16 @@ +import { Knex } from 'knex' + +const TABLE_NAME = 'file_uploads' +const METADATA_FIELD = 'metadata' + +export async function up(knex: Knex): Promise { + await knex.schema.table(TABLE_NAME, (table) => { + table.dropColumn(METADATA_FIELD) + }) +} + +export async function down(knex: Knex): Promise { + await knex.schema.table(TABLE_NAME, (table) => { + table.json(METADATA_FIELD).nullable().defaultTo(null) + }) +} diff --git a/packages/server/modules/fileuploads/repositories/fileUploads.ts b/packages/server/modules/fileuploads/repositories/fileUploads.ts index d2047cad5..a1615158f 100644 --- a/packages/server/modules/fileuploads/repositories/fileUploads.ts +++ b/packages/server/modules/fileuploads/repositories/fileUploads.ts @@ -1,13 +1,16 @@ import { Branches, FileUploads, knex } from '@/modules/core/dbSchema' import { - UpdateFileStatus, GarbageCollectPendingUploadedFiles, GetFileInfo, SaveUploadFile, SaveUploadFileV2, SaveUploadFileInput, SaveUploadFileInputV2, - GetFileInfoV2 + GetFileInfoV2, + UpdateFileUpload, + GetModelUploadsItems, + GetModelUploadsBaseArgs, + GetModelUploadsTotalCount } from '@/modules/fileuploads/domain/operations' import { FileUploadConvertedStatus, @@ -16,11 +19,19 @@ import { } from '@/modules/fileuploads/helpers/types' import { Knex } from 'knex' import { FileImportJobNotFoundError } from '@/modules/fileuploads/helpers/errors' +import { compositeCursorTools } from '@/modules/shared/helpers/graphqlHelper' +import { clamp } from 'lodash' const tables = { fileUploads: (db: Knex) => db(FileUploads.name) } +const getCursorTools = () => + compositeCursorTools({ + schema: FileUploads, + cols: ['convertedLastUpdate', 'id'] + }) + export const getFileInfoFactory = (deps: { db: Knex }): GetFileInfo => async (params) => { @@ -100,7 +111,8 @@ export const saveUploadFileFactory = userId, fileName, fileType, - fileSize + fileSize, + modelId }: SaveUploadFileInput) => { const dbFile: Partial = { id: fileId, @@ -110,7 +122,8 @@ export const saveUploadFileFactory = fileName, fileType, fileSize, - uploadComplete: true + uploadComplete: true, + modelId } const [newRecord] = await tables.fileUploads(deps.db).insert(dbFile, '*') return newRecord as FileUploadRecord @@ -232,23 +245,61 @@ export const getBranchPendingVersionsFactory = return await q } -export const updateFileStatusFactory = - (deps: { db: Knex }): UpdateFileStatus => +export const updateFileUploadFactory = + (deps: { db: Knex }): UpdateFileUpload => async (params) => { - const { fileId, status, convertedMessage, convertedCommitId } = params - const fileInfos = await tables + const { id, upload } = params + const updatedFile = await tables .fileUploads(deps.db) - .update({ - [FileUploads.withoutTablePrefix.col.convertedStatus]: status, - [FileUploads.withoutTablePrefix.col.convertedLastUpdate]: knex.fn.now(), - [FileUploads.withoutTablePrefix.col.convertedMessage]: convertedMessage, - [FileUploads.withoutTablePrefix.col.convertedCommitId]: convertedCommitId - }) - .where({ [FileUploads.withoutTablePrefix.col.id]: fileId }) + .update(upload) + .where({ [FileUploads.col.id]: id }) .returning('*') - if (fileInfos.length === 0) { - throw new FileImportJobNotFoundError(`File with id ${fileId} not found`) + if (updatedFile.length === 0) { + throw new FileImportJobNotFoundError(`File with id ${id} not found`) } - return fileInfos[0] + return updatedFile[0] + } + +const getModelUploadsBaseQueryFactory = + (deps: { db: Knex }) => (params: GetModelUploadsBaseArgs) => { + const { projectId, modelId } = params + const q = tables + .fileUploads(deps.db) + .where(FileUploads.col.streamId, projectId) + .andWhere(FileUploads.col.modelId, modelId) + + return q + } + +export const getModelUploadsItemsFactory = + (deps: { db: Knex }): GetModelUploadsItems => + async (params) => { + const limit = clamp(params.limit || 0, 0, 100) + const { filterByCursor, resolveNewCursor } = getCursorTools() + + const q = getModelUploadsBaseQueryFactory(deps)(params) + .orderBy(FileUploads.col.convertedLastUpdate, 'desc') + .limit(limit) + + filterByCursor({ + query: q, + cursor: params.cursor + }) + + const rows = await q + const newCursor = resolveNewCursor(rows) + + return { + items: rows, + cursor: newCursor + } + } + +export const getModelUploadsTotalCountFactory = + (deps: { db: Knex }): GetModelUploadsTotalCount => + async (params) => { + const q = getModelUploadsBaseQueryFactory(deps)(params) + const [{ count }] = await q.count() + return parseInt(count + '') } diff --git a/packages/server/modules/fileuploads/rest/nextGenRouter.ts b/packages/server/modules/fileuploads/rest/nextGenRouter.ts index b75d16781..5429bf57f 100644 --- a/packages/server/modules/fileuploads/rest/nextGenRouter.ts +++ b/packages/server/modules/fileuploads/rest/nextGenRouter.ts @@ -9,7 +9,7 @@ import { fileImportResultPayload } from '@speckle/shared/workers/fileimport' import { onFileImportResultFactory } from '@/modules/fileuploads/services/resultHandler' import { saveUploadFileFactoryV2, - updateFileStatusFactory + updateFileUploadFactory } from '@/modules/fileuploads/repositories/fileUploads' import { validateRequest } from 'zod-express' import { z } from 'zod' @@ -170,7 +170,7 @@ export const nextGenFileImporterRouterFactory = (): Router => { const onFileImportResult = onFileImportResultFactory({ logger: logger.child({ fileUploadStatus: jobResult.status }), - updateFileStatus: updateFileStatusFactory({ db: projectDb }), + updateFileUpload: updateFileUploadFactory({ db: projectDb }), publish }) diff --git a/packages/server/modules/fileuploads/rest/router.ts b/packages/server/modules/fileuploads/rest/router.ts index 67f23d7a1..e958afeb6 100644 --- a/packages/server/modules/fileuploads/rest/router.ts +++ b/packages/server/modules/fileuploads/rest/router.ts @@ -43,8 +43,11 @@ export const fileuploadRouterFactory = (): Router => { }) const projectDb = await getProjectDbClient({ projectId }) + const getStreamBranchByName = getStreamBranchByNameFactory({ db: projectDb }) + const branch = await getStreamBranchByName(projectId, branchName) + const insertNewUploadAndNotify = insertNewUploadAndNotifyFactory({ - getStreamBranchByName: getStreamBranchByNameFactory({ db: projectDb }), + getStreamBranchByName, saveUploadFile: saveUploadFileFactory({ db: projectDb }), publish, emit: getEventBus().emit @@ -63,11 +66,12 @@ export const fileuploadRouterFactory = (): Router => { await insertNewUploadAndNotify({ fileId: upload.blobId, streamId: projectId, - branchName, + branchName: branch?.name || branchName, userId, fileName: upload.fileName, fileType: upload.fileName?.split('.').pop() || '', //FIXME - fileSize: upload.fileSize + fileSize: upload.fileSize, + modelId: branch?.id || null }) }) ) diff --git a/packages/server/modules/fileuploads/services/management.ts b/packages/server/modules/fileuploads/services/management.ts index d008fbb6f..afb7deacb 100644 --- a/packages/server/modules/fileuploads/services/management.ts +++ b/packages/server/modules/fileuploads/services/management.ts @@ -9,6 +9,9 @@ import { NotifyChangeInFileStatus, SaveUploadFileV2, PushJobToFileImporter, + GetModelUploads, + GetModelUploadsItems, + GetModelUploadsTotalCount, InsertNewUploadAndNotifyV2, InsertNewUploadAndNotify } from '@/modules/fileuploads/domain/operations' @@ -159,3 +162,23 @@ export const notifyChangeInFileStatus = projectId: streamId }) } + +export const getModelUploadsFactory = + (deps: { + getModelUploadsItems: GetModelUploadsItems + getModelUploadsTotalCount: GetModelUploadsTotalCount + }): GetModelUploads => + async (params) => { + const [{ items, cursor }, totalCount] = await Promise.all([ + params.limit === 0 + ? { items: [], cursor: null } + : deps.getModelUploadsItems(params), + deps.getModelUploadsTotalCount(params) + ]) + + return { + items, + totalCount, + cursor + } + } diff --git a/packages/server/modules/fileuploads/services/resultHandler.ts b/packages/server/modules/fileuploads/services/resultHandler.ts index fee80bb12..a58899e97 100644 --- a/packages/server/modules/fileuploads/services/resultHandler.ts +++ b/packages/server/modules/fileuploads/services/resultHandler.ts @@ -1,7 +1,7 @@ import { Logger } from '@/observability/logging' import { ProcessFileImportResult, - UpdateFileStatus + UpdateFileUpload } from '@/modules/fileuploads/domain/operations' import { FileImportSubscriptions, @@ -16,9 +16,10 @@ import { jobResultToConvertedMessage } from '@/modules/fileuploads/helpers/convert' import { ensureError } from '@speckle/shared' +import { FileUploadRecord } from '@/modules/fileuploads/helpers/types' type OnFileImportResultDeps = { - updateFileStatus: UpdateFileStatus + updateFileUpload: UpdateFileUpload publish: PublishSubscription logger: Logger } @@ -42,13 +43,16 @@ export const onFileImportResultFactory = convertedCommitId = jobResult.result.versionId } - let updatedFile + let updatedFile: FileUploadRecord try { - updatedFile = await deps.updateFileStatus({ - fileId: jobId, - status, - convertedMessage, - convertedCommitId + updatedFile = await deps.updateFileUpload({ + id: jobId, + upload: { + convertedStatus: status, + convertedLastUpdate: new Date(), + convertedMessage, + convertedCommitId + } }) } catch (e) { const err = ensureError(e) diff --git a/packages/server/modules/fileuploads/services/resultListener.ts b/packages/server/modules/fileuploads/services/resultListener.ts index 02d453af5..02b539118 100644 --- a/packages/server/modules/fileuploads/services/resultListener.ts +++ b/packages/server/modules/fileuploads/services/resultListener.ts @@ -8,7 +8,7 @@ import { ProjectPendingModelsUpdatedMessageType, ProjectPendingVersionsUpdatedMessageType } from '@/modules/core/graph/generated/graphql' -import { GetFileInfo } from '@/modules/fileuploads/domain/operations' +import { GetFileInfo, UpdateFileUpload } from '@/modules/fileuploads/domain/operations' import { GetStreamBranchByName } from '@/modules/core/domain/branches/operations' import { EventBusEmit } from '@/modules/shared/services/eventBus' import { ModelEvents } from '@/modules/core/domain/branches/events' @@ -19,6 +19,7 @@ import { FileUploadInternalError } from '@/modules/fileuploads/helpers/errors' type OnFileImportProcessedDeps = { getFileInfo: GetFileInfo getStreamBranchByName: GetStreamBranchByName + updateFileUpload: UpdateFileUpload publish: PublishSubscription eventEmit: EventBusEmit } @@ -45,11 +46,21 @@ export const onFileImportProcessedFactory = const [upload, branch] = await Promise.all([ deps.getFileInfo({ fileId: uploadId }), - isNewBranch ? deps.getStreamBranchByName(streamId, branchName) : null + deps.getStreamBranchByName(streamId, branchName) ]) if (!upload) return if (upload.streamId !== streamId) return + // Update upload to reference the actual model/branch created + if (branch) { + await deps.updateFileUpload({ + id: upload.id, + upload: { + modelId: branch.id + } + }) + } + if (upload.convertedStatus === FileUploadConvertedStatus.Error) { //TODO in future differentiate between internal server errors and user errors const err = new FileUploadInternalError( diff --git a/packages/server/modules/fileuploads/tests/helpers/creation.ts b/packages/server/modules/fileuploads/tests/helpers/creation.ts index bc004a704..a1df15345 100644 --- a/packages/server/modules/fileuploads/tests/helpers/creation.ts +++ b/packages/server/modules/fileuploads/tests/helpers/creation.ts @@ -16,7 +16,8 @@ export const createFileUploadJob = (params: { projectId: string; userId: string userId, fileName: cryptoRandomString({ length: 10 }), fileType: cryptoRandomString({ length: 3 }), - fileSize: randomInt(1, 1e6) + fileSize: randomInt(1, 1e6), + modelId: null } return saveUploadFile(data) diff --git a/packages/server/modules/fileuploads/tests/unit/fileuploads.spec.ts b/packages/server/modules/fileuploads/tests/unit/fileuploads.spec.ts index ce346cb89..9f234b1b6 100644 --- a/packages/server/modules/fileuploads/tests/unit/fileuploads.spec.ts +++ b/packages/server/modules/fileuploads/tests/unit/fileuploads.spec.ts @@ -69,7 +69,8 @@ describe('FileUploads @fileuploads', () => { fileId, fileName: 'testfile.txt', fileSize: 100, - fileType: 'text/plain' + fileType: 'text/plain', + modelId: null }) await sleep(2000) await garbageCollector({ logger, timeoutThresholdSeconds: 1 }) @@ -98,7 +99,8 @@ describe('FileUploads @fileuploads', () => { fileId, fileName: 'testfile.txt', fileSize: 100, - fileType: 'text/plain' + fileType: 'text/plain', + modelId: null }) // timeout far in the future, so it won't be garbage collected await garbageCollector({ logger, timeoutThresholdSeconds: 1 * TIME.hour }) @@ -133,7 +135,8 @@ describe('FileUploads @fileuploads', () => { fileId, fileName: 'testfile.txt', fileSize: 100, - fileType: 'text/plain' + fileType: 'text/plain', + modelId: null }) const results = await getFileInfoFactory({ db })({ diff --git a/packages/server/modules/shared/helpers/graphqlHelper.ts b/packages/server/modules/shared/helpers/graphqlHelper.ts index a2284489b..c58bbac78 100644 --- a/packages/server/modules/shared/helpers/graphqlHelper.ts +++ b/packages/server/modules/shared/helpers/graphqlHelper.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import { AuthContext } from '@/modules/shared/authz' import { base64Decode, base64Encode } from '@/modules/shared/helpers/cryptoHelper' import DataLoader from 'dataloader' @@ -13,6 +14,8 @@ import { } from '@/modules/shared/errors' import { MaybeNullOrUndefined, Nullable, Optional } from '@speckle/shared' import { Knex } from 'knex' +import { SchemaConfig } from '@/modules/core/dbSchema' +import { has, isObjectLike, isString, mapValues, pick, times } from 'lodash' /** * Encode cursor to turn it into an opaque & obfuscated value @@ -73,12 +76,101 @@ export const decodeCompositeCursor = ( return null } +/** + * Simplifies working with composite cursors in SQL queries. Composite cursors are better because they + * allow duplicate values (e.g. updatedAt date) in different rows + */ +export const compositeCursorTools = < + Config extends SchemaConfig, + SelectedCols extends Array +>(args: { + schema: Config + /** + * Order of columns matters - put the primary ordering column first (e.g. updatedAt), then the secondary + * ones like the ID. + */ + cols: SelectedCols +}) => { + type Cursor = { + [Col in SelectedCols[number]]: string + } + + type CursorRecord = { + [Col in SelectedCols[number]]: string | Date | number | boolean + } + + const encode = (val: Cursor) => encodeCompositeCursor(val) + const decode = (cursor: MaybeNullOrUndefined): Nullable => + decodeCompositeCursor( + cursor, + (c) => isObjectLike(c) && args.cols.every((col) => has(c, col)) + ) + + /** + * Invoke this on the knex querybuilder to filter the query by the cursor + */ + const filterByCursor = (params: { + query: Query + /** + * If falsy, filter will be skipped + */ + cursor: MaybeNullOrUndefined + /** + * How the results are sorted. Descending by default. + */ + sort?: 'desc' | 'asc' + }) => { + const { query, sort = 'desc' } = params + const cursor = isString(params.cursor) ? decode(params.cursor) : params.cursor + if (!cursor) return query + + const colCount = args.cols.length + + const sql = `(${times(colCount, () => '??').join(', ')}) ${ + sort === 'desc' ? '<' : '>' + } (${times(colCount, () => '?').join(', ')})` // string like (??, ??) < (?, ?) + + // e.g. WHERE (table.updatedAt, table.id) < ('2023-10-01T00:00:00.000Z', '12345') + query.andWhereRaw(sql, [ + ...args.cols.map((col) => args.schema.col[col]), + ...args.cols.map((col) => cursor[col].toString()) + ]) + + return query + } + + /** + * Feed in an entire page of items and this will build the next cursor accordingly + */ + const resolveNewCursor = (items: Array) => { + if (!items.length) return null + const lastItem = items.at(-1) + if (!lastItem) return null + + const cursor: Cursor = mapValues(pick(lastItem, args.cols), (value) => { + if (value instanceof Date) { + return value.toISOString() + } + + return `${value}` + }) + + return encode(cursor) + } + + return { + encode, + decode, + filterByCursor, + resolveNewCursor + } +} + /** * All dataloaders must at the very least follow this type */ export type ModularizedDataLoadersConstraint = { [group: string]: Optional<{ - // eslint-disable-next-line @typescript-eslint/no-explicit-any [loader: string]: DataLoader | { clearAll: () => unknown } }> } diff --git a/packages/server/test/graphql/generated/graphql.ts b/packages/server/test/graphql/generated/graphql.ts index 838644580..35c78d9a9 100644 --- a/packages/server/test/graphql/generated/graphql.ts +++ b/packages/server/test/graphql/generated/graphql.ts @@ -1033,6 +1033,13 @@ export type FileUpload = { userId: Scalars['String']['output']; }; +export type FileUploadCollection = { + __typename?: 'FileUploadCollection'; + cursor?: Maybe; + items: Array; + totalCount: Scalars['Int']['output']; +}; + export type FileUploadMutations = { __typename?: 'FileUploadMutations'; /** @@ -1105,6 +1112,13 @@ export type GenerateFileUploadUrlOutput = { url: Scalars['String']['output']; }; +export type GetModelUploadsInput = { + /** The cursor for pagination. */ + cursor?: InputMaybe; + /** The maximum number of uploads to return. */ + limit?: InputMaybe; +}; + export type InvitableCollaboratorsFilter = { search?: InputMaybe; }; @@ -1323,6 +1337,8 @@ export type Model = { permissions: ModelPermissionChecks; previewUrl?: Maybe; updatedAt: Scalars['DateTime']['output']; + /** Get all file uploads ever done in this model */ + uploads: FileUploadCollection; version: Version; versions: VersionCollection; }; @@ -1339,6 +1355,11 @@ export type ModelPendingImportedVersionsArgs = { }; +export type ModelUploadsArgs = { + input?: InputMaybe; +}; + + export type ModelVersionArgs = { id: Scalars['String']['input']; }; diff --git a/packages/shared/src/blobs/index.ts b/packages/shared/src/blobs/index.ts index 776185af1..7f35bb586 100644 --- a/packages/shared/src/blobs/index.ts +++ b/packages/shared/src/blobs/index.ts @@ -38,3 +38,22 @@ export const BlobUploadStatus = { } export type BlobUploadStatus = (typeof BlobUploadStatus)[keyof typeof BlobUploadStatus] +export const FileUploadConvertedStatus = { + Queued: 0, + Converting: 1, + Completed: 2, + Error: 3 +} + +export type FileUploadConvertedStatus = + (typeof FileUploadConvertedStatus)[keyof typeof FileUploadConvertedStatus] + +export const fileUploadConvertedStatusLabels: Record< + FileUploadConvertedStatus, + string +> = { + [FileUploadConvertedStatus.Queued]: 'Queued', + [FileUploadConvertedStatus.Converting]: 'Converting', + [FileUploadConvertedStatus.Completed]: 'Completed', + [FileUploadConvertedStatus.Error]: 'Error' +} diff --git a/packages/ui-components/src/components/common/Badge.stories.ts b/packages/ui-components/src/components/common/Badge.stories.ts index 6e4943b85..ea88830d8 100644 --- a/packages/ui-components/src/components/common/Badge.stories.ts +++ b/packages/ui-components/src/components/common/Badge.stories.ts @@ -20,6 +20,10 @@ export default { clickIcon: { action: 'click', type: 'function' + }, + color: { + options: ['primary', 'secondary'], + control: { type: 'select' } } } } as Meta diff --git a/packages/ui-components/src/components/layout/Table.stories.ts b/packages/ui-components/src/components/layout/Table.stories.ts index 5d101c148..086b50ce1 100644 --- a/packages/ui-components/src/components/layout/Table.stories.ts +++ b/packages/ui-components/src/components/layout/Table.stories.ts @@ -28,11 +28,7 @@ export const Default: StoryObj = { }, template: `