Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Switch tutorial feed to Sanity #3822

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions packages/frontend-2/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,4 @@ NUXT_PUBLIC_SURVICATE_WORKSPACE_KEY=
NUXT_PUBLIC_ENABLE_DIRECT_PREVIEWS=true

# Ghost API
NUXT_PUBLIC_GHOST_API_KEY=

NUXT_WEBFLOW_API_TOKEN=8c9bea4c120742a21ff308cda0bea73f13e89ffe26dcc886990bba353549b652
NUXT_PUBLIC_GHOST_API_KEY=
18 changes: 9 additions & 9 deletions packages/frontend-2/components/dashboard/tutorials/Card.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<template>
<NuxtLink :to="webflowItem.url" target="_blank" @click="trackClick">
<NuxtLink :to="tutorialItem.url" target="_blank" @click="trackClick">
<div
class="bg-foundation border border-outline-3 rounded-xl flex flex-col overflow-hidden hover:border-outline-5 transition"
>
<NuxtImg
v-if="webflowItem.featureImageUrl"
:src="webflowItem.featureImageUrl"
:alt="webflowItem.title"
v-if="tutorialItem.image"
:src="tutorialItem.image"
:alt="tutorialItem.title"
class="h-32 w-full object-cover"
width="400"
height="225"
Expand All @@ -19,27 +19,27 @@
</div>
<div class="p-5">
<h3 class="text-body-2xs text-foreground truncate">
{{ webflowItem.title }}
{{ tutorialItem.title }}
</h3>
</div>
</div>
</NuxtLink>
</template>

<script lang="ts" setup>
import type { WebflowItem } from '~/lib/dashboard/helpers/types'
import type { TutorialItem } from '~/lib/dashboard/helpers/types'
import { useMixpanel } from '~~/lib/core/composables/mp'

const mixpanel = useMixpanel()

const props = defineProps<{
webflowItem: WebflowItem
tutorialItem: TutorialItem
}>()

const trackClick = () => {
mixpanel.track('Tutorial clicked', {
title: props.webflowItem.title,
id: props.webflowItem.id
title: props.tutorialItem.title,
id: props.tutorialItem.id
})
}
</script>
26 changes: 13 additions & 13 deletions packages/frontend-2/components/dashboard/tutorials/Wrapper.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,29 @@
<h2 class="text-heading-sm text-foreground-2 mb-4">Tutorials</h2>
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
<DashboardTutorialsCard
v-for="webflowItem in webflowItems"
:key="webflowItem.id"
:webflow-item="webflowItem"
v-for="tutorialItem in tutorialItems"
:key="tutorialItem.id"
:tutorial-item="tutorialItem"
/>
</div>
</section>
<section v-else />
</template>

<script setup lang="ts">
import type { WebflowItem } from '~/lib/dashboard/helpers/types'
import type { TutorialItem } from '~/lib/dashboard/helpers/types'

const logger = useLogger()

const { data: webflowData, error } = await useAsyncData<{
items: WebflowItem[]
}>('webflow-items', () =>
$fetch<{ items: WebflowItem[] }>('/api/webflow', {
onResponseError({ response }) {
logger.error('API Response Error:', response.status, response.statusText)
}
})
const { data: tutorialData, error } = await useAsyncData<TutorialItem[]>(
'tutorial-items',
() =>
$fetch<TutorialItem[]>('/api/tutorials', {
onResponseError({ response }) {
logger.error('API Response Error:', response.status, response.statusText)
}
})
)

const webflowItems = computed(() => webflowData.value?.items || [])
const tutorialItems = computed(() => tutorialData.value || [])
</script>
23 changes: 23 additions & 0 deletions packages/frontend-2/lib/common/generated/gql/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4285,6 +4285,10 @@ export type WorkspaceCreationStateInput = {
workspaceId: Scalars['ID']['input'];
};

export type WorkspaceDismissInput = {
workspaceId: Scalars['ID']['input'];
};

export type WorkspaceDomain = {
__typename?: 'WorkspaceDomain';
domain: Scalars['String']['output'];
Expand Down Expand Up @@ -4378,10 +4382,13 @@ export type WorkspaceMutations = {
delete: Scalars['Boolean']['output'];
deleteDomain: Workspace;
deleteSsoProvider: Scalars['Boolean']['output'];
/** Dismiss a workspace from the discoverable list, behind the scene a join request is created with the status "dismissed" */
dismiss: Scalars['Boolean']['output'];
invites: WorkspaceInviteMutations;
join: Workspace;
leave: Scalars['Boolean']['output'];
projects: WorkspaceProjectMutations;
requestToJoin: Scalars['Boolean']['output'];
/** Set the default region where project data will be stored. Only available to admins. */
setDefaultRegion: Workspace;
update: Workspace;
Expand Down Expand Up @@ -4415,6 +4422,11 @@ export type WorkspaceMutationsDeleteSsoProviderArgs = {
};


export type WorkspaceMutationsDismissArgs = {
input: WorkspaceDismissInput;
};


export type WorkspaceMutationsJoinArgs = {
input: JoinWorkspaceInput;
};
Expand All @@ -4425,6 +4437,11 @@ export type WorkspaceMutationsLeaveArgs = {
};


export type WorkspaceMutationsRequestToJoinArgs = {
input: WorkspaceRequestToJoinInput;
};


export type WorkspaceMutationsSetDefaultRegionArgs = {
regionKey: Scalars['String']['input'];
workspaceId: Scalars['String']['input'];
Expand Down Expand Up @@ -4534,6 +4551,10 @@ export enum WorkspaceProjectsUpdatedMessageType {
Removed = 'REMOVED'
}

export type WorkspaceRequestToJoinInput = {
workspaceId: Scalars['ID']['input'];
};

export enum WorkspaceRole {
Admin = 'ADMIN',
Guest = 'GUEST',
Expand Down Expand Up @@ -8117,10 +8138,12 @@ export type WorkspaceMutationsFieldArgs = {
delete: WorkspaceMutationsDeleteArgs,
deleteDomain: WorkspaceMutationsDeleteDomainArgs,
deleteSsoProvider: WorkspaceMutationsDeleteSsoProviderArgs,
dismiss: WorkspaceMutationsDismissArgs,
invites: {},
join: WorkspaceMutationsJoinArgs,
leave: WorkspaceMutationsLeaveArgs,
projects: {},
requestToJoin: WorkspaceMutationsRequestToJoinArgs,
setDefaultRegion: WorkspaceMutationsSetDefaultRegionArgs,
update: WorkspaceMutationsUpdateArgs,
updateCreationState: WorkspaceMutationsUpdateCreationStateArgs,
Expand Down
9 changes: 4 additions & 5 deletions packages/frontend-2/lib/dashboard/helpers/types.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { type LayoutDialogButton } from '@speckle/ui-components'

export type WebflowItem = {
id: string
export interface TutorialItem {
title: string
createdOn: string
lastPublished: string
featureImageUrl?: string
publishedAt: string
image?: string
id: string
url: string
}

Expand Down
1 change: 0 additions & 1 deletion packages/frontend-2/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ export default defineNuxtConfig({
],
runtimeConfig: {
redisUrl: '',
webflowApiToken: '',
public: {
...featureFlags,
apiOrigin: 'UNDEFINED',
Expand Down
2 changes: 2 additions & 0 deletions packages/frontend-2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@
"@nuxt/image": "^1.8.1",
"@nuxtjs/tailwindcss": "^6.12.2",
"@parcel/watcher": "^2.4.1",
"@sanity/image-url": "^1.1.0",
"@sanity/types": "^3.70.0",
"@speckle/tailwind-theme": "workspace:^",
"@tailwindcss/forms": "^0.5.3",
"@tailwindcss/line-clamp": "^0.4.2",
Expand Down
59 changes: 59 additions & 0 deletions packages/frontend-2/server/api/tutorials.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { ensureError } from '@speckle/shared'
import imageUrlBuilder from '@sanity/image-url'
import dayjs from 'dayjs'
import type { SanityDocument, Reference } from '@sanity/types'
import type { TutorialItem } from '~/lib/dashboard/helpers/types'

export interface SanityTutorial extends SanityDocument {
title: string
publishedAt: string
mainImage?: {
asset: Reference
}
url: string
webflowUrl: string
}

export default defineEventHandler(async (): Promise<TutorialItem[]> => {
const imageBuilder = imageUrlBuilder({
projectId: '6kukgozu',
dataset: 'production'
})

const currentDate = dayjs().format('YYYY-MM-DD')
const query = encodeURIComponent(
'*[_type == "tutorial"] | order(publishedAt desc)[0...8]'
)
const url = `https://6kukgozu.api.sanity.io/v${currentDate}/data/query/production?query=${query}`

try {
const response = await fetch(url)
const data = (await response.json()) as { result: SanityTutorial[] }

if (!response.ok) {
const errMsg = `Sanity API Error: ${response.status} ${response.statusText}`
throw createError({
statusCode: response.status,
fatal: true,
message: errMsg
})
}

return data.result.map((item) => ({
title: item.title,
publishedAt: item.publishedAt,
image: item.mainImage
? imageBuilder.image(item.mainImage).width(600).height(300).fit('fillmax').url()
: undefined,
id: item._id,
url: item.webflowUrl
}))
} catch (e) {
const errMsg = ensureError(e).message
throw createError({
statusCode: 500,
fatal: true,
message: `Error fetching tutorial items: ${errMsg}`
})
}
})
86 changes: 0 additions & 86 deletions packages/frontend-2/server/api/webflow.ts

This file was deleted.

3 changes: 0 additions & 3 deletions utils/helm/speckle-server/templates/frontend_2/deployment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,6 @@ spec:
secretKeyRef:
name: {{ default .Values.secretName .Values.redis.connectionString.secretName }}
key: {{ default "redis_url" .Values.redis.connectionString.secretKey }}
{{- if .Values.frontend_2.webflowApiToken }}
- name: NUXT_WEBFLOW_API_TOKEN
value: {{ .Values.frontend_2.webflowApiToken | quote }}
{{- end }}
{{- if .Values.analytics.datadog_app_id }}
- name: NUXT_PUBLIC_DATADOG_APP_ID
Expand Down
5 changes: 0 additions & 5 deletions utils/helm/speckle-server/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1749,11 +1749,6 @@
"description": "The Docker image to be used for the Speckle Frontend 2 component. If blank, defaults to speckle/speckle-frontend-2:{{ .Values.docker_image_tag }}. If provided, this value should be the full path including tag. The docker_image_tag value will be ignored.",
"default": ""
},
"webflowApiToken": {
"type": "string",
"description": "API Key for Webflow, which provides the blog content for the new web application frontend.",
"default": ""
},
"logClientApiToken": {
"type": "string",
"description": "SEQ API token",
Expand Down
3 changes: 0 additions & 3 deletions utils/helm/speckle-server/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1047,9 +1047,6 @@ frontend_2:
## @param frontend_2.image The Docker image to be used for the Speckle Frontend 2 component. If blank, defaults to speckle/speckle-frontend-2:{{ .Values.docker_image_tag }}. If provided, this value should be the full path including tag. The docker_image_tag value will be ignored.
##
image: ''
## @param frontend_2.webflowApiToken API Key for Webflow, which provides the blog content for the new web application frontend.
##
webflowApiToken: ''
## @param frontend_2.logClientApiToken SEQ API token
##
logClientApiToken: ''
Expand Down
Loading