a6287fc06d
* 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
88 lines
2.6 KiB
Vue
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>
|