Feat: Add empty state to dashboard (#2667)

This commit is contained in:
Mike
2024-08-19 09:07:05 +02:00
committed by GitHub
parent 1803e0e46c
commit 17992cd882
3 changed files with 32 additions and 9 deletions
@@ -94,8 +94,8 @@ const documents = {
"\n fragment UserProfileEditDialogBio_User on User {\n id\n name\n company\n bio\n ...UserProfileEditDialogAvatar_User\n }\n": types.UserProfileEditDialogBio_UserFragmentDoc,
"\n fragment UserProfileEditDialogAvatar_User on User {\n id\n avatar\n ...ActiveUserAvatar\n }\n": types.UserProfileEditDialogAvatar_UserFragmentDoc,
"\n fragment SettingsWorkspacesGeneral_Workspace on Workspace {\n ...SettingsWorkspaceGeneralDeleteDialog_Workspace\n id\n name\n logo\n description\n }\n": types.SettingsWorkspacesGeneral_WorkspaceFragmentDoc,
"\n fragment SettingsWorkspaceGeneralDeleteDialog_Workspace on Workspace {\n id\n name\n }\n": types.SettingsWorkspaceGeneralDeleteDialog_WorkspaceFragmentDoc,
"\n fragment SettingsWorkspacesMembers_Workspace on Workspace {\n id\n role\n }\n": types.SettingsWorkspacesMembers_WorkspaceFragmentDoc,
"\n fragment SettingsWorkspaceGeneralDeleteDialog_Workspace on Workspace {\n id\n name\n }\n": types.SettingsWorkspaceGeneralDeleteDialog_WorkspaceFragmentDoc,
"\n fragment SettingsWorkspacesMembersInvitesTable_PendingWorkspaceCollaborator on PendingWorkspaceCollaborator {\n id\n role\n title\n updatedAt\n user {\n id\n ...LimitedUserAvatar\n }\n invitedBy {\n id\n ...LimitedUserAvatar\n }\n }\n": types.SettingsWorkspacesMembersInvitesTable_PendingWorkspaceCollaboratorFragmentDoc,
"\n fragment SettingsWorkspacesMembersInvitesTable_Workspace on Workspace {\n id\n ...SettingsWorkspacesMembersTableHeader_Workspace\n invitedTeam(filter: $invitesFilter) {\n ...SettingsWorkspacesMembersInvitesTable_PendingWorkspaceCollaborator\n }\n }\n": types.SettingsWorkspacesMembersInvitesTable_WorkspaceFragmentDoc,
"\n fragment SettingsWorkspacesMembersMembersTable_WorkspaceCollaborator on WorkspaceCollaborator {\n id\n role\n user {\n id\n avatar\n name\n company\n verified\n }\n }\n": types.SettingsWorkspacesMembersMembersTable_WorkspaceCollaboratorFragmentDoc,
@@ -616,11 +616,11 @@ export function graphql(source: "\n fragment SettingsWorkspacesGeneral_Workspac
/**
* 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 SettingsWorkspaceGeneralDeleteDialog_Workspace on Workspace {\n id\n name\n }\n"): (typeof documents)["\n fragment SettingsWorkspaceGeneralDeleteDialog_Workspace on Workspace {\n id\n name\n }\n"];
export function graphql(source: "\n fragment SettingsWorkspacesMembers_Workspace on Workspace {\n id\n role\n }\n"): (typeof documents)["\n fragment SettingsWorkspacesMembers_Workspace on Workspace {\n id\n role\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 SettingsWorkspacesMembers_Workspace on Workspace {\n id\n role\n }\n"): (typeof documents)["\n fragment SettingsWorkspacesMembers_Workspace on Workspace {\n id\n role\n }\n"];
export function graphql(source: "\n fragment SettingsWorkspaceGeneralDeleteDialog_Workspace on Workspace {\n id\n name\n }\n"): (typeof documents)["\n fragment SettingsWorkspaceGeneralDeleteDialog_Workspace on Workspace {\n id\n name\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
@@ -4176,10 +4176,10 @@ export type UserProfileEditDialogAvatar_UserFragment = { __typename?: 'User', id
export type SettingsWorkspacesGeneral_WorkspaceFragment = { __typename?: 'Workspace', id: string, name: string, logo?: string | null, description?: string | null };
export type SettingsWorkspaceGeneralDeleteDialog_WorkspaceFragment = { __typename?: 'Workspace', id: string, name: string };
export type SettingsWorkspacesMembers_WorkspaceFragment = { __typename?: 'Workspace', id: string, role?: string | null };
export type SettingsWorkspaceGeneralDeleteDialog_WorkspaceFragment = { __typename?: 'Workspace', id: string, name: string };
export type SettingsWorkspacesMembersInvitesTable_PendingWorkspaceCollaboratorFragment = { __typename?: 'PendingWorkspaceCollaborator', id: string, role: string, title: string, updatedAt: string, user?: { __typename?: 'LimitedUser', id: string, name: string, avatar?: string | null } | null, invitedBy: { __typename?: 'LimitedUser', id: string, name: string, avatar?: string | null } };
export type SettingsWorkspacesMembersInvitesTable_WorkspaceFragment = { __typename?: 'Workspace', id: string, invitedTeam?: Array<{ __typename?: 'PendingWorkspaceCollaborator', title: string, id: string, role: string, updatedAt: string, user?: { __typename?: 'LimitedUser', id: string, name: string, avatar?: string | null } | null, invitedBy: { __typename?: 'LimitedUser', id: string, name: string, avatar?: string | null } }> | null, team: Array<{ __typename?: 'WorkspaceCollaborator', id: string, user: { __typename?: 'LimitedUser', id: string } }> };
+27 -4
View File
@@ -15,10 +15,18 @@
<section>
<h2 class="text-heading-sm text-foreground-2">Recently updated projects</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-3 pt-5">
<DashboardProjectCard
v-for="project in projects"
:key="project.id"
:project="project"
<template v-if="hasProjects">
<DashboardProjectCard
v-for="project in projects"
:key="project.id"
:project="project"
/>
</template>
<QuickStartCard
v-else
title="Create your first project"
description="Projects are the place where your models and their versions live."
:buttons="createProjectButton"
/>
</div>
</section>
@@ -32,9 +40,12 @@
/>
</div>
</section>
<ProjectsAddDialog v-model:open="openNewProject" />
</div>
</template>
<script setup lang="ts">
import { type LayoutDialogButton } from '@speckle/ui-components'
import { dashboardProjectsPageQuery } from '~~/lib/dashboard/graphql/queries'
import type { QuickStartItem } from '~~/lib/dashboard/helpers/types'
import { getResizedGhostImage } from '~~/lib/dashboard/helpers/utils'
@@ -45,6 +56,7 @@ import { docsPageUrl, forumPageUrl } from '~~/lib/common/helpers/route'
import type { ManagerExtension } from '~~/lib/common/utils/downloadManager'
import { downloadManager } from '~~/lib/common/utils/downloadManager'
import { ToastNotificationType, useGlobalToast } from '~~/lib/common/composables/toast'
import { useActiveUser } from '~~/lib/auth/composables/activeUser'
useHead({ title: 'Dashboard' })
@@ -56,10 +68,13 @@ const config = useRuntimeConfig()
const mixpanel = useMixpanel()
const { result: projectsResult } = useQuery(dashboardProjectsPageQuery)
const { triggerNotification } = useGlobalToast()
const { isGuest } = useActiveUser()
const { data: tutorials } = await useLazyAsyncData('tutorials', fetchTutorials, {
server: false
})
const openNewProject = ref(false)
const ghostContentApi = new GhostContentAPI({
url: 'https://speckle.systems',
key: config.public.ghostApiKey,
@@ -102,8 +117,16 @@ const quickStartItems = shallowRef<QuickStartItem[]>([
]
}
])
const createProjectButton = shallowRef<LayoutDialogButton[]>([
{
text: 'Create a project',
props: { disabled: isGuest.value },
onClick: () => (openNewProject.value = true)
}
])
const projects = computed(() => projectsResult.value?.activeUser?.projects.items)
const hasProjects = computed(() => (projects.value ? projects.value.length > 0 : false))
async function fetchTutorials() {
const posts = await ghostContentApi.posts.browse({