Files
speckle-server/packages/frontend-2/components/workspace/plan/ProjectModelLimitReachedDialog.vue
T
Kristaps Fabians Geikins a6287fc06d feat(fe2 & server): saved views foundation (list & view) + bits n bobs (#5163)
* init db migration

* WIP store view

* create service call

* WIP insertion

* insert sort of works

* moving code arounmd

* creation tests

* avoid duplicate entries

* fixes from main

* basic group retrieval works

* group filtering works

* WIP view listing

* filter by acl

* fixes + WIP single group retrieval

* wip pivot

* more pivot query fixes

* tests fixed after pivot

* views list tests

* fixing test command

* business plan only checks

* more tests for coverage

* .dts import fix

* cli fix

* anutha one

* auth policy tests for business plan access

* WIP saved views panel base

* BE listing adjustments

* WIP group rendering

* group render done

* WIP post create cache updates

* listing fine?

* my vs theirs

* auto open

* minor fixes

* click load omg

* nicely loading views

* type fix

* less spammy loading

* another type fix:

* more lint fix

* test fix

* codecov disable

* moar coverage

* fix sidebar flashin

* more test coverage

* more test cvoverage

* minor adfjustments

* adj

* saved view wipe fixes

* CSR viewer

* more improvements

* extra feature flag checks

* lint fix

* feature flags fix

* more test fixes
2025-08-05 11:52:50 +03:00

88 lines
2.6 KiB
Vue

<template>
<WorkspacePlanLimitReachedDialog v-model:open="dialogOpen" :buttons="buttons">
<template #header>Plan limit reached</template>
<div class="mb-2">
The workspace
<span class="font-bold">{{ workspaceName }}</span>
is on a {{ formatName(plan) }} plan with a limit of
{{ planConfig?.limits.projectCount }}
{{ planConfig?.limits.projectCount === 1 ? 'project' : 'projects' }} and
{{ planConfig?.limits.modelCount }}
{{ planConfig?.limits.modelCount === 1 ? 'model' : 'models' }}. Upgrade the
workspace to add more.
</div>
</WorkspacePlanLimitReachedDialog>
</template>
<script setup lang="ts">
import {
Roles,
type WorkspacePlans,
WorkspacePlanConfigs,
type MaybeNullOrUndefined
} from '@speckle/shared'
import type { LayoutDialogButton } from '@speckle/ui-components'
import { settingsWorkspaceRoutes } from '~/lib/common/helpers/route'
import { formatName } from '~/lib/billing/helpers/plan'
import { useMixpanel } from '~/lib/core/composables/mp'
import { useFeatureFlags } from '~/lib/common/composables/env'
const props = defineProps<{
workspaceSlug: string
workspaceName?: string
workspaceRole?: MaybeNullOrUndefined<string>
plan?: WorkspacePlans
type?: 'project' | 'model'
location: string
}>()
const dialogOpen = defineModel<boolean>('open', {
required: true
})
const mixpanel = useMixpanel()
const featureFlags = useFeatureFlags()
const planConfig = computed(() => {
if (!props.plan) return null
return WorkspacePlanConfigs({ featureFlags })[props.plan]
})
const explorePlansButton: LayoutDialogButton = {
text: 'Explore plans',
disabled: props.workspaceRole === Roles.Workspace.Guest,
disabledMessage: 'As a Guest you cannot access plans and billing',
onClick: () => {
mixpanel.track('Limit Reached Dialog Upgrade Button Clicked', {
type: props.type,
location: props.location,
// eslint-disable-next-line camelcase
workspace_id: props.workspaceSlug
})
return navigateTo(settingsWorkspaceRoutes.billing.route(props.workspaceSlug))
}
}
const cancelButton: LayoutDialogButton = {
text: 'Cancel',
props: {
color: 'subtle'
},
onClick: () => (dialogOpen.value = false)
}
const buttons = computed((): LayoutDialogButton[] => [cancelButton, explorePlansButton])
watch(dialogOpen, (value) => {
if (value) {
mixpanel.track('Limit Reached Dialog Viewed', {
type: props.type,
location: props.location,
// eslint-disable-next-line camelcase
workspace_id: props.workspaceSlug,
limitType: props.type || 'project/model'
})
}
})
</script>