feat: opening a model w/ a home view targets latest version (#5376)

* model link resolution updated

* finalization

* lint fix
This commit is contained in:
Kristaps Fabians Geikins
2025-09-04 10:02:02 +03:00
committed by GitHub
parent 51065ab635
commit 3497eed931
12 changed files with 224 additions and 87 deletions
@@ -360,7 +360,7 @@ type Documents = {
"\n subscription OnProjectPendingVersionsUpdated($id: String!) {\n projectPendingVersionsUpdated(id: $id) {\n id\n type\n version {\n ...PendingFileUpload\n ...UseFailedFileImportJobUtils_FileUpload\n model {\n ...ProjectPageLatestItemsModelItem\n }\n }\n }\n }\n": typeof types.OnProjectPendingVersionsUpdatedDocument,
"\n subscription OnProjectTriggeredAutomationsStatusUpdated($id: String!) {\n projectTriggeredAutomationsStatusUpdated(projectId: $id) {\n type\n version {\n id\n automationsStatus {\n automationRuns {\n ...AutomateViewerPanel_AutomateRun\n }\n ...TriggeredAutomationsStatusSummary\n ...AutomateRunsTriggerStatusDialog_TriggeredAutomationsStatus\n }\n }\n model {\n id\n }\n run {\n id\n automationId\n ...AutomationRunDetails\n }\n }\n }\n": typeof types.OnProjectTriggeredAutomationsStatusUpdatedDocument,
"\n subscription OnProjectAutomationsUpdated($id: String!) {\n projectAutomationsUpdated(projectId: $id) {\n type\n automationId\n automation {\n id\n ...ProjectPageAutomationPage_Automation\n ...ProjectPageAutomationsRow_Automation\n }\n }\n }\n": typeof types.OnProjectAutomationsUpdatedDocument,
"\n fragment GetModelItemRoute_Model on Model {\n id\n projectId\n homeView {\n id\n resourceIds\n }\n }\n": typeof types.GetModelItemRoute_ModelFragmentDoc,
"\n fragment GetModelItemRoute_Model on Model {\n id\n projectId\n homeView {\n id\n resourceIds\n }\n resourceIdString\n }\n": typeof types.GetModelItemRoute_ModelFragmentDoc,
"\n mutation ServerInfoUpdate($info: ServerInfoUpdateInput!) {\n serverInfoUpdate(info: $info)\n }\n": typeof types.ServerInfoUpdateDocument,
"\n mutation AdminPanelDeleteUser($userConfirmation: UserDeleteInput!) {\n adminDeleteUser(userConfirmation: $userConfirmation)\n }\n": typeof types.AdminPanelDeleteUserDocument,
"\n mutation AdminPanelDeleteProject($ids: [String!]!) {\n projectMutations {\n batchDelete(ids: $ids)\n }\n }\n": typeof types.AdminPanelDeleteProjectDocument,
@@ -880,7 +880,7 @@ const documents: Documents = {
"\n subscription OnProjectPendingVersionsUpdated($id: String!) {\n projectPendingVersionsUpdated(id: $id) {\n id\n type\n version {\n ...PendingFileUpload\n ...UseFailedFileImportJobUtils_FileUpload\n model {\n ...ProjectPageLatestItemsModelItem\n }\n }\n }\n }\n": types.OnProjectPendingVersionsUpdatedDocument,
"\n subscription OnProjectTriggeredAutomationsStatusUpdated($id: String!) {\n projectTriggeredAutomationsStatusUpdated(projectId: $id) {\n type\n version {\n id\n automationsStatus {\n automationRuns {\n ...AutomateViewerPanel_AutomateRun\n }\n ...TriggeredAutomationsStatusSummary\n ...AutomateRunsTriggerStatusDialog_TriggeredAutomationsStatus\n }\n }\n model {\n id\n }\n run {\n id\n automationId\n ...AutomationRunDetails\n }\n }\n }\n": types.OnProjectTriggeredAutomationsStatusUpdatedDocument,
"\n subscription OnProjectAutomationsUpdated($id: String!) {\n projectAutomationsUpdated(projectId: $id) {\n type\n automationId\n automation {\n id\n ...ProjectPageAutomationPage_Automation\n ...ProjectPageAutomationsRow_Automation\n }\n }\n }\n": types.OnProjectAutomationsUpdatedDocument,
"\n fragment GetModelItemRoute_Model on Model {\n id\n projectId\n homeView {\n id\n resourceIds\n }\n }\n": types.GetModelItemRoute_ModelFragmentDoc,
"\n fragment GetModelItemRoute_Model on Model {\n id\n projectId\n homeView {\n id\n resourceIds\n }\n resourceIdString\n }\n": types.GetModelItemRoute_ModelFragmentDoc,
"\n mutation ServerInfoUpdate($info: ServerInfoUpdateInput!) {\n serverInfoUpdate(info: $info)\n }\n": types.ServerInfoUpdateDocument,
"\n mutation AdminPanelDeleteUser($userConfirmation: UserDeleteInput!) {\n adminDeleteUser(userConfirmation: $userConfirmation)\n }\n": types.AdminPanelDeleteUserDocument,
"\n mutation AdminPanelDeleteProject($ids: [String!]!) {\n projectMutations {\n batchDelete(ids: $ids)\n }\n }\n": types.AdminPanelDeleteProjectDocument,
@@ -2455,7 +2455,7 @@ export function graphql(source: "\n subscription OnProjectAutomationsUpdated($i
/**
* 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 GetModelItemRoute_Model on Model {\n id\n projectId\n homeView {\n id\n resourceIds\n }\n }\n"): (typeof documents)["\n fragment GetModelItemRoute_Model on Model {\n id\n projectId\n homeView {\n id\n resourceIds\n }\n }\n"];
export function graphql(source: "\n fragment GetModelItemRoute_Model on Model {\n id\n projectId\n homeView {\n id\n resourceIds\n }\n resourceIdString\n }\n"): (typeof documents)["\n fragment GetModelItemRoute_Model on Model {\n id\n projectId\n homeView {\n id\n resourceIds\n }\n resourceIdString\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
File diff suppressed because one or more lines are too long
@@ -1,4 +1,3 @@
import { resourceBuilder } from '@speckle/shared/viewer/route'
import { has } from 'lodash-es'
import { graphql } from '~/lib/common/generated/gql'
import { modelRoute } from '~/lib/common/helpers/route'
@@ -35,20 +34,23 @@ graphql(`
id
resourceIds
}
resourceIdString
}
`)
export const getModelItemRoute = (
i: GetModelItemRoute_ModelFragment | PendingFileUploadFragment
i:
| GetModelItemRoute_ModelFragment
| PendingFileUploadFragment
| { projectId: string; id: string }
) => {
if (isPendingModelFragment(i)) {
return modelRoute(i.projectId, i.id)
}
return modelRoute(
i.projectId,
i.homeView?.id
? resourceBuilder().addResources(i.homeView.resourceIds).toString()
: i.id
)
if (!('resourceIdString' in i)) {
return modelRoute(i.projectId, i.id)
}
return modelRoute(i.projectId, i.resourceIdString)
}
@@ -255,4 +255,8 @@ extend type Model {
The model's home view, if any
"""
homeView: SavedView
"""
The resourceIdString to use when building links to this model in the viewer. Takes home view settings into account.
"""
resourceIdString: String!
}
@@ -1711,6 +1711,8 @@ export type Model = {
permissions: ModelPermissionChecks;
previewUrl?: Maybe<Scalars['String']['output']>;
projectId: Scalars['String']['output'];
/** The resourceIdString to use when building links to this model in the viewer. Takes home view settings into account. */
resourceIdString: Scalars['String']['output'];
updatedAt: Scalars['DateTime']['output'];
/** Get all file uploads ever done in this model */
uploads: FileUploadCollection;
@@ -7566,6 +7568,7 @@ export type ModelResolvers<ContextType = GraphQLContext, ParentType extends Reso
permissions?: Resolver<ResolversTypes['ModelPermissionChecks'], ParentType, ContextType>;
previewUrl?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
projectId?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
resourceIdString?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
updatedAt?: Resolver<ResolversTypes['DateTime'], ParentType, ContextType>;
uploads?: Resolver<ResolversTypes['FileUploadCollection'], ParentType, ContextType, Partial<ModelUploadsArgs>>;
version?: Resolver<ResolversTypes['Version'], ParentType, ContextType, RequireFields<ModelVersionArgs, 'id'>>;
@@ -9537,6 +9540,14 @@ export type UpdateSavedViewGroupMutationVariables = Exact<{
export type UpdateSavedViewGroupMutation = { __typename?: 'Mutation', projectMutations: { __typename?: 'ProjectMutations', savedViewMutations: { __typename?: 'SavedViewMutations', updateGroup: { __typename?: 'SavedViewGroup', id: string, projectId: string, resourceIds: Array<string>, title: string, isUngroupedViewsGroup: boolean, views: { __typename?: 'SavedViewCollection', totalCount: number, cursor?: string | null, items: Array<{ __typename?: 'SavedView', id: string, name: string, description?: string | null, groupId?: string | null, createdAt: Date, updatedAt: Date, resourceIdString: string, resourceIds: Array<string>, isHomeView: boolean, visibility: SavedViewVisibility, viewerState: Record<string, unknown>, screenshot: string, position: number, projectId: string, author?: { __typename?: 'LimitedUser', id: string } | null, group: { __typename?: 'SavedViewGroup', id: string, title: string, isUngroupedViewsGroup: boolean } }> } } } } };
export type GetModelHomeViewQueryVariables = Exact<{
projectId: Scalars['String']['input'];
modelId: Scalars['String']['input'];
}>;
export type GetModelHomeViewQuery = { __typename?: 'Query', project: { __typename?: 'Project', id: string, model: { __typename?: 'Model', id: string, resourceIdString: string, homeView?: { __typename?: 'SavedView', id: string, name: string, description?: string | null, groupId?: string | null, createdAt: Date, updatedAt: Date, resourceIdString: string, resourceIds: Array<string>, isHomeView: boolean, visibility: SavedViewVisibility, viewerState: Record<string, unknown>, screenshot: string, position: number, projectId: string, author?: { __typename?: 'LimitedUser', id: string } | null, group: { __typename?: 'SavedViewGroup', id: string, title: string, isUngroupedViewsGroup: boolean } } | null } } };
export type BasicWorkspaceFragment = { __typename?: 'Workspace', id: string, name: string, slug: string, updatedAt: Date, createdAt: Date, role?: string | null, readOnly: boolean };
export type BasicPendingWorkspaceCollaboratorFragment = { __typename?: 'PendingWorkspaceCollaborator', id: string, inviteId: string, title: string, role: string, token?: string | null, workspace: { __typename?: 'LimitedWorkspace', id: string, name: string }, invitedBy: { __typename?: 'LimitedUser', id: string, name: string }, user?: { __typename?: 'LimitedUser', id: string, name: string } | null };
@@ -10679,6 +10690,7 @@ export const UpdateSavedViewDocument = {"kind":"Document","definitions":[{"kind"
export const DeleteSavedViewGroupDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteSavedViewGroup"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"DeleteSavedViewGroupInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"savedViewMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteGroup"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]}}]}}]} as unknown as DocumentNode<DeleteSavedViewGroupMutation, DeleteSavedViewGroupMutationVariables>;
export const CanUpdateSavedViewGroupDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"CanUpdateSavedViewGroup"},"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":"groupId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"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":"savedViewGroup"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"groupId"}}}],"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":"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<CanUpdateSavedViewGroupQuery, CanUpdateSavedViewGroupQueryVariables>;
export const UpdateSavedViewGroupDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateSavedViewGroup"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateSavedViewGroupInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"viewsInput"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SavedViewGroupViewsInput"}}},"defaultValue":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"10"}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"savedViewMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateGroup"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BasicSavedViewGroup"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BasicSavedView"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"SavedView"}},"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":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}},{"kind":"Field","name":{"kind":"Name","value":"groupId"}},{"kind":"Field","name":{"kind":"Name","value":"group"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"isUngroupedViewsGroup"}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"resourceIdString"}},{"kind":"Field","name":{"kind":"Name","value":"resourceIds"}},{"kind":"Field","name":{"kind":"Name","value":"isHomeView"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"Field","name":{"kind":"Name","value":"viewerState"}},{"kind":"Field","name":{"kind":"Name","value":"screenshot"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"projectId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BasicSavedViewGroup"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"SavedViewGroup"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"projectId"}},{"kind":"Field","name":{"kind":"Name","value":"resourceIds"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"isUngroupedViewsGroup"}},{"kind":"Field","name":{"kind":"Name","value":"views"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"viewsInput"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BasicSavedView"}}]}}]}}]}}]} as unknown as DocumentNode<UpdateSavedViewGroupMutation, UpdateSavedViewGroupMutationVariables>;
export const GetModelHomeViewDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetModelHomeView"},"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"}}}}],"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":"homeView"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BasicSavedView"}}]}},{"kind":"Field","name":{"kind":"Name","value":"resourceIdString"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BasicSavedView"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"SavedView"}},"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":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}},{"kind":"Field","name":{"kind":"Name","value":"groupId"}},{"kind":"Field","name":{"kind":"Name","value":"group"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"isUngroupedViewsGroup"}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"resourceIdString"}},{"kind":"Field","name":{"kind":"Name","value":"resourceIds"}},{"kind":"Field","name":{"kind":"Name","value":"isHomeView"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"Field","name":{"kind":"Name","value":"viewerState"}},{"kind":"Field","name":{"kind":"Name","value":"screenshot"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"projectId"}}]}}]} as unknown as DocumentNode<GetModelHomeViewQuery, GetModelHomeViewQueryVariables>;
export const CreateWorkspaceInviteDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateWorkspaceInvite"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}},"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":"WorkspaceInviteCreateInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspaceMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"invites"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"create"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"workspaceId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}}},{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BasicWorkspace"}},{"kind":"Field","name":{"kind":"Name","value":"invitedTeam"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BasicPendingWorkspaceCollaborator"}}]}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BasicWorkspace"},"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":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"readOnly"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BasicPendingWorkspaceCollaborator"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"PendingWorkspaceCollaborator"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"inviteId"}},{"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":"title"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"invitedBy"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"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":"token"}}]}}]} as unknown as DocumentNode<CreateWorkspaceInviteMutation, CreateWorkspaceInviteMutationVariables>;
export const BatchCreateWorkspaceInvitesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"BatchCreateWorkspaceInvites"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}},"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":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"WorkspaceInviteCreateInput"}}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspaceMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"invites"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"batchCreate"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"workspaceId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}}},{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BasicWorkspace"}},{"kind":"Field","name":{"kind":"Name","value":"invitedTeam"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BasicPendingWorkspaceCollaborator"}}]}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BasicWorkspace"},"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":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"readOnly"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BasicPendingWorkspaceCollaborator"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"PendingWorkspaceCollaborator"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"inviteId"}},{"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":"title"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"invitedBy"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"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":"token"}}]}}]} as unknown as DocumentNode<BatchCreateWorkspaceInvitesMutation, BatchCreateWorkspaceInvitesMutationVariables>;
export const GetWorkspaceWithTeamDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetWorkspaceWithTeam"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspace"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BasicWorkspace"}},{"kind":"Field","name":{"kind":"Name","value":"invitedTeam"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BasicPendingWorkspaceCollaborator"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BasicWorkspace"},"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":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"readOnly"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BasicPendingWorkspaceCollaborator"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"PendingWorkspaceCollaborator"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"inviteId"}},{"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":"title"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"invitedBy"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"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":"token"}}]}}]} as unknown as DocumentNode<GetWorkspaceWithTeamQuery, GetWorkspaceWithTeamQueryVariables>;
@@ -186,6 +186,22 @@ const resolvers: Resolvers = {
modelId: parent.id,
projectId
})
},
resourceIdString: async (parent, _args, ctx) => {
const projectId = parent.streamId
const projectDb = await getProjectDbClient({ projectId })
const homeView = await ctx.loaders
.forRegion({ db: projectDb })
.savedViews.getModelHomeSavedView.load({
modelId: parent.id,
projectId
})
if (!homeView) return parent.id
return resourceBuilder()
.addResources(homeView.resourceIds)
.clearVersions() // just use latest version
.toString()
}
},
SavedView: {
@@ -522,7 +538,8 @@ const disabledResolvers: Resolvers = {
}
},
Model: {
homeView: () => null // intentional - so we dont have to FF guard the query
homeView: () => null, // intentional - so we dont have to FF guard the query
resourceIdString: (parent) => parent.id
},
ProjectMutations: {
savedViewMutations: () => {
@@ -422,11 +422,11 @@ const adjustResourceIdStringWithHomeSavedViewSettingsFactory =
if (!modelIds.length) return emptyReturn
const modelId = modelIds[0]
const savedView = await deps.getModelHomeSavedView({
const homeView = await deps.getModelHomeSavedView({
modelId: modelId.modelId,
projectId
})
if (!savedView) {
if (!homeView) {
// no home view found
return emptyReturn
}
@@ -436,7 +436,7 @@ const adjustResourceIdStringWithHomeSavedViewSettingsFactory =
// BUT: if its the same one the home view has, at least return the view too, cause the FE will change the
// resourceIdString to be more like the view's which will set a specific versionId that would otherwise be ignored
const viewResource = resourceBuilder()
.addResources(savedView.resourceIds)
.addResources(homeView.resourceIds)
.toResources()
.filter(isModelResource)
.at(0)
@@ -446,20 +446,25 @@ const adjustResourceIdStringWithHomeSavedViewSettingsFactory =
savedView:
viewResource?.modelId === modelId.modelId &&
viewResource?.versionId === modelId.versionId
? savedView
? homeView
: undefined
}
}
return adjustResourceIdStringWithSpecificSavedViewSettingsFactory(deps)({
projectId,
resourceIdString,
savedViewId: savedView,
savedViewSettings: {
// home view means - load that specific version too, otherwise theres no point
loadOriginal: true
}
})
// In case we want to move back to loading the view's specific version:
// return adjustResourceIdStringWithSpecificSavedViewSettingsFactory(deps)({
// projectId,
// resourceIdString,
// savedViewId: homeView,
// savedViewSettings: {
// // for now, home views just load latest
// loadOriginal: false
// }
// })
return {
...emptyReturn,
savedView: homeView
}
}
/**
@@ -263,3 +263,20 @@ export const createSavedViewFactory =
(deps: { apollo: TestApolloServer }) =>
(input: CreateSavedViewMutationVariables, options?: ExecuteOperationOptions) =>
deps.apollo.execute(CreateSavedViewDocument, input, options)
export const getModelHomeViewQuery = gql`
query GetModelHomeView($projectId: String!, $modelId: String!) {
project(id: $projectId) {
id
model(id: $modelId) {
id
homeView {
...BasicSavedView
}
resourceIdString
}
}
}
${basicSavedViewFragment}
`
@@ -8,6 +8,7 @@ import type {
CreateSavedViewMutationVariables,
DeleteSavedViewGroupMutationVariables,
DeleteSavedViewMutationVariables,
GetModelHomeViewQueryVariables,
GetProjectSavedViewGroupQueryVariables,
GetProjectSavedViewGroupsQueryVariables,
GetProjectSavedViewIfExistsQueryVariables,
@@ -24,6 +25,7 @@ import {
CreateSavedViewGroupDocument,
DeleteSavedViewDocument,
DeleteSavedViewGroupDocument,
GetModelHomeViewDocument,
GetProjectSavedViewDocument,
GetProjectSavedViewGroupDocument,
GetProjectSavedViewGroupsDocument,
@@ -215,6 +217,11 @@ const fakeViewerState = (overrides?: PartialDeep<ViewerState.SerializedViewerSta
options?: ExecuteOperationOptions
) => apollo.execute(UpdateSavedViewGroupDocument, input, options)
const getModelHomeView = (
input: GetModelHomeViewQueryVariables,
options?: ExecuteOperationOptions
) => apollo.execute(GetModelHomeViewDocument, input, options)
const getDefaultGroup = async (params: {
projectId: string
resourceIdString: string
@@ -839,6 +846,7 @@ const fakeViewerState = (overrides?: PartialDeep<ViewerState.SerializedViewerSta
describe('updates', () => {
let updatablesProject: BasicTestStream
let models: BasicTestBranch[]
let modelWithoutViews: BasicTestBranch
let testView: BasicSavedViewFragment
let testView2: BasicSavedViewFragment
let optionalGroup: BasicSavedViewGroupFragment
@@ -883,6 +891,13 @@ const fakeViewerState = (overrides?: PartialDeep<ViewerState.SerializedViewerSta
})
})
)
modelWithoutViews = await createTestBranch({
branch: buildBasicTestModel({
name: `Model w/o views`
}),
stream: updatablesProject,
owner: me
})
optionalGroup = (
await createSavedViewGroup(
@@ -1163,6 +1178,42 @@ const fakeViewerState = (overrides?: PartialDeep<ViewerState.SerializedViewerSta
expect(view1Again!.isHomeView).to.be.false
})
it('models w/ and w/o saved views resolve resourceIdString correctly', async () => {
await updateView(
{
input: {
id: testView.id,
projectId: updatablesProject.id,
isHomeView: true
}
},
{ assertNoErrors: true }
)
const testViewModelId = models[0].id
const resWithHomeView = await getModelHomeView(
{
projectId: updatablesProject.id,
modelId: testViewModelId
},
{ assertNoErrors: true }
)
expect(resWithHomeView.data?.project.model.resourceIdString).to.eq(
testViewModelId
)
const resWithoutHomeView = await getModelHomeView(
{
projectId: updatablesProject.id,
modelId: modelWithoutViews.id
},
{ assertNoErrors: true }
)
expect(resWithoutHomeView.data?.project.model.resourceIdString).to.eq(
modelWithoutViews.id
)
})
it('fails if updating view to be private home view', async () => {
const res = await updateView({
input: {
@@ -457,9 +457,14 @@ describe('Viewer Resources Collection Service', () => {
expect(homeViewGroup).to.be.ok
expect(homeViewGroup!.items.length).to.equal(1)
expect(homeViewGroup!.items[0].modelId).to.equal(homeViewModel().id)
// expect(homeViewGroup!.items[0].versionId).to.equal(
// getModelVersions(homeViewModel().id)[0].id
// ) // version specified in view, not latest one
expect(homeViewGroup!.items[0].versionId).to.equal(
getModelVersions(homeViewModel().id)[0].id
) // version specified in view, not latest one
getModelVersions(homeViewModel().id).at(-1)!.id
) // we're doing latest version for now
expect(homeViewGroup!.items[0].objectId).to.be.ok
})
@@ -226,6 +226,16 @@ describe('Viewer Route Helpers', () => {
)
})
it('can clear versionIds', () => {
const builder = resourceBuilder().addResources('abc,def@ver')
expect(builder.length).toBe(2)
expect(builder.toString()).toBe('abc,def@ver')
builder.clearVersions()
expect(builder.length).toBe(2)
expect(builder.toString()).toBe('abc,def')
})
it('can add resources array', () => {
const resources = [
parseResourceFromString('abc'),
@@ -260,6 +260,17 @@ class ViewerResourceBuilder implements Iterable<ViewerResource> {
return this.#resources.length
}
/**
* Remove specified versionIds from any model resources
*/
clearVersions() {
this.#resources.forEach((r) => {
if (!isModelResource(r)) return
r.versionId = undefined
})
return this
}
isEqualTo(resource: ViewerResourcesTarget) {
const incomingBuilder = resourceBuilder().addResources(resource)
return this.toString() === incomingBuilder.toString()