From 45d7d4d02bdbca7859214d80b2a17656c00db6a7 Mon Sep 17 00:00:00 2001 From: andrewwallacespeckle <139135120+andrewwallacespeckle@users.noreply.github.com> Date: Fri, 7 Mar 2025 12:18:45 +0000 Subject: [PATCH] feat(fe): Tutorials page (#4120) * Tutorials Page * Add tutorials page * Update Page.vue * Changes from PR * Updates from call * Remove page added in error * Update Page.vue * Remove shallowref * Update mixpanel name --- .../frontend-2/components/connectors/Page.vue | 3 +- .../frontend-2/components/dashboard/Page.vue | 25 ++++----- .../components/dashboard/Sidebar.vue | 14 ++++- .../components/global/icon/Tutorials.vue | 45 ++++++++++++++++ .../TutorialCard.vue => tutorials/Card.vue} | 6 ++- .../frontend-2/components/tutorials/Page.vue | 51 +++++++++++++++++++ .../frontend-2/lib/common/helpers/route.ts | 1 + .../lib/dashboard/helpers/tutorials.ts | 14 ++--- packages/frontend-2/pages/tutorials/index.vue | 13 +++++ .../modules/core/graph/generated/graphql.ts | 12 ++++- .../graph/generated/graphql.ts | 11 +++- .../server/test/graphql/generated/graphql.ts | 19 ++++--- 12 files changed, 177 insertions(+), 37 deletions(-) create mode 100644 packages/frontend-2/components/global/icon/Tutorials.vue rename packages/frontend-2/components/{dashboard/TutorialCard.vue => tutorials/Card.vue} (86%) create mode 100644 packages/frontend-2/components/tutorials/Page.vue create mode 100644 packages/frontend-2/pages/tutorials/index.vue diff --git a/packages/frontend-2/components/connectors/Page.vue b/packages/frontend-2/components/connectors/Page.vue index 80c1a2d07..88de18a2b 100644 --- a/packages/frontend-2/components/connectors/Page.vue +++ b/packages/frontend-2/components/connectors/Page.vue @@ -33,11 +33,12 @@ name="categories" label="Categories" placeholder="All categories" - class="md:min-w-80" + class="md:w-80" allow-unset :items="categories" size="base" color="foundation" + clearable > + + + + + + + + + + + + + + diff --git a/packages/frontend-2/components/dashboard/TutorialCard.vue b/packages/frontend-2/components/tutorials/Card.vue similarity index 86% rename from packages/frontend-2/components/dashboard/TutorialCard.vue rename to packages/frontend-2/components/tutorials/Card.vue index 20e06e645..0eb00f034 100644 --- a/packages/frontend-2/components/dashboard/TutorialCard.vue +++ b/packages/frontend-2/components/tutorials/Card.vue @@ -6,7 +6,7 @@ @@ -27,12 +27,14 @@ const mixpanel = useMixpanel() const props = defineProps<{ tutorialItem: TutorialItem + source: 'tutorials' | 'dashboard' }>() const trackClick = () => { mixpanel.track('Tutorial clicked', { title: props.tutorialItem.title, - url: props.tutorialItem.url + url: props.tutorialItem.url, + source: props.source }) } diff --git a/packages/frontend-2/components/tutorials/Page.vue b/packages/frontend-2/components/tutorials/Page.vue new file mode 100644 index 000000000..7dc90e9bd --- /dev/null +++ b/packages/frontend-2/components/tutorials/Page.vue @@ -0,0 +1,51 @@ + + + diff --git a/packages/frontend-2/lib/common/helpers/route.ts b/packages/frontend-2/lib/common/helpers/route.ts index 187c871e2..b298002ad 100644 --- a/packages/frontend-2/lib/common/helpers/route.ts +++ b/packages/frontend-2/lib/common/helpers/route.ts @@ -16,6 +16,7 @@ export const verifyEmailRoute = '/verify-email' export const verifyEmailCountdownRoute = '/verify-email?source=registration' export const serverManagementRoute = '/server-management' export const connectorsRoute = '/connectors' +export const tutorialsRoute = '/tutorials' export const downloadManagerUrl = 'https://speckle.systems/download' export const docsPageUrl = 'https://speckle.guide/' export const forumPageUrl = 'https://speckle.community/' diff --git a/packages/frontend-2/lib/dashboard/helpers/tutorials.ts b/packages/frontend-2/lib/dashboard/helpers/tutorials.ts index e1e2a6ecc..98c0ed09a 100644 --- a/packages/frontend-2/lib/dashboard/helpers/tutorials.ts +++ b/packages/frontend-2/lib/dashboard/helpers/tutorials.ts @@ -1,6 +1,12 @@ import type { TutorialItem } from '~/lib/dashboard/helpers/types' -export const tutorials: TutorialItem[] = [ +export const tutorialItems: TutorialItem[] = [ + { + title: 'Get Civil 3D Pipe Networks Into Revit as Families', + image: + 'https://cdn.prod.website-files.com/66c31b5a50432200dc753cc4/67b8980920e42b89aff75a3f_C3d%20to%20Revit.jpg', + url: 'https://www.speckle.systems/tutorials/pipe-networks-civil3d-revit' + }, { title: 'How To Get Data From Grasshopper Into Power BI', image: @@ -42,11 +48,5 @@ export const tutorials: TutorialItem[] = [ image: 'https://cdn.prod.website-files.com/66c31b5a50432200dc753cc4/66f9c50ac50a28b58fe0e10b_66e047f505114bd4a6854b6a_216-blocks-to-families%25400.5x.png', url: 'https://www.speckle.systems/tutorials/new-in-2-16-block-to-family-conversion' - }, - { - title: 'SketchUp Connector for Mac', - image: - 'https://cdn.prod.website-files.com/66c31b5a50432200dc753cc4/66f9c508c50a28b58fe0ddef_66e047f6aacfa88a6524a956_final-blog.jpeg', - url: 'https://www.speckle.systems/tutorials/sketchup-connector-for-mac' } ] diff --git a/packages/frontend-2/pages/tutorials/index.vue b/packages/frontend-2/pages/tutorials/index.vue new file mode 100644 index 000000000..1538b8aad --- /dev/null +++ b/packages/frontend-2/pages/tutorials/index.vue @@ -0,0 +1,13 @@ + + + diff --git a/packages/server/modules/core/graph/generated/graphql.ts b/packages/server/modules/core/graph/generated/graphql.ts index 67482072d..2bdabacb8 100644 --- a/packages/server/modules/core/graph/generated/graphql.ts +++ b/packages/server/modules/core/graph/generated/graphql.ts @@ -2036,7 +2036,7 @@ export type Project = { versions: VersionCollection; /** Return metadata about resources being requested in the viewer */ viewerResources: Array; - visibility: ProjectVisibility; + visibility: SimpleProjectVisibility; webhooks: WebhookCollection; workspace?: Maybe; workspaceId?: Maybe; @@ -3147,6 +3147,13 @@ export type SetPrimaryUserEmailInput = { id: Scalars['ID']['input']; }; +/** Visbility without the "discoverable" option */ +export const SimpleProjectVisibility = { + Private: 'PRIVATE', + Unlisted: 'UNLISTED' +} as const; + +export type SimpleProjectVisibility = typeof SimpleProjectVisibility[keyof typeof SimpleProjectVisibility]; export type SmartTextEditorValue = { __typename?: 'SmartTextEditorValue'; /** File attachments, if any */ @@ -5160,6 +5167,7 @@ export type ResolversTypes = { ServerWorkspacesInfo: ResolverTypeWrapper; SessionPaymentStatus: SessionPaymentStatus; SetPrimaryUserEmailInput: SetPrimaryUserEmailInput; + SimpleProjectVisibility: SimpleProjectVisibility; SmartTextEditorValue: ResolverTypeWrapper; SortDirection: SortDirection; Stream: ResolverTypeWrapper; @@ -6328,7 +6336,7 @@ export type ProjectResolvers>; versions?: Resolver>; viewerResources?: Resolver, ParentType, ContextType, RequireFields>; - visibility?: Resolver; + visibility?: Resolver; webhooks?: Resolver>; workspace?: Resolver, ParentType, ContextType>; workspaceId?: Resolver, ParentType, ContextType>; 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 58c4d2422..bbee869e8 100644 --- a/packages/server/modules/cross-server-sync/graph/generated/graphql.ts +++ b/packages/server/modules/cross-server-sync/graph/generated/graphql.ts @@ -2016,7 +2016,7 @@ export type Project = { versions: VersionCollection; /** Return metadata about resources being requested in the viewer */ viewerResources: Array; - visibility: ProjectVisibility; + visibility: SimpleProjectVisibility; webhooks: WebhookCollection; workspace?: Maybe; workspaceId?: Maybe; @@ -3127,6 +3127,13 @@ export type SetPrimaryUserEmailInput = { id: Scalars['ID']['input']; }; +/** Visbility without the "discoverable" option */ +export const SimpleProjectVisibility = { + Private: 'PRIVATE', + Unlisted: 'UNLISTED' +} as const; + +export type SimpleProjectVisibility = typeof SimpleProjectVisibility[keyof typeof SimpleProjectVisibility]; export type SmartTextEditorValue = { __typename?: 'SmartTextEditorValue'; /** File attachments, if any */ @@ -4914,7 +4921,7 @@ export type CrossSyncProjectMetadataQueryVariables = Exact<{ }>; -export type CrossSyncProjectMetadataQuery = { __typename?: 'Query', project: { __typename?: 'Project', id: string, name: string, description?: string | null, visibility: ProjectVisibility, versions: { __typename?: 'VersionCollection', totalCount: number, cursor?: string | null, items: Array<{ __typename?: 'Version', id: string, createdAt: string, model: { __typename?: 'Model', id: string, name: string } }> } } }; +export type CrossSyncProjectMetadataQuery = { __typename?: 'Query', project: { __typename?: 'Project', id: string, name: string, description?: string | null, visibility: SimpleProjectVisibility, versions: { __typename?: 'VersionCollection', totalCount: number, cursor?: string | null, items: Array<{ __typename?: 'Version', id: string, createdAt: string, model: { __typename?: 'Model', id: string, name: string } }> } } }; export type CrossSyncClientTestQueryVariables = Exact<{ [key: string]: never; }>; diff --git a/packages/server/test/graphql/generated/graphql.ts b/packages/server/test/graphql/generated/graphql.ts index 148c5f21b..40077b217 100644 --- a/packages/server/test/graphql/generated/graphql.ts +++ b/packages/server/test/graphql/generated/graphql.ts @@ -2017,7 +2017,7 @@ export type Project = { versions: VersionCollection; /** Return metadata about resources being requested in the viewer */ viewerResources: Array; - visibility: ProjectVisibility; + visibility: SimpleProjectVisibility; webhooks: WebhookCollection; workspace?: Maybe; workspaceId?: Maybe; @@ -3128,6 +3128,13 @@ export type SetPrimaryUserEmailInput = { id: Scalars['ID']['input']; }; +/** Visbility without the "discoverable" option */ +export const SimpleProjectVisibility = { + Private: 'PRIVATE', + Unlisted: 'UNLISTED' +} as const; + +export type SimpleProjectVisibility = typeof SimpleProjectVisibility[keyof typeof SimpleProjectVisibility]; export type SmartTextEditorValue = { __typename?: 'SmartTextEditorValue'; /** File attachments, if any */ @@ -5152,7 +5159,7 @@ export type UpdateWorkspaceProjectRoleMutationVariables = Exact<{ }>; -export type UpdateWorkspaceProjectRoleMutation = { __typename?: 'Mutation', workspaceMutations: { __typename?: 'WorkspaceMutations', projects: { __typename?: 'WorkspaceProjectMutations', updateRole: { __typename?: 'Project', id: string, name: string, description?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, role?: string | null, createdAt: string, updatedAt: string } } } }; +export type UpdateWorkspaceProjectRoleMutation = { __typename?: 'Mutation', workspaceMutations: { __typename?: 'WorkspaceMutations', projects: { __typename?: 'WorkspaceProjectMutations', updateRole: { __typename?: 'Project', id: string, name: string, description?: string | null, visibility: SimpleProjectVisibility, allowPublicComments: boolean, role?: string | null, createdAt: string, updatedAt: string } } } }; export type BasicStreamAccessRequestFieldsFragment = { __typename?: 'StreamAccessRequest', id: string, requesterId: string, streamId: string, createdAt: string, requester: { __typename?: 'LimitedUser', id: string, name: string } }; @@ -5495,7 +5502,7 @@ export type EditProjectCommentMutationVariables = Exact<{ export type EditProjectCommentMutation = { __typename?: 'Mutation', commentMutations: { __typename?: 'CommentMutations', edit: { __typename?: 'Comment', id: string, rawText: string, authorId: string, text: { __typename?: 'SmartTextEditorValue', doc?: Record | null } } } }; -export type BasicProjectFieldsFragment = { __typename?: 'Project', id: string, name: string, description?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, role?: string | null, createdAt: string, updatedAt: string }; +export type BasicProjectFieldsFragment = { __typename?: 'Project', id: string, name: string, description?: string | null, visibility: SimpleProjectVisibility, allowPublicComments: boolean, role?: string | null, createdAt: string, updatedAt: string }; export type AdminProjectListQueryVariables = Exact<{ query?: InputMaybe; @@ -5506,7 +5513,7 @@ export type AdminProjectListQueryVariables = Exact<{ }>; -export type AdminProjectListQuery = { __typename?: 'Query', admin: { __typename?: 'AdminQueries', projectList: { __typename?: 'ProjectCollection', cursor?: string | null, totalCount: number, items: Array<{ __typename?: 'Project', id: string, name: string, description?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, role?: string | null, createdAt: string, updatedAt: string }> } } }; +export type AdminProjectListQuery = { __typename?: 'Query', admin: { __typename?: 'AdminQueries', projectList: { __typename?: 'ProjectCollection', cursor?: string | null, totalCount: number, items: Array<{ __typename?: 'Project', id: string, name: string, description?: string | null, visibility: SimpleProjectVisibility, allowPublicComments: boolean, role?: string | null, createdAt: string, updatedAt: string }> } } }; export type GetProjectObjectQueryVariables = Exact<{ projectId: Scalars['String']['input']; @@ -5528,7 +5535,7 @@ export type CreateProjectMutationVariables = Exact<{ }>; -export type CreateProjectMutation = { __typename?: 'Mutation', projectMutations: { __typename?: 'ProjectMutations', create: { __typename?: 'Project', id: string, name: string, description?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, role?: string | null, createdAt: string, updatedAt: string } } }; +export type CreateProjectMutation = { __typename?: 'Mutation', projectMutations: { __typename?: 'ProjectMutations', create: { __typename?: 'Project', id: string, name: string, description?: string | null, visibility: SimpleProjectVisibility, allowPublicComments: boolean, role?: string | null, createdAt: string, updatedAt: string } } }; export type BatchDeleteProjectsMutationVariables = Exact<{ ids: Array | Scalars['String']['input']; @@ -5542,7 +5549,7 @@ export type UpdateProjectRoleMutationVariables = Exact<{ }>; -export type UpdateProjectRoleMutation = { __typename?: 'Mutation', projectMutations: { __typename?: 'ProjectMutations', updateRole: { __typename?: 'Project', id: string, name: string, description?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, role?: string | null, createdAt: string, updatedAt: string } } }; +export type UpdateProjectRoleMutation = { __typename?: 'Mutation', projectMutations: { __typename?: 'ProjectMutations', updateRole: { __typename?: 'Project', id: string, name: string, description?: string | null, visibility: SimpleProjectVisibility, allowPublicComments: boolean, role?: string | null, createdAt: string, updatedAt: string } } }; export type CreateServerInviteMutationVariables = Exact<{ input: ServerInviteCreateInput;