Loading states

This commit is contained in:
andrewwallacespeckle
2025-04-11 23:31:48 +01:00
parent 81192c001b
commit 801e05c032
2 changed files with 101 additions and 86 deletions
@@ -11,36 +11,41 @@
class="mb-2"
v-on="on"
/>
<div
v-if="hasMoveableProjects"
class="flex flex-col mt-2 border rounded-md border-outline-3"
>
<div
v-for="project in moveableProjects"
:key="project.id"
class="flex px-4 py-3 items-center space-x-2 justify-between border-b last:border-0 border-outline-3"
>
<div class="flex flex-col flex-1 truncate text-body-xs">
<span class="font-medium text-foreground truncate">
{{ project.name }}
</span>
<div class="flex items-center gap-x-1">
<span class="text-foreground-3 truncate">
{{ project.modelCount.totalCount }} model{{
project.modelCount.totalCount !== 1 ? 's' : ''
}}
</span>
</div>
</div>
<FormButton size="sm" color="outline" @click="onMoveClick(project)">
Move...
</FormButton>
</div>
<div v-if="loading" class="py-4 flex items-center justify-center w-full h-32">
<CommonLoadingIcon size="sm" />
</div>
<p v-else class="py-4 text-body-xs text-foreground-2">
You don't have any projects that can be moved into this workspace. Only projects
you own and that aren't in another workspace can be moved.
</p>
<template v-else>
<div
v-if="hasMoveableProjects"
class="flex flex-col mt-2 border rounded-md border-outline-3"
>
<div
v-for="project in moveableProjects"
:key="project.id"
class="flex px-4 py-3 items-center space-x-2 justify-between border-b last:border-0 border-outline-3"
>
<div class="flex flex-col flex-1 truncate text-body-xs">
<span class="font-medium text-foreground truncate">
{{ project.name }}
</span>
<div class="flex items-center gap-x-1">
<span class="text-foreground-3 truncate">
{{ project.modelCount.totalCount }} model{{
project.modelCount.totalCount !== 1 ? 's' : ''
}}
</span>
</div>
</div>
<FormButton size="sm" color="outline" @click="onMoveClick(project)">
Move...
</FormButton>
</div>
</div>
<p v-else class="py-4 text-body-xs text-foreground-2">
You don't have any projects that can be moved into this workspace. Only projects
you own and that aren't in another workspace can be moved.
</p>
</template>
<InfiniteLoading
v-if="moveableProjects?.length && !search?.length"
:settings="{ identifier }"
@@ -52,7 +57,11 @@
<script setup lang="ts">
import { graphql } from '~~/lib/common/generated/gql'
import { FormTextInput, useDebouncedTextInput } from '@speckle/ui-components'
import {
CommonLoadingIcon,
FormTextInput,
useDebouncedTextInput
} from '@speckle/ui-components'
import type { WorkspaceMoveProjectSelectProject_ProjectFragment } from '~~/lib/common/generated/gql/graphql'
import { usePaginatedQuery } from '~/lib/common/composables/graphql'
import { workspaceMoveProjectManagerUserQuery } from '~/lib/workspaces/graphql/queries'
@@ -81,7 +90,7 @@ const emit = defineEmits<{
}>()
const {
query: { result },
query: { result, loading },
identifier,
onInfiniteLoad
} = usePaginatedQuery({
@@ -1,65 +1,70 @@
<template>
<div>
<div class="flex flex-col space-y-4">
<div v-if="hasWorkspaces">
<p class="mb-4">Select an existing workspaces or create a new one.</p>
<div class="flex flex-col gap-2">
<div
v-for="ws in workspaces"
:key="`${ws.id}-${ws.permissions?.canMoveProjectToWorkspace?.code}`"
v-tippy="disabledTooltipText(ws)"
>
<button
class="w-full"
:class="
!canMoveToWorkspace(ws) && !isLimitReached(ws)
? 'cursor-not-allowed'
: ''
"
:disabled="!canMoveToWorkspace(ws) && !isLimitReached(ws)"
@click="handleWorkspaceClick(ws)"
<div v-if="loading" class="py-4 flex items-center justify-center w-full h-32">
<CommonLoadingIcon size="sm" />
</div>
<template v-else>
<div v-if="hasWorkspaces">
<p class="mb-4">Select an existing workspaces or create a new one.</p>
<div class="flex flex-col gap-2">
<div
v-for="ws in workspaces"
:key="`${ws.id}-${ws.permissions?.canMoveProjectToWorkspace?.code}`"
v-tippy="disabledTooltipText(ws)"
>
<WorkspaceCard
:logo="ws.logo ?? ''"
:name="ws.name"
:clickable="canMoveToWorkspace(ws) || isLimitReached(ws)"
<button
class="w-full"
:class="
!canMoveToWorkspace(ws) && !isLimitReached(ws)
? 'cursor-not-allowed'
: ''
"
:disabled="!canMoveToWorkspace(ws) && !isLimitReached(ws)"
@click="handleWorkspaceClick(ws)"
>
<template #text>
<div class="flex flex-col gap-2 items-start">
<CommonBadge
v-if="isSsoRequired(ws)"
color="secondary"
class="capitalize"
rounded
>
SSO login required
<WorkspaceCard
:logo="ws.logo ?? ''"
:name="ws.name"
:clickable="canMoveToWorkspace(ws) || isLimitReached(ws)"
>
<template #text>
<div class="flex flex-col gap-2 items-start">
<CommonBadge
v-if="isSsoRequired(ws)"
color="secondary"
class="capitalize"
rounded
>
SSO login required
</CommonBadge>
<p>
{{ ws.projects.totalCount }} projects,
{{ ws.projects.totalCount }} models
</p>
<UserAvatarGroup
:users="ws.team.items.map((t) => t.user)"
:max-count="6"
size="sm"
/>
</div>
</template>
<template #actions>
<CommonBadge color="secondary" rounded>
{{ formatName(ws.plan?.name) }}
</CommonBadge>
<p>
{{ ws.projects.totalCount }} projects,
{{ ws.projects.totalCount }} models
</p>
<UserAvatarGroup
:users="ws.team.items.map((t) => t.user)"
:max-count="6"
size="sm"
/>
</div>
</template>
<template #actions>
<CommonBadge color="secondary" class="capitalize" rounded>
{{ ws.plan?.name }}
</CommonBadge>
</template>
</WorkspaceCard>
</button>
</template>
</WorkspaceCard>
</button>
</div>
</div>
</div>
</div>
<p v-else class="text-body-xs text-foreground">
Looks like you haven't created any workspaces yet. Workspaces help you easily
organise and control your digital projects. Create one to move your project
into.
</p>
<p v-else class="text-body-xs text-foreground">
Looks like you haven't created any workspaces yet. Workspaces help you easily
organise and control your digital projects. Create one to move your project
into.
</p>
</template>
</div>
<WorkspacePlanLimitReachedDialog
@@ -83,6 +88,7 @@ import type {
import { useQuery } from '@vue/apollo-composable'
import { UserAvatarGroup } from '@speckle/ui-components'
import { workspaceMoveProjectManagerUserQuery } from '~/lib/workspaces/graphql/queries'
import { formatName } from '~/lib/billing/helpers/plan'
graphql(`
fragment WorkspaceMoveProjectSelectWorkspace_User on User {
@@ -144,7 +150,7 @@ const emit = defineEmits<{
): void
}>()
const { result } = useQuery(workspaceMoveProjectManagerUserQuery, () => ({
const { result, loading } = useQuery(workspaceMoveProjectManagerUserQuery, () => ({
cursor: null,
filter: {},
projectId: props.project.id