feat(fe2): redirects for legacy/fe1 embed routes (#2432)

This commit is contained in:
Kristaps Fabians Geikins
2024-06-28 10:52:09 +03:00
committed by GitHub
parent e55a94028d
commit 1da1c4e30a
4 changed files with 139 additions and 9 deletions
@@ -230,6 +230,7 @@ const documents = {
"\n fragment LinkableComment on Comment {\n id\n viewerResources {\n modelId\n versionId\n objectId\n }\n }\n": types.LinkableCommentFragmentDoc,
"\n query LegacyBranchRedirectMetadata($streamId: String!, $branchName: String!) {\n stream(id: $streamId) {\n branch(name: $branchName) {\n id\n }\n }\n }\n": types.LegacyBranchRedirectMetadataDocument,
"\n query LegacyViewerCommitRedirectMetadata($streamId: String!, $commitId: String!) {\n stream(id: $streamId) {\n commit(id: $commitId) {\n id\n branch {\n id\n }\n }\n }\n }\n": types.LegacyViewerCommitRedirectMetadataDocument,
"\n query LegacyViewerStreamRedirectMetadata($streamId: String!) {\n stream(id: $streamId) {\n id\n commits(limit: 1) {\n totalCount\n items {\n id\n branch {\n id\n }\n }\n }\n }\n }\n": types.LegacyViewerStreamRedirectMetadataDocument,
"\n query ResolveCommentLink($commentId: String!, $projectId: String!) {\n comment(id: $commentId, streamId: $projectId) {\n ...LinkableComment\n }\n }\n": types.ResolveCommentLinkDocument,
"\n fragment AutomateFunctionPage_AutomateFunction on AutomateFunction {\n id\n name\n description\n logo\n supportedSourceApps\n tags\n ...AutomateFunctionPageHeader_Function\n ...AutomateFunctionPageInfo_AutomateFunction\n ...AutomateAutomationCreateDialog_AutomateFunction\n creator {\n id\n }\n }\n": types.AutomateFunctionPage_AutomateFunctionFragmentDoc,
"\n query AutomateFunctionPage($functionId: ID!) {\n automateFunction(id: $functionId) {\n ...AutomateFunctionPage_AutomateFunction\n }\n }\n": types.AutomateFunctionPageDocument,
@@ -1122,6 +1123,10 @@ export function graphql(source: "\n query LegacyBranchRedirectMetadata($streamI
* 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 LegacyViewerCommitRedirectMetadata($streamId: String!, $commitId: String!) {\n stream(id: $streamId) {\n commit(id: $commitId) {\n id\n branch {\n id\n }\n }\n }\n }\n"): (typeof documents)["\n query LegacyViewerCommitRedirectMetadata($streamId: String!, $commitId: String!) {\n stream(id: $streamId) {\n commit(id: $commitId) {\n id\n branch {\n id\n }\n }\n }\n }\n"];
/**
* 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 LegacyViewerStreamRedirectMetadata($streamId: String!) {\n stream(id: $streamId) {\n id\n commits(limit: 1) {\n totalCount\n items {\n id\n branch {\n id\n }\n }\n }\n }\n }\n"): (typeof documents)["\n query LegacyViewerStreamRedirectMetadata($streamId: String!) {\n stream(id: $streamId) {\n id\n commits(limit: 1) {\n totalCount\n items {\n id\n branch {\n id\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.
*/
File diff suppressed because one or more lines are too long
@@ -33,7 +33,7 @@ export const modelRoute = (
resourceIdString: string,
hashState?: Partial<Record<ViewerHashStateKeys, string>>
) =>
`/projects/${projectId}/models/${encodeURIComponent(resourceIdString)}${
`/projects/${projectId}/models/${resourceIdString}${
hashState ? serializeHashState(hashState) || '' : ''
}`
export const modelVersionsRoute = (projectId: string, modelId: string) =>
@@ -9,6 +9,7 @@ import {
projectRoute,
serverManagementRoute
} from '~/lib/common/helpers/route'
import type { EmbedOptions } from '~/lib/viewer/composables/setup/embed'
import { ViewerHashStateKeys } from '~/lib/viewer/composables/setup/urlHashState'
const legacyBranchMetadataQuery = graphql(`
@@ -34,6 +35,34 @@ const legacyViewerCommitMetadataQuery = graphql(`
}
`)
const legacyViewerStreamMetadataQuery = graphql(`
query LegacyViewerStreamRedirectMetadata($streamId: String!) {
stream(id: $streamId) {
id
commits(limit: 1) {
totalCount
items {
id
branch {
id
}
}
}
}
}
`)
const viewerPageRgx =
/^\/streams\/([a-zA-Z0-9-_]+)\/(commits|objects)\/([a-zA-Z0-9-_]+)\/?/
const embedViewerPageRgx = /^\/embed\/?/
const streamBranchPageRgx =
/^\/streams\/([a-zA-Z0-9-_]+)\/branches\/([a-zA-Z0-9-_%]+)\/?/
const streamPageRgx = /^\/streams\/([a-zA-Z0-9-_]+)\/?/
const adminPageRgx = /^\/admin\/?/
/**
* Setting up all kinds of redirects (e.g. for FE1 backwards compatibility)
*/
@@ -41,17 +70,15 @@ const legacyViewerCommitMetadataQuery = graphql(`
export default defineNuxtRouteMiddleware(async (to) => {
const path = to.path
const apollo = useApolloClientFromNuxt()
const resourceBuilder = () => SpeckleViewer.ViewerRoute.resourceBuilder()
if (['/streams', '/commits'].includes(path)) {
return navigateTo(homeRoute)
}
const viewerPageRgx =
/^\/streams\/([a-zA-Z0-9-_]+)\/(commits|objects)\/([a-zA-Z0-9-_]+)\/?/
const [, viewerStreamId, viewerType, viewerId] = path.match(viewerPageRgx) || []
if (viewerStreamId && viewerType && viewerId) {
const resourceIdStringBuilder = SpeckleViewer.ViewerRoute.resourceBuilder()
const resourceIdStringBuilder = resourceBuilder()
// Resolve comment ID, if any
const commentId = to.query['cId'] as Optional<string>
@@ -84,8 +111,100 @@ export default defineNuxtRouteMiddleware(async (to) => {
}
}
const streamBranchPageRgx =
/^\/streams\/([a-zA-Z0-9-_]+)\/branches\/([a-zA-Z0-9-_%]+)\/?/
const isEmbed = embedViewerPageRgx.test(path)
if (isEmbed) {
const embedOptions: EmbedOptions = {
isEnabled: true,
...(to.query['transparent'] === 'true' ? { isTransparent: true } : {}),
...(to.query['hidecontrols'] === 'true' ? { hideControls: true } : {}),
...(to.query['hideselectioninfo'] === 'true' ? { hideSelectionInfo: true } : {}),
...(to.query['noscroll'] === 'true' ? { noScroll: true } : {}),
...(to.query['autoload'] === 'true'
? { manualLoad: false }
: { manualLoad: true })
}
// Resolve stream/object/commit ID from query
const streamId = to.query['stream'] as Optional<string> // get first stream commit
const commitId = to.query['commit'] as Optional<string> // get specific commit
const objectId = to.query['object'] as Optional<string> // get specific object
const branchName = to.query['branch'] as Optional<string> // get first branch commit
if (!streamId?.length) {
return navigateTo(homeRoute)
}
if (objectId?.length) {
return navigateTo(
modelRoute(streamId, resourceBuilder().addObject(objectId).toString(), {
[ViewerHashStateKeys.EmbedOptions]: JSON.stringify(embedOptions)
})
)
} else if (commitId?.length) {
const { data } = await apollo
.query({
query: legacyViewerCommitMetadataQuery,
variables: { streamId, commitId }
})
.catch(convertThrowIntoFetchResult)
const branchId = data?.stream?.commit?.branch?.id
return navigateTo(
branchId
? modelRoute(
streamId,
resourceBuilder().addModel(branchId, commitId).toString(),
{
[ViewerHashStateKeys.EmbedOptions]: JSON.stringify(embedOptions)
}
)
: projectRoute(viewerStreamId)
)
} else if (branchName?.length) {
const { data } = await apollo
.query({
query: legacyBranchMetadataQuery,
variables: {
streamId,
branchName: decodeURIComponent(branchName)
}
})
.catch(convertThrowIntoFetchResult)
return navigateTo(
data?.stream?.branch?.id
? modelRoute(
streamId,
resourceBuilder().addModel(data.stream.branch.id).toString(),
{
[ViewerHashStateKeys.EmbedOptions]: JSON.stringify(embedOptions)
}
)
: projectRoute(streamId)
)
} else {
const { data } = await apollo
.query({ query: legacyViewerStreamMetadataQuery, variables: { streamId } })
.catch(convertThrowIntoFetchResult)
return navigateTo(
data?.stream?.commits?.items?.length && data.stream.commits.items[0].branch
? modelRoute(
data.stream.id,
SpeckleViewer.ViewerRoute.resourceBuilder()
.addModel(
data.stream.commits.items[0].branch.id,
data.stream.commits.items[0].id
)
.toString(),
{
[ViewerHashStateKeys.EmbedOptions]: JSON.stringify(embedOptions)
}
)
: projectRoute(streamId)
)
}
}
const [, branchStreamId, branchName] = path.match(streamBranchPageRgx) || []
if (branchStreamId && branchName) {
@@ -107,13 +226,11 @@ export default defineNuxtRouteMiddleware(async (to) => {
)
}
const streamPageRgx = /^\/streams\/([a-zA-Z0-9-_]+)\/?/
const [, streamId] = path.match(streamPageRgx) || []
if (streamId) {
return navigateTo(projectRoute(streamId))
}
const adminPageRgx = /^\/admin\/?/
if (adminPageRgx.test(path)) {
return navigateTo(serverManagementRoute)
}