Feat: Add loading screen to presentation (#5585)

This commit is contained in:
Mike
2025-09-29 16:17:20 +02:00
committed by GitHub
parent 299832ea9f
commit f970a02dc1
9 changed files with 114 additions and 44 deletions
@@ -24,19 +24,6 @@
>
{{ presentation?.title }}
</h1>
<!-- <LayoutMenu
v-model:open="showMenu"
class="hidden md:block"
:items="menuItems"
:menu-id="menuId"
mount-menu-on-body
@chosen="onActionChosen"
>
<PresentationFloatingPanelButton @click="showMenu = !showMenu">
<LucideEllipsis class="size-4" />
</PresentationFloatingPanelButton>
</LayoutMenu> -->
</div>
</PresentationFloatingPanel>
</template>
@@ -54,10 +41,6 @@ graphql(`
}
`)
// enum MenuItems {
// OpenInViewer = 'open-in-viewer'
// }
const emit = defineEmits<{
(e: 'toggleSidebar'): void
}>()
@@ -67,25 +50,4 @@ const isSidebarOpen = defineModel<boolean>('is-sidebar-open')
const {
response: { presentation }
} = useInjectedPresentationState()
// const menuId = useId()
// const showMenu = ref(false)
// const menuItems = computed<LayoutMenuItem[][]>(() => [
// [
// {
// title: 'Open in viewer',
// id: MenuItems.OpenInViewer
// }
// ]
// ])
// const onActionChosen = (params: { item: LayoutMenuItem }) => {
// const { item } = params
// switch (item.id) {
// case MenuItems.OpenInViewer:
// // Will be added soon
// }
// }
</script>
@@ -48,7 +48,7 @@
<p
v-if="currentSlide?.description"
ref="descriptionRef"
class="text-body-sm xl:text-body text-foreground whitespace-pre-wrap px-1 lg:px-2 xl:px-3 lg:py-1 lg:flex-1 lg:overflow-y-auto lg:line-clamp-none"
class="simple-scrollbar text-body-sm xl:text-body text-foreground whitespace-pre-wrap px-1 lg:px-2 xl:px-3 lg:py-1 lg:flex-1 lg:overflow-y-auto lg:line-clamp-none"
:class="{
'line-clamp-4 overflow-hidden': !isExpanded,
'flex-1 overflow-y-auto': isExpanded
@@ -0,0 +1,85 @@
<template>
<div class="w-full h-full flex bg-foundation">
<div class="w-full h-full flex items-center justify-center">
<div
class="text-foreground flex flex-col mx-4 items-center justify-center bg-foundation rounded-2xl border border-outline-2 shadow-lg p-10 pb-8 w-full max-w-md"
>
<div class="min-w-0 mb-14 text-center">
<h1 class="text-heading-xl truncate">{{ presentation?.title }}</h1>
</div>
<div class="w-30 h-30 inline-block mb-4">
<svg width="120" height="120" viewBox="0 0 120 120" class="medium-spin">
<circle cx="60" cy="60" r="59.5" fill="#F7F7F7" stroke="#F2F2F2" />
<circle cx="60" cy="60" r="50" fill="white" />
<circle
cx="60"
cy="60"
r="55"
fill="none"
stroke="#146FFF"
stroke-width="8"
stroke-linecap="round"
stroke-dasharray="60 290"
/>
</svg>
</div>
<div class="text-heading-sm mb-10">Fetching the 3D data</div>
<div class="max-w-[220px] flex items-center gap-x-2">
<WorkspaceAvatar :name="workspace?.name" :logo="workspace?.logo" size="lg" />
<div class="flex-1 min-w-0">
<p class="text-body-xs font-medium text-foreground truncate">
{{ workspace?.name }}
</p>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { graphql } from '~~/lib/common/generated/gql'
import { useInjectedPresentationState } from '~/lib/presentations/composables/setup'
graphql(`
fragment PresentationLoading_SavedViewGroup on SavedViewGroup {
id
title
views(input: $input) {
items {
id
screenshot
}
}
}
fragment PresentationLoading_LimitedWorkspace on LimitedWorkspace {
id
name
logo
}
`)
const {
response: { presentation, workspace }
} = useInjectedPresentationState()
</script>
<style scoped>
.medium-spin {
animation: spin 1.5s linear infinite;
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
</style>
@@ -1,5 +1,12 @@
<template>
<div class="relative">
<div
v-if="isViewerLoading"
key="loading"
class="h-dvh w-screen flex flex-col md:flex-row absolute left-0 top-0 z-50"
>
<PresentationLoading />
</div>
<div class="h-dvh w-screen flex flex-col md:flex-row relative">
<PresentationHeader
v-if="!hideUi"
@@ -3,6 +3,7 @@
<ViewerCoreSetup
viewer-host-classes="h-full"
:disable-selection="disableSelection"
:hide-loading-bar="true"
/>
</div>
</template>
@@ -10,7 +10,7 @@
</div>
<!-- Global loading bar -->
<ViewerLoadingBar :class="loadingBarClasses" />
<ViewerLoadingBar v-if="!hideLoadingBar" :class="loadingBarClasses" />
</div>
</template>
<script setup lang="ts">
@@ -22,5 +22,6 @@
defineProps<{
viewerHostClasses?: string
loadingBarClasses?: string
hideLoadingBar?: boolean
}>()
</script>
@@ -71,6 +71,7 @@ type Documents = {
"\n fragment PresentationHeader_SavedViewGroup on SavedViewGroup {\n id\n title\n }\n": typeof types.PresentationHeader_SavedViewGroupFragmentDoc,
"\n fragment PresentationInfoSidebar_SavedView on SavedView {\n id\n ...PresentationSlideEditDialog_SavedView\n name\n description\n permissions {\n canUpdate {\n ...FullPermissionCheckResult\n }\n }\n }\n": typeof types.PresentationInfoSidebar_SavedViewFragmentDoc,
"\n fragment PresentationLeftSidebar_LimitedWorkspace on LimitedWorkspace {\n id\n name\n logo\n slug\n }\n": typeof types.PresentationLeftSidebar_LimitedWorkspaceFragmentDoc,
"\n fragment PresentationLoading_SavedViewGroup on SavedViewGroup {\n id\n title\n views(input: $input) {\n items {\n id\n screenshot\n }\n }\n }\n\n fragment PresentationLoading_LimitedWorkspace on LimitedWorkspace {\n id\n name\n logo\n }\n": typeof types.PresentationLoading_SavedViewGroupFragmentDoc,
"\n fragment PresentationPageWrapper_SavedViewGroup on SavedViewGroup {\n id\n permissions {\n canUpdate {\n ...FullPermissionCheckResult\n }\n }\n }\n": typeof types.PresentationPageWrapper_SavedViewGroupFragmentDoc,
"\n fragment PresentationSlideEditDialog_SavedView on SavedView {\n id\n projectId\n name\n description\n screenshot\n }\n": typeof types.PresentationSlideEditDialog_SavedViewFragmentDoc,
"\n fragment PresentationSlideListSlide_SavedView on SavedView {\n id\n name\n screenshot\n }\n": typeof types.PresentationSlideListSlide_SavedViewFragmentDoc,
@@ -297,7 +298,7 @@ type Documents = {
"\n query NavigationWorkspaceInvites {\n activeUser {\n id\n workspaceInvites {\n ...HeaderNavNotificationsWorkspaceInvite_PendingWorkspaceCollaborator\n }\n }\n }\n": typeof types.NavigationWorkspaceInvitesDocument,
"\n mutation UpdatePresentationSlide($input: UpdateSavedViewInput!) {\n projectMutations {\n savedViewMutations {\n updateView(input: $input) {\n id\n name\n description\n }\n }\n }\n }\n": typeof types.UpdatePresentationSlideDocument,
"\n query PresentationAccessCheck($savedViewGroupId: ID!, $projectId: String!) {\n project(id: $projectId) {\n id\n savedViewGroup(id: $savedViewGroupId) {\n id\n }\n }\n }\n": typeof types.PresentationAccessCheckDocument,
"\n query ProjectPresentationPage(\n $input: SavedViewGroupViewsInput!\n $savedViewGroupId: ID!\n $projectId: String!\n ) {\n project(id: $projectId) {\n id\n limitedWorkspace {\n id\n ...PresentationLeftSidebar_LimitedWorkspace\n }\n savedViewGroup(id: $savedViewGroupId) {\n id\n title\n ...PresentationViewerPageWrapper_SavedViewGroup\n ...PresentationHeader_SavedViewGroup\n ...PresentationSlideList_SavedViewGroup\n ...PresentationPageWrapper_SavedViewGroup\n views(input: $input) {\n totalCount\n items {\n id\n name\n description\n screenshot\n projectId\n visibility\n ...PresentationInfoSidebar_SavedView\n group {\n id\n }\n }\n }\n }\n }\n }\n": typeof types.ProjectPresentationPageDocument,
"\n query ProjectPresentationPage(\n $input: SavedViewGroupViewsInput!\n $savedViewGroupId: ID!\n $projectId: String!\n ) {\n project(id: $projectId) {\n id\n limitedWorkspace {\n id\n ...PresentationLeftSidebar_LimitedWorkspace\n ...PresentationLoading_LimitedWorkspace\n }\n savedViewGroup(id: $savedViewGroupId) {\n id\n title\n ...PresentationViewerPageWrapper_SavedViewGroup\n ...PresentationHeader_SavedViewGroup\n ...PresentationSlideList_SavedViewGroup\n ...PresentationPageWrapper_SavedViewGroup\n ...PresentationLoading_SavedViewGroup\n views(input: $input) {\n totalCount\n items {\n id\n name\n description\n screenshot\n projectId\n visibility\n ...PresentationInfoSidebar_SavedView\n group {\n id\n }\n }\n }\n }\n }\n }\n": typeof types.ProjectPresentationPageDocument,
"\n fragment UseCopyModelLink_Model on Model {\n id\n projectId\n ...GetModelItemRoute_Model\n }\n": typeof types.UseCopyModelLink_ModelFragmentDoc,
"\n fragment UseCanCreatePersonalProject_User on User {\n permissions {\n canCreatePersonalProject {\n ...FullPermissionCheckResult\n }\n }\n }\n": typeof types.UseCanCreatePersonalProject_UserFragmentDoc,
"\n fragment UseCanCreateWorkspace_User on User {\n permissions {\n canCreateWorkspace {\n ...FullPermissionCheckResult\n }\n }\n }\n": typeof types.UseCanCreateWorkspace_UserFragmentDoc,
@@ -607,6 +608,7 @@ const documents: Documents = {
"\n fragment PresentationHeader_SavedViewGroup on SavedViewGroup {\n id\n title\n }\n": types.PresentationHeader_SavedViewGroupFragmentDoc,
"\n fragment PresentationInfoSidebar_SavedView on SavedView {\n id\n ...PresentationSlideEditDialog_SavedView\n name\n description\n permissions {\n canUpdate {\n ...FullPermissionCheckResult\n }\n }\n }\n": types.PresentationInfoSidebar_SavedViewFragmentDoc,
"\n fragment PresentationLeftSidebar_LimitedWorkspace on LimitedWorkspace {\n id\n name\n logo\n slug\n }\n": types.PresentationLeftSidebar_LimitedWorkspaceFragmentDoc,
"\n fragment PresentationLoading_SavedViewGroup on SavedViewGroup {\n id\n title\n views(input: $input) {\n items {\n id\n screenshot\n }\n }\n }\n\n fragment PresentationLoading_LimitedWorkspace on LimitedWorkspace {\n id\n name\n logo\n }\n": types.PresentationLoading_SavedViewGroupFragmentDoc,
"\n fragment PresentationPageWrapper_SavedViewGroup on SavedViewGroup {\n id\n permissions {\n canUpdate {\n ...FullPermissionCheckResult\n }\n }\n }\n": types.PresentationPageWrapper_SavedViewGroupFragmentDoc,
"\n fragment PresentationSlideEditDialog_SavedView on SavedView {\n id\n projectId\n name\n description\n screenshot\n }\n": types.PresentationSlideEditDialog_SavedViewFragmentDoc,
"\n fragment PresentationSlideListSlide_SavedView on SavedView {\n id\n name\n screenshot\n }\n": types.PresentationSlideListSlide_SavedViewFragmentDoc,
@@ -833,7 +835,7 @@ const documents: Documents = {
"\n query NavigationWorkspaceInvites {\n activeUser {\n id\n workspaceInvites {\n ...HeaderNavNotificationsWorkspaceInvite_PendingWorkspaceCollaborator\n }\n }\n }\n": types.NavigationWorkspaceInvitesDocument,
"\n mutation UpdatePresentationSlide($input: UpdateSavedViewInput!) {\n projectMutations {\n savedViewMutations {\n updateView(input: $input) {\n id\n name\n description\n }\n }\n }\n }\n": types.UpdatePresentationSlideDocument,
"\n query PresentationAccessCheck($savedViewGroupId: ID!, $projectId: String!) {\n project(id: $projectId) {\n id\n savedViewGroup(id: $savedViewGroupId) {\n id\n }\n }\n }\n": types.PresentationAccessCheckDocument,
"\n query ProjectPresentationPage(\n $input: SavedViewGroupViewsInput!\n $savedViewGroupId: ID!\n $projectId: String!\n ) {\n project(id: $projectId) {\n id\n limitedWorkspace {\n id\n ...PresentationLeftSidebar_LimitedWorkspace\n }\n savedViewGroup(id: $savedViewGroupId) {\n id\n title\n ...PresentationViewerPageWrapper_SavedViewGroup\n ...PresentationHeader_SavedViewGroup\n ...PresentationSlideList_SavedViewGroup\n ...PresentationPageWrapper_SavedViewGroup\n views(input: $input) {\n totalCount\n items {\n id\n name\n description\n screenshot\n projectId\n visibility\n ...PresentationInfoSidebar_SavedView\n group {\n id\n }\n }\n }\n }\n }\n }\n": types.ProjectPresentationPageDocument,
"\n query ProjectPresentationPage(\n $input: SavedViewGroupViewsInput!\n $savedViewGroupId: ID!\n $projectId: String!\n ) {\n project(id: $projectId) {\n id\n limitedWorkspace {\n id\n ...PresentationLeftSidebar_LimitedWorkspace\n ...PresentationLoading_LimitedWorkspace\n }\n savedViewGroup(id: $savedViewGroupId) {\n id\n title\n ...PresentationViewerPageWrapper_SavedViewGroup\n ...PresentationHeader_SavedViewGroup\n ...PresentationSlideList_SavedViewGroup\n ...PresentationPageWrapper_SavedViewGroup\n ...PresentationLoading_SavedViewGroup\n views(input: $input) {\n totalCount\n items {\n id\n name\n description\n screenshot\n projectId\n visibility\n ...PresentationInfoSidebar_SavedView\n group {\n id\n }\n }\n }\n }\n }\n }\n": types.ProjectPresentationPageDocument,
"\n fragment UseCopyModelLink_Model on Model {\n id\n projectId\n ...GetModelItemRoute_Model\n }\n": types.UseCopyModelLink_ModelFragmentDoc,
"\n fragment UseCanCreatePersonalProject_User on User {\n permissions {\n canCreatePersonalProject {\n ...FullPermissionCheckResult\n }\n }\n }\n": types.UseCanCreatePersonalProject_UserFragmentDoc,
"\n fragment UseCanCreateWorkspace_User on User {\n permissions {\n canCreateWorkspace {\n ...FullPermissionCheckResult\n }\n }\n }\n": types.UseCanCreateWorkspace_UserFragmentDoc,
@@ -1328,6 +1330,10 @@ export function graphql(source: "\n fragment PresentationInfoSidebar_SavedView
* 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 PresentationLeftSidebar_LimitedWorkspace on LimitedWorkspace {\n id\n name\n logo\n slug\n }\n"): (typeof documents)["\n fragment PresentationLeftSidebar_LimitedWorkspace on LimitedWorkspace {\n id\n name\n logo\n slug\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 PresentationLoading_SavedViewGroup on SavedViewGroup {\n id\n title\n views(input: $input) {\n items {\n id\n screenshot\n }\n }\n }\n\n fragment PresentationLoading_LimitedWorkspace on LimitedWorkspace {\n id\n name\n logo\n }\n"): (typeof documents)["\n fragment PresentationLoading_SavedViewGroup on SavedViewGroup {\n id\n title\n views(input: $input) {\n items {\n id\n screenshot\n }\n }\n }\n\n fragment PresentationLoading_LimitedWorkspace on LimitedWorkspace {\n id\n name\n logo\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
@@ -2235,7 +2241,7 @@ export function graphql(source: "\n query PresentationAccessCheck($savedViewGro
/**
* 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 ProjectPresentationPage(\n $input: SavedViewGroupViewsInput!\n $savedViewGroupId: ID!\n $projectId: String!\n ) {\n project(id: $projectId) {\n id\n limitedWorkspace {\n id\n ...PresentationLeftSidebar_LimitedWorkspace\n }\n savedViewGroup(id: $savedViewGroupId) {\n id\n title\n ...PresentationViewerPageWrapper_SavedViewGroup\n ...PresentationHeader_SavedViewGroup\n ...PresentationSlideList_SavedViewGroup\n ...PresentationPageWrapper_SavedViewGroup\n views(input: $input) {\n totalCount\n items {\n id\n name\n description\n screenshot\n projectId\n visibility\n ...PresentationInfoSidebar_SavedView\n group {\n id\n }\n }\n }\n }\n }\n }\n"): (typeof documents)["\n query ProjectPresentationPage(\n $input: SavedViewGroupViewsInput!\n $savedViewGroupId: ID!\n $projectId: String!\n ) {\n project(id: $projectId) {\n id\n limitedWorkspace {\n id\n ...PresentationLeftSidebar_LimitedWorkspace\n }\n savedViewGroup(id: $savedViewGroupId) {\n id\n title\n ...PresentationViewerPageWrapper_SavedViewGroup\n ...PresentationHeader_SavedViewGroup\n ...PresentationSlideList_SavedViewGroup\n ...PresentationPageWrapper_SavedViewGroup\n views(input: $input) {\n totalCount\n items {\n id\n name\n description\n screenshot\n projectId\n visibility\n ...PresentationInfoSidebar_SavedView\n group {\n id\n }\n }\n }\n }\n }\n }\n"];
export function graphql(source: "\n query ProjectPresentationPage(\n $input: SavedViewGroupViewsInput!\n $savedViewGroupId: ID!\n $projectId: String!\n ) {\n project(id: $projectId) {\n id\n limitedWorkspace {\n id\n ...PresentationLeftSidebar_LimitedWorkspace\n ...PresentationLoading_LimitedWorkspace\n }\n savedViewGroup(id: $savedViewGroupId) {\n id\n title\n ...PresentationViewerPageWrapper_SavedViewGroup\n ...PresentationHeader_SavedViewGroup\n ...PresentationSlideList_SavedViewGroup\n ...PresentationPageWrapper_SavedViewGroup\n ...PresentationLoading_SavedViewGroup\n views(input: $input) {\n totalCount\n items {\n id\n name\n description\n screenshot\n projectId\n visibility\n ...PresentationInfoSidebar_SavedView\n group {\n id\n }\n }\n }\n }\n }\n }\n"): (typeof documents)["\n query ProjectPresentationPage(\n $input: SavedViewGroupViewsInput!\n $savedViewGroupId: ID!\n $projectId: String!\n ) {\n project(id: $projectId) {\n id\n limitedWorkspace {\n id\n ...PresentationLeftSidebar_LimitedWorkspace\n ...PresentationLoading_LimitedWorkspace\n }\n savedViewGroup(id: $savedViewGroupId) {\n id\n title\n ...PresentationViewerPageWrapper_SavedViewGroup\n ...PresentationHeader_SavedViewGroup\n ...PresentationSlideList_SavedViewGroup\n ...PresentationPageWrapper_SavedViewGroup\n ...PresentationLoading_SavedViewGroup\n views(input: $input) {\n totalCount\n items {\n id\n name\n description\n screenshot\n projectId\n visibility\n ...PresentationInfoSidebar_SavedView\n group {\n id\n }\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
@@ -22,6 +22,7 @@ export const projectPresentationPageQuery = graphql(`
limitedWorkspace {
id
...PresentationLeftSidebar_LimitedWorkspace
...PresentationLoading_LimitedWorkspace
}
savedViewGroup(id: $savedViewGroupId) {
id
@@ -30,6 +31,7 @@ export const projectPresentationPageQuery = graphql(`
...PresentationHeader_SavedViewGroup
...PresentationSlideList_SavedViewGroup
...PresentationPageWrapper_SavedViewGroup
...PresentationLoading_SavedViewGroup
views(input: $input) {
totalCount
items {