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
This commit is contained in:
committed by
GitHub
parent
23e9cd31b9
commit
a6287fc06d
@@ -13,8 +13,14 @@ describe('workspacePlanHasAccessToFeature', () => {
|
||||
|
||||
describe.each(allPlans)('should work for %s plan', (plan) => {
|
||||
it.each(allFeatures)('%s feature combination', (feature) => {
|
||||
const expectedResult = WorkspacePlanConfigs[plan].features.includes(feature)
|
||||
const actualResult = workspacePlanHasAccessToFeature({ plan, feature })
|
||||
const expectedResult = WorkspacePlanConfigs({ featureFlags: undefined })[
|
||||
plan
|
||||
].features.includes(feature)
|
||||
const actualResult = workspacePlanHasAccessToFeature({
|
||||
plan,
|
||||
feature,
|
||||
featureFlags: undefined
|
||||
})
|
||||
|
||||
expect(
|
||||
actualResult,
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
WorkspacePlans
|
||||
} from './plans.js'
|
||||
import type { MaybeNullOrUndefined } from '../../core/helpers/utilityTypes.js'
|
||||
import { FeatureFlags } from '../../environment/index.js'
|
||||
|
||||
/**
|
||||
* WORKSPACE FEATURES
|
||||
@@ -22,7 +23,8 @@ export const WorkspacePlanFeatures = <const>{
|
||||
CustomDataRegion: 'workspaceDataRegionSpecificity',
|
||||
HideSpeckleBranding: 'hideSpeckleBranding',
|
||||
ExclusiveMembership: 'exclusiveMembership',
|
||||
EmbedPrivateProjects: 'embedPrivateProjects'
|
||||
EmbedPrivateProjects: 'embedPrivateProjects',
|
||||
SavedViews: 'savedViews'
|
||||
}
|
||||
|
||||
export type WorkspacePlanFeatures =
|
||||
@@ -62,6 +64,10 @@ export const WorkspacePlanFeaturesMetadata = (<const>{
|
||||
[WorkspacePlanFeatures.EmbedPrivateProjects]: {
|
||||
displayName: 'Embed private projects',
|
||||
description: 'Embed projects with visibility set to private or workspace'
|
||||
},
|
||||
[WorkspacePlanFeatures.SavedViews]: {
|
||||
displayName: 'Saved views',
|
||||
description: 'Create and share saved views of your models'
|
||||
}
|
||||
}) satisfies Record<
|
||||
WorkspacePlanFeatures,
|
||||
@@ -100,9 +106,11 @@ const baseFeatures = [
|
||||
WorkspacePlanFeatures.EmbedPrivateProjects
|
||||
] as const
|
||||
|
||||
export const WorkspacePaidPlanConfigs: {
|
||||
export const WorkspacePaidPlanConfigs: (params: {
|
||||
featureFlags: Partial<FeatureFlags> | undefined
|
||||
}) => {
|
||||
[plan in PaidWorkspacePlans]: WorkspacePlanConfig<plan>
|
||||
} = {
|
||||
} = (params) => ({
|
||||
[PaidWorkspacePlans.Team]: {
|
||||
plan: PaidWorkspacePlans.Team,
|
||||
features: [...baseFeatures],
|
||||
@@ -130,7 +138,10 @@ export const WorkspacePaidPlanConfigs: {
|
||||
WorkspacePlanFeatures.DomainSecurity,
|
||||
WorkspacePlanFeatures.SSO,
|
||||
WorkspacePlanFeatures.CustomDataRegion,
|
||||
WorkspacePlanFeatures.HideSpeckleBranding
|
||||
WorkspacePlanFeatures.HideSpeckleBranding,
|
||||
...(params.featureFlags?.FF_SAVED_VIEWS_ENABLED
|
||||
? [WorkspacePlanFeatures.SavedViews]
|
||||
: [])
|
||||
],
|
||||
limits: {
|
||||
projectCount: 10,
|
||||
@@ -146,7 +157,10 @@ export const WorkspacePaidPlanConfigs: {
|
||||
WorkspacePlanFeatures.DomainSecurity,
|
||||
WorkspacePlanFeatures.SSO,
|
||||
WorkspacePlanFeatures.CustomDataRegion,
|
||||
WorkspacePlanFeatures.HideSpeckleBranding
|
||||
WorkspacePlanFeatures.HideSpeckleBranding,
|
||||
...(params.featureFlags?.FF_SAVED_VIEWS_ENABLED
|
||||
? [WorkspacePlanFeatures.SavedViews]
|
||||
: [])
|
||||
],
|
||||
limits: {
|
||||
projectCount: null,
|
||||
@@ -155,11 +169,13 @@ export const WorkspacePaidPlanConfigs: {
|
||||
commentHistory: null
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export const WorkspaceUnpaidPlanConfigs: {
|
||||
export const WorkspaceUnpaidPlanConfigs: (params: {
|
||||
featureFlags: Partial<FeatureFlags> | undefined
|
||||
}) => {
|
||||
[plan in UnpaidWorkspacePlans]: WorkspacePlanConfig<plan>
|
||||
} = {
|
||||
} = (params) => ({
|
||||
[UnpaidWorkspacePlans.Enterprise]: {
|
||||
plan: UnpaidWorkspacePlans.Enterprise,
|
||||
features: [
|
||||
@@ -168,7 +184,10 @@ export const WorkspaceUnpaidPlanConfigs: {
|
||||
WorkspacePlanFeatures.SSO,
|
||||
WorkspacePlanFeatures.CustomDataRegion,
|
||||
WorkspacePlanFeatures.HideSpeckleBranding,
|
||||
WorkspacePlanFeatures.ExclusiveMembership
|
||||
WorkspacePlanFeatures.ExclusiveMembership,
|
||||
...(params.featureFlags?.FF_SAVED_VIEWS_ENABLED
|
||||
? [WorkspacePlanFeatures.SavedViews]
|
||||
: [])
|
||||
],
|
||||
limits: unlimited
|
||||
},
|
||||
@@ -180,7 +199,10 @@ export const WorkspaceUnpaidPlanConfigs: {
|
||||
WorkspacePlanFeatures.SSO,
|
||||
WorkspacePlanFeatures.CustomDataRegion,
|
||||
WorkspacePlanFeatures.HideSpeckleBranding,
|
||||
WorkspacePlanFeatures.ExclusiveMembership
|
||||
WorkspacePlanFeatures.ExclusiveMembership,
|
||||
...(params.featureFlags?.FF_SAVED_VIEWS_ENABLED
|
||||
? [WorkspacePlanFeatures.SavedViews]
|
||||
: [])
|
||||
],
|
||||
limits: unlimited
|
||||
},
|
||||
@@ -191,16 +213,19 @@ export const WorkspaceUnpaidPlanConfigs: {
|
||||
WorkspacePlanFeatures.DomainSecurity,
|
||||
WorkspacePlanFeatures.SSO,
|
||||
WorkspacePlanFeatures.CustomDataRegion,
|
||||
WorkspacePlanFeatures.HideSpeckleBranding
|
||||
WorkspacePlanFeatures.HideSpeckleBranding,
|
||||
...(params.featureFlags?.FF_SAVED_VIEWS_ENABLED
|
||||
? [WorkspacePlanFeatures.SavedViews]
|
||||
: [])
|
||||
],
|
||||
limits: unlimited
|
||||
},
|
||||
[UnpaidWorkspacePlans.TeamUnlimitedInvoiced]: {
|
||||
...WorkspacePaidPlanConfigs.teamUnlimited,
|
||||
...WorkspacePaidPlanConfigs(params).teamUnlimited,
|
||||
plan: UnpaidWorkspacePlans.TeamUnlimitedInvoiced
|
||||
},
|
||||
[UnpaidWorkspacePlans.ProUnlimitedInvoiced]: {
|
||||
...WorkspacePaidPlanConfigs.proUnlimited,
|
||||
...WorkspacePaidPlanConfigs(params).proUnlimited,
|
||||
plan: UnpaidWorkspacePlans.ProUnlimitedInvoiced
|
||||
},
|
||||
[UnpaidWorkspacePlans.Free]: {
|
||||
@@ -213,24 +238,28 @@ export const WorkspaceUnpaidPlanConfigs: {
|
||||
commentHistory: { value: 7, unit: 'day' }
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export const WorkspacePlanConfigs = {
|
||||
...WorkspacePaidPlanConfigs,
|
||||
...WorkspaceUnpaidPlanConfigs
|
||||
}
|
||||
export const WorkspacePlanConfigs = (params: {
|
||||
featureFlags: Partial<FeatureFlags> | undefined
|
||||
}) => ({
|
||||
...WorkspacePaidPlanConfigs(params),
|
||||
...WorkspaceUnpaidPlanConfigs(params)
|
||||
})
|
||||
|
||||
/**
|
||||
* Checks if a workspace exceeds its plan limits for projects and models
|
||||
*/
|
||||
export const workspaceExceedsPlanLimit = (
|
||||
plan: MaybeNullOrUndefined<WorkspacePlans>,
|
||||
projectCount: MaybeNullOrUndefined<number>,
|
||||
export const workspaceExceedsPlanLimit = (params: {
|
||||
plan: MaybeNullOrUndefined<WorkspacePlans>
|
||||
projectCount: MaybeNullOrUndefined<number>
|
||||
modelCount: MaybeNullOrUndefined<number>
|
||||
): boolean => {
|
||||
featureFlags: Partial<FeatureFlags> | undefined
|
||||
}): boolean => {
|
||||
const { plan, projectCount, modelCount, featureFlags } = params
|
||||
if (!plan) return false
|
||||
|
||||
const planConfig = WorkspacePlanConfigs[plan]
|
||||
const planConfig = WorkspacePlanConfigs({ featureFlags })[plan]
|
||||
if (!planConfig) return false
|
||||
|
||||
const limits = planConfig.limits
|
||||
@@ -243,14 +272,16 @@ export const workspaceExceedsPlanLimit = (
|
||||
/**
|
||||
* Checks if a workspace reached its plan limits for projects and models
|
||||
*/
|
||||
export const workspaceReachedPlanLimit = (
|
||||
plan: MaybeNullOrUndefined<WorkspacePlans>,
|
||||
projectCount: MaybeNullOrUndefined<number>,
|
||||
export const workspaceReachedPlanLimit = (params: {
|
||||
plan: MaybeNullOrUndefined<WorkspacePlans>
|
||||
projectCount: MaybeNullOrUndefined<number>
|
||||
modelCount: MaybeNullOrUndefined<number>
|
||||
): boolean => {
|
||||
featureFlags: Partial<FeatureFlags> | undefined
|
||||
}): boolean => {
|
||||
const { plan, projectCount, modelCount, featureFlags } = params
|
||||
if (!plan) return false
|
||||
|
||||
const planConfig = WorkspacePlanConfigs[plan]
|
||||
const planConfig = WorkspacePlanConfigs({ featureFlags })[plan]
|
||||
if (!planConfig) return false
|
||||
|
||||
const limits = planConfig.limits
|
||||
@@ -261,12 +292,14 @@ export const workspaceReachedPlanLimit = (
|
||||
|
||||
export const workspacePlanHasAccessToFeature = ({
|
||||
plan,
|
||||
feature
|
||||
feature,
|
||||
featureFlags
|
||||
}: {
|
||||
plan: WorkspacePlans
|
||||
feature: WorkspacePlanFeatures
|
||||
featureFlags: Partial<FeatureFlags> | undefined
|
||||
}): boolean => {
|
||||
const planConfig = WorkspacePlanConfigs[plan]
|
||||
const planConfig = WorkspacePlanConfigs({ featureFlags })[plan]
|
||||
const hasAccess = planConfig.features.includes(feature)
|
||||
return hasAccess
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user