mirror of
https://github.com/nocodb/nocodb.git
synced 2026-04-28 13:15:55 +00:00
151 lines
4.1 KiB
TypeScript
151 lines
4.1 KiB
TypeScript
import { useStorage } from '@vueuse/core'
|
|
import { isEeUI } from '#imports'
|
|
|
|
export interface WorkspaceSettings {
|
|
data: {
|
|
showOtherUserPersonalViews?: boolean
|
|
// any other ws level keys we can store here
|
|
[key: string]: any
|
|
}
|
|
lastAccessed: number // TTL and tracking
|
|
}
|
|
|
|
export interface UserLocalStorageInfo {
|
|
[userId: string]: {
|
|
[workspaceId: string]: WorkspaceSettings
|
|
}
|
|
}
|
|
|
|
export class UserLocalStorageInfoManager {
|
|
private storage: Ref<UserLocalStorageInfo>
|
|
private readonly TTL = 180 * 24 * 60 * 60 * 1000 // 180 days
|
|
private readonly defaultData: WorkspaceSettings['data'] = {
|
|
showOtherUserPersonalViews: true,
|
|
}
|
|
|
|
constructor() {
|
|
this.storage = useStorage<UserLocalStorageInfo>('nc-user-local-storage-info', {})
|
|
this.cleanExpired()
|
|
}
|
|
|
|
/** Cleanup expired workspace settings */
|
|
private cleanExpired(): void {
|
|
if (!isEeUI) return
|
|
|
|
const now = Date.now()
|
|
const data = this.storage.value
|
|
|
|
Object.keys(data).forEach((userId) => {
|
|
const workspaces = data[userId]
|
|
if (!workspaces) return
|
|
|
|
Object.keys(workspaces).forEach((wsId) => {
|
|
if (now - workspaces[wsId]!.lastAccessed > this.TTL) {
|
|
delete workspaces[wsId]
|
|
}
|
|
})
|
|
|
|
// remove user entirely if no workspaces left
|
|
if (Object.keys(workspaces).length === 0) {
|
|
delete data[userId]
|
|
}
|
|
})
|
|
}
|
|
|
|
/** Cleanup local storage workspaces that no longer exist */
|
|
cleanMissingWorkspaces(userId: string, workspaceIds: string[]): void {
|
|
if (!isEeUI) return
|
|
|
|
const userWorkspaces = this.storage.value[userId]
|
|
if (!userWorkspaces) return
|
|
|
|
Object.keys(userWorkspaces).forEach((wsId) => {
|
|
if (!workspaceIds.includes(wsId)) {
|
|
delete userWorkspaces[wsId]
|
|
} else {
|
|
this.touch(userId, wsId)
|
|
}
|
|
})
|
|
|
|
// Remove user if no workspace left
|
|
if (Object.keys(userWorkspaces).length === 0) {
|
|
delete this.storage.value[userId]
|
|
}
|
|
}
|
|
|
|
/** Ensure workspace exists for user */
|
|
private ensureWorkspace(userId: string, workspaceId: string): void {
|
|
if (!isEeUI) return
|
|
|
|
if (!userId || !workspaceId) return
|
|
|
|
if (!this.storage.value[userId]) this.storage.value[userId] = {}
|
|
|
|
if (!this.storage.value[userId][workspaceId]) {
|
|
this.storage.value[userId][workspaceId] = {
|
|
data: {},
|
|
lastAccessed: Date.now(),
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Update lastAccessed timestamp */
|
|
private touch(userId: string, workspaceId: string): void {
|
|
if (!userId || !workspaceId || !isEeUI) return
|
|
|
|
if (this.storage.value[userId]?.[workspaceId]) {
|
|
this.storage.value[userId][workspaceId].lastAccessed = Date.now()
|
|
} else {
|
|
this.storage.value[userId] = {
|
|
...(this.storage.value[userId] || {}),
|
|
[workspaceId]: {
|
|
data: {},
|
|
lastAccessed: Date.now(),
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Get a workspace-level key */
|
|
get(userId: string, workspaceId: string, key: keyof WorkspaceSettings['data'], defaultValue: any = null): any {
|
|
if (!userId || !workspaceId || !isEeUI) return defaultValue
|
|
|
|
this.touch(userId, workspaceId)
|
|
|
|
if (defaultValue !== null && ncIsUndefined(this.storage.value[userId]![workspaceId]!.data[key])) {
|
|
this.storage.value[userId]![workspaceId]!.data[key] = defaultValue
|
|
}
|
|
|
|
return this.storage.value[userId]![workspaceId]!.data[key]
|
|
}
|
|
|
|
/** Set a workspace-level key */
|
|
set(userId: string, workspaceId: string, key: string, value: any): void {
|
|
if (!userId || !workspaceId || !key || !isEeUI) return
|
|
|
|
this.ensureWorkspace(userId, workspaceId)
|
|
this.storage.value[userId]![workspaceId]!.data[key] = value
|
|
this.touch(userId, workspaceId)
|
|
}
|
|
|
|
/** Clear workspace for user */
|
|
clearWorkspace(userId: string, workspaceId: string): void {
|
|
if (!userId || !workspaceId || !isEeUI) return
|
|
|
|
if (this.storage.value[userId]?.[workspaceId]) {
|
|
delete this.storage.value[userId][workspaceId]
|
|
}
|
|
}
|
|
|
|
/** Clear all data for a user */
|
|
clearUser(userId: string): void {
|
|
if (!userId || !isEeUI) return
|
|
|
|
if (this.storage.value[userId]) {
|
|
delete this.storage.value[userId]
|
|
}
|
|
}
|
|
}
|
|
|
|
export const userLocalStorageInfoManager = new UserLocalStorageInfoManager()
|