Files
speckle-server/packages/server/modules/viewer/helpers/savedViews.ts
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

72 lines
2.0 KiB
TypeScript

import { base64Decode, base64Encode } from '@/modules/shared/helpers/cryptoHelper'
import type { Nullable } from '@speckle/shared'
import {
isModelResource,
isObjectResource,
resourceBuilder
} from '@speckle/shared/viewer/route'
import { isObjectLike } from 'lodash-es'
export type DefaultGroupMetadata = {
resourceIds: string[]
projectId: string
name: 'Default Group'
}
export const buildDefaultGroupId = (params: {
resourceIds: string[]
projectId: string
}) => {
const payload: DefaultGroupMetadata = {
resourceIds: formatResourceIdsForGroup(params.resourceIds),
projectId: params.projectId,
name: 'Default Group'
}
const str = JSON.stringify(payload)
return 'default-' + base64Encode(str)
}
export const decodeDefaultGroupId = (id: string): Nullable<DefaultGroupMetadata> => {
try {
if (!id.startsWith('default-')) return null
const json = base64Decode(id.replace('default-', ''))
const obj = JSON.parse(json)
if (
!isObjectLike(obj) ||
!obj.resourceIds ||
!obj.projectId ||
obj.name !== 'Default Group'
) {
throw new Error('Invalid saved view group ID format')
}
return obj as Nullable<DefaultGroupMetadata>
} catch {
// Suppress - not the default group ID
return null
}
}
/**
* Converts a resourceId string into a more abstract format used by groups that disregards
* specific versions of models and objects.
*/
export const formatResourceIdsForGroup = (resourceIdString: string | string[]) => {
resourceIdString = Array.isArray(resourceIdString)
? resourceIdString.join(',')
: resourceIdString
return resourceBuilder()
.addFromString(resourceIdString)
.forEach((r) => {
if (isModelResource(r)) {
// not interested in the specific version ids originally used
r.versionId = undefined
}
})
.filter((r) => {
// filter out any resources that are not ViewerModelResource or ViewerObjectResource
return isModelResource(r) || isObjectResource(r)
})
.map((r) => r.toString())
}