Merge branch 'main' into andrew/move-project-to-workspace-improvements

This commit is contained in:
andrewwallacespeckle
2025-04-14 09:31:22 +01:00
14 changed files with 39 additions and 65 deletions
@@ -49,7 +49,6 @@ import { loginRoute } from '~~/lib/common/helpers/route'
import type { Optional } from '@speckle/shared'
const isWorkspacesEnabled = useIsWorkspacesEnabled()
const isWorkspaceNewPlansEnabled = useWorkspaceNewPlansEnabled()
const { activeUser, isLoggedIn } = useActiveUser()
const route = useRoute()
const router = useRouter()
@@ -66,7 +65,6 @@ const loginUrl = computed(() =>
)
const showWorkspaceSwitcher = computed(
() =>
isWorkspacesEnabled.value && isWorkspaceNewPlansEnabled.value && activeUser.value
() => isWorkspacesEnabled.value && activeUser.value
)
</script>
@@ -3,10 +3,8 @@
<Portal to="navigation">
<HeaderNavLink
v-if="project.workspace && isWorkspacesEnabled"
:to="
isWorkspaceNewPlansEnabled ? 'Home' : workspaceRoute(project.workspace.slug)
"
:name="project.workspace.name"
:to="workspaceRoute(project.workspace.slug)"
name="Home"
:separator="false"
/>
<HeaderNavLink v-else :to="projectsRoute" name="Projects" :separator="false" />
@@ -57,5 +55,4 @@ const props = defineProps<{
}>()
const isWorkspacesEnabled = useIsWorkspacesEnabled()
const isWorkspaceNewPlansEnabled = useWorkspaceNewPlansEnabled()
</script>
@@ -4,7 +4,7 @@
<template v-if="project.workspace && isWorkspacesEnabled">
<HeaderNavLink
:to="workspaceRoute(project.workspace.slug)"
:name="isWorkspaceNewPlansEnabled ? 'Home' : project.workspace.name"
name="Home"
:separator="false"
/>
</template>
@@ -58,5 +58,4 @@ defineProps<{
}>()
const isWorkspacesEnabled = useIsWorkspacesEnabled()
const isWorkspaceNewPlansEnabled = useWorkspaceNewPlansEnabled()
</script>
@@ -8,10 +8,7 @@
</FormButton>
</div>
<div class="flex flex-col mt-6 gap-y-6">
<div
v-if="isWorkspaceNewPlansEnabled && project.workspace"
class="flex flex-col gap-y-3"
>
<div v-if="project.workspace" class="flex flex-col gap-y-3">
<p class="text-body-2xs text-foreground-2 font-medium">General access</p>
<ProjectPageCollaboratorsGeneralAccessRow
:name="project.workspace?.name"
@@ -91,7 +88,6 @@ const projectPageCollaboratorsQuery = graphql(`
const projectId = computed(() => route.params.id as string)
const route = useRoute()
const isWorkspaceNewPlansEnabled = useWorkspaceNewPlansEnabled()
const apollo = useApolloClient().client
const mixpanel = useMixpanel()
const cancelInvite = useCancelProjectInvite()
@@ -107,7 +107,6 @@ const openNewProject = ref(false)
const showLoadingBar = ref(false)
const areQueriesLoading = useQueryLoading()
const isWorkspacesEnabled = useIsWorkspacesEnabled()
const isWorkspaceNewPlansEnabled = useWorkspaceNewPlansEnabled()
useUserProjectsUpdatedTracking()
const {
@@ -131,7 +130,7 @@ const {
: selectedRoles.value?.length
? selectedRoles.value
: null,
personalOnly: isWorkspaceNewPlansEnabled.value
personalOnly: isWorkspacesEnabled.value
},
cursor: null as Nullable<string>
}))
@@ -20,7 +20,10 @@
Updated
{{ updatedAt.relative }}
</span>
<span class="text-body-3xs capitalize mb-2 text-foreground-2 select-none">
<span
v-if="project.role"
class="text-body-3xs capitalize mb-2 text-foreground-2 select-none"
>
{{ RoleInfo.Stream[project.role as StreamRoles].title }}
</span>
<UserAvatarGroup :users="teamUsers" :max-count="2" />
@@ -8,7 +8,7 @@
<template v-if="project?.workspace && isWorkspacesEnabled">
<HeaderNavLink
:to="workspaceRoute(project?.workspace.slug)"
:name="isWorkspaceNewPlansEnabled ? 'Home' : project?.workspace.name"
name="Home"
:separator="false"
/>
</template>
@@ -161,7 +161,6 @@ const projectId = writableAsyncComputed({
asyncRead: false
})
const isWorkspaceNewPlansEnabled = useWorkspaceNewPlansEnabled()
const state = useSetupViewer({
projectId
})
@@ -60,7 +60,6 @@ defineProps<{
const { currentStep, resetWizardState } = useWorkspacesWizard()
const mixpanel = useMixpanel()
const { logout } = useAuthManager()
const isWorkspaceNewPlansEnabled = useWorkspaceNewPlansEnabled()
const isWorkspacesEnabled = useIsWorkspacesEnabled()
const { result } = useQuery(activeUserWorkspaceExistenceCheckQuery)
@@ -72,7 +71,6 @@ const isFirstStep = computed(() => currentStep.value === WizardSteps.Details)
const requiresWorkspaceCreation = computed(() => {
return (
isWorkspacesEnabled.value &&
isWorkspaceNewPlansEnabled.value &&
(result.value?.activeUser?.workspaces?.totalCount || 0) === 0 &&
// Legacy projects
(result.value?.activeUser?.versions.totalCount || 0) === 0
@@ -14,7 +14,7 @@
<Portal v-if="workspace?.name" to="navigation">
<HeaderNavLink
:to="workspaceRoute(workspaceSlug)"
:name="isWorkspaceNewPlansEnabled ? 'Home' : workspace?.name"
name="Home"
:separator="false"
/>
</Portal>
@@ -148,7 +148,6 @@ const {
} = useDebouncedTextInput({
debouncedBy: 800
})
const isWorkspaceNewPlansEnabled = useWorkspaceNewPlansEnabled()
const showMoveProjectsDialog = ref(false)
const selectedRoles = ref(undefined as Optional<StreamRoles[]>)
@@ -4,41 +4,19 @@
<BillingAlert :workspace="workspaceInfo" :actions="billingAlertAction" />
</div>
<div class="flex items-center justify-between gap-4">
<div class="flex items-center gap-3 lg:gap-4">
<template v-if="isWorkspaceNewPlansEnabled">
<h1 class="text-heading-sm md:text-heading line-clamp-2">
Hello, {{ activeUser?.name }}
</h1>
</template>
<template v-else>
<WorkspaceAvatar
v-tippy="workspaceInfo.logo ? undefined : 'Add a workspace icon'"
:name="workspaceInfo.name"
:logo="workspaceInfo.logo"
size="lg"
class="hidden md:block"
:class="{ 'cursor-pointer': !workspaceInfo.logo }"
is-button
@click="
workspaceInfo.logo
? undefined
: navigateTo(settingsWorkspaceRoutes.general.route(workspaceInfo.slug))
"
/>
<WorkspaceAvatar
class="md:hidden"
:name="workspaceInfo.name"
:logo="workspaceInfo.logo"
/>
<h1 class="text-heading-sm md:text-heading line-clamp-2">
{{ workspaceInfo.name }}
</h1>
<CommonBadge rounded color-classes="bg-highlight-3 text-foreground-2">
<span class="capitalize">
{{ workspaceInfo.role?.split(':').reverse()[0] }}
</span>
</CommonBadge>
</template>
<div class="flex items-center gap-x-2">
<h1 class="text-heading-sm md:text-heading line-clamp-2">
Hello, {{ activeUser?.name }}
</h1>
<CommonBadge
v-if="!isWorkspaceMember"
rounded
color-classes="bg-highlight-3 text-foreground-2"
>
<span class="capitalize">
{{ workspaceInfo.role?.split(':').reverse()[0] }}
</span>
</CommonBadge>
</div>
<div class="flex gap-1.5 md:gap-2">
@@ -113,7 +91,6 @@ const props = defineProps<{
workspaceInfo: WorkspaceHeader_WorkspaceFragment
}>()
const isWorkspaceNewPlansEnabled = useWorkspaceNewPlansEnabled()
const { activeUser } = useActiveUser()
const isWorkspaceAdmin = computed(
@@ -122,6 +99,9 @@ const isWorkspaceAdmin = computed(
const isWorkspaceGuest = computed(
() => props.workspaceInfo.role === Roles.Workspace.Guest
)
const isWorkspaceMember = computed(
() => props.workspaceInfo.role === Roles.Workspace.Member
)
const canCreateProject = computed(
() => props.workspaceInfo.permissions.canCreateProject
@@ -94,10 +94,9 @@ export default defineNuxtRouteMiddleware(async (to) => {
// 3. Workspace join/create redirect
// Everything past this point is only relevant for workspace enabled instances
const isWorkspaceNewPlansEnabled = useWorkspaceNewPlansEnabled()
const isWorkspacesEnabled = useIsWorkspacesEnabled()
if (!isWorkspacesEnabled.value || !isWorkspaceNewPlansEnabled.value) return
if (!isWorkspacesEnabled.value) return
const { data: workspaceExistenceData } = await client
.query({
@@ -353,6 +353,8 @@ export const upgradeWorkspaceSubscriptionFactoryNew =
default:
throwUncoveredError(billingInterval)
}
// must update the billing interval to the new one
workspaceSubscription.billingInterval = billingInterval
const subscriptionData: SubscriptionDataInput = cloneDeep(
workspaceSubscription.subscriptionData
@@ -76,7 +76,9 @@ export const consumePreviewResultFactory =
jobId: previewResult.jobId,
status: previewResult.status,
durationSeconds: previewResult.result.durationSeconds,
projectId: streamId
projectId: streamId,
streamId, // for legacy reasons
objectId
})
const previewMessage =
+5 -2
View File
@@ -29,8 +29,11 @@ export function throwUncoveredError(e: never): never {
export class UncoveredError extends Error {}
export function createUncoveredError(e: never) {
return new UncoveredError(`Uncovered error case ${e}.`)
export function createUncoveredError(e: unknown) {
let errorRepr = e
if (typeof e === 'object') errorRepr = JSON.stringify(e)
return new UncoveredError(`Uncovered error case ${errorRepr}.`)
}
/**