mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-14 21:27:20 +00:00
refactor: workspace crud
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { Workspaces } from './workspaces';
|
||||
import type { WorkspacesChangeEvent } from './workspaces';
|
||||
import { Workspace } from '@blocksuite/store';
|
||||
import { BaseProvider } from './provider/base';
|
||||
import { LocalProvider } from './provider/local/local';
|
||||
@@ -14,9 +15,10 @@ import { applyUpdate, encodeStateAsUpdate } from 'yjs';
|
||||
* @classdesc DataCenter is a data center, it can manage different providers for business
|
||||
*/
|
||||
export class DataCenter {
|
||||
private readonly workspaces = new Workspaces(this);
|
||||
private readonly _workspaces = new Workspaces();
|
||||
private currentWorkspace: Workspace | null = null;
|
||||
private readonly _logger = getLogger('dc');
|
||||
private _defaultProvider?: BaseProvider;
|
||||
providerMap: Map<string, BaseProvider> = new Map();
|
||||
|
||||
constructor(debug: boolean) {
|
||||
@@ -28,32 +30,43 @@ export class DataCenter {
|
||||
// TODO: switch different provider
|
||||
dc.registerProvider(new LocalProvider());
|
||||
dc.registerProvider(new AffineProvider());
|
||||
dc.workspaces.init();
|
||||
|
||||
return dc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register provider.
|
||||
* We will automatically set the first provider to default provider.
|
||||
*/
|
||||
registerProvider(provider: BaseProvider) {
|
||||
if (!this._defaultProvider) {
|
||||
this._defaultProvider = provider;
|
||||
}
|
||||
// inject data in provider
|
||||
provider.inject({ logger: this._logger, workspaces: this.workspaces });
|
||||
provider.inject({
|
||||
logger: this._logger,
|
||||
workspaces: this._workspaces.createScope(),
|
||||
});
|
||||
provider.init();
|
||||
this.providerMap.set(provider.id, provider);
|
||||
}
|
||||
|
||||
setDefaultProvider(providerId: string) {
|
||||
this._defaultProvider = this.providerMap.get(providerId);
|
||||
}
|
||||
|
||||
get providers() {
|
||||
return Array.from(this.providerMap.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* get workspaces list if focusUpdate is true, it will refresh workspaces
|
||||
* @param {string} name workspace name
|
||||
* @returns {Promise<WS[]>}
|
||||
*/
|
||||
public async getWorkspaces(focusUpdate = false) {
|
||||
if (focusUpdate) {
|
||||
this.workspaces.refreshWorkspaces();
|
||||
}
|
||||
return this.workspaces.workspaces;
|
||||
public get workspaces() {
|
||||
return this._workspaces.workspaces;
|
||||
}
|
||||
|
||||
public async refreshWorkspaces() {
|
||||
return Promise.allSettled(
|
||||
Object.values(this.providerMap).map(provider => provider.loadWorkspaces())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,11 +74,16 @@ export class DataCenter {
|
||||
* @param {string} name workspace name
|
||||
* @returns {Promise<WS>}
|
||||
*/
|
||||
public async createWorkspace(name: string) {
|
||||
const workspaceInfo = this.workspaces.addLocalWorkspace(name);
|
||||
// IMP: create workspace in local provider
|
||||
this.providerMap.get('local')?.createWorkspace({ name });
|
||||
return workspaceInfo;
|
||||
public async createWorkspace(workspaceMeta: WorkspaceMeta) {
|
||||
assert(
|
||||
this._defaultProvider,
|
||||
'There is no provider. You should add provider first.'
|
||||
);
|
||||
|
||||
const workspace = await this._defaultProvider.createWorkspace(
|
||||
workspaceMeta
|
||||
);
|
||||
return workspace;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,14 +91,11 @@ export class DataCenter {
|
||||
* @param {string} workspaceId workspace id
|
||||
*/
|
||||
public async deleteWorkspace(workspaceId: string) {
|
||||
const workspaceInfo = this.workspaces.getWorkspace(workspaceId);
|
||||
const workspaceInfo = this._workspaces.find(workspaceId);
|
||||
assert(workspaceInfo, 'Workspace not found');
|
||||
const provider = this.providerMap.get(workspaceInfo.provider);
|
||||
if (provider && this.workspaces.hasWorkspace(workspaceId)) {
|
||||
await provider.delete(workspaceId);
|
||||
// may be refresh all workspaces
|
||||
this.workspaces.delete(workspaceId);
|
||||
}
|
||||
assert(provider, `Workspace exists, but we couldn't find its provider.`);
|
||||
await provider.deleteWorkspace(workspaceId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,11 +134,11 @@ export class DataCenter {
|
||||
* @returns {Promise<Workspace>}
|
||||
*/
|
||||
public async loadWorkspace(workspaceId: string) {
|
||||
const workspaceInfo = this.workspaces.getWorkspace(workspaceId);
|
||||
const workspaceInfo = this._workspaces.find(workspaceId);
|
||||
assert(workspaceInfo, 'Workspace not found');
|
||||
const currentProvider = this.providerMap.get(workspaceInfo.provider);
|
||||
if (currentProvider) {
|
||||
currentProvider.close(workspaceId);
|
||||
currentProvider.closeWorkspace(workspaceId);
|
||||
}
|
||||
const provider = this.providerMap.get(workspaceInfo.provider);
|
||||
assert(provider, `provide '${workspaceInfo.provider}' is not registered`);
|
||||
@@ -149,8 +164,10 @@ export class DataCenter {
|
||||
* listen workspaces list change
|
||||
* @param {Function} callback callback function
|
||||
*/
|
||||
public async onWorkspacesChange(callback: (workspaces: WS[]) => void) {
|
||||
this.workspaces.onWorkspacesChange(callback);
|
||||
public async onWorkspacesChange(
|
||||
callback: (workspaces: WorkspacesChangeEvent) => void
|
||||
) {
|
||||
this._workspaces.on('change', callback);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -166,20 +183,18 @@ export class DataCenter {
|
||||
assert(w?.room, 'No workspace to set meta');
|
||||
const update: Partial<WorkspaceMeta> = {};
|
||||
if (name) {
|
||||
w.doc.meta.setName(name);
|
||||
w.meta.setName(name);
|
||||
update.name = name;
|
||||
}
|
||||
if (avatar) {
|
||||
w.doc.meta.setAvatar(avatar);
|
||||
w.meta.setAvatar(avatar);
|
||||
update.avatar = avatar;
|
||||
}
|
||||
// may run for change workspace meta
|
||||
const workspaceInfo = this.workspaces.getWorkspace(w.room);
|
||||
const workspaceInfo = this._workspaces.find(w.room);
|
||||
assert(workspaceInfo, 'Workspace not found');
|
||||
const provider = this.providerMap.get(workspaceInfo.provider);
|
||||
provider?.updateWorkspaceMeta(w.room, update);
|
||||
// update workspace list directly
|
||||
this.workspaces.updateWorkspaceInfo(w.room, update);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,27 +203,26 @@ export class DataCenter {
|
||||
* @param id workspace id
|
||||
*/
|
||||
public async leaveWorkspace(workspaceId: string) {
|
||||
const workspaceInfo = this.workspaces.getWorkspace(workspaceId);
|
||||
const workspaceInfo = this._workspaces.find(workspaceId);
|
||||
assert(workspaceInfo, 'Workspace not found');
|
||||
const provider = this.providerMap.get(workspaceInfo.provider);
|
||||
if (provider) {
|
||||
await provider.close(workspaceId);
|
||||
await provider.leave(workspaceId);
|
||||
await provider.closeWorkspace(workspaceId);
|
||||
await provider.leaveWorkspace(workspaceId);
|
||||
}
|
||||
}
|
||||
|
||||
public async setWorkspacePublish(workspaceId: string, isPublish: boolean) {
|
||||
const workspaceInfo = this.workspaces.getWorkspace(workspaceId);
|
||||
const workspaceInfo = this._workspaces.find(workspaceId);
|
||||
assert(workspaceInfo, 'Workspace not found');
|
||||
const provider = this.providerMap.get(workspaceInfo.provider);
|
||||
if (provider) {
|
||||
await provider.publish(workspaceId, isPublish);
|
||||
this.workspaces.updateWorkspaceInfo(workspaceId, { isPublish });
|
||||
}
|
||||
}
|
||||
|
||||
public async inviteMember(id: string, email: string) {
|
||||
const workspaceInfo = this.workspaces.getWorkspace(id);
|
||||
const workspaceInfo = this._workspaces.find(id);
|
||||
assert(workspaceInfo, 'Workspace not found');
|
||||
const provider = this.providerMap.get(workspaceInfo.provider);
|
||||
if (provider) {
|
||||
@@ -221,7 +235,7 @@ export class DataCenter {
|
||||
* @param {number} permissionId permission id
|
||||
*/
|
||||
public async removeMember(workspaceId: string, permissionId: number) {
|
||||
const workspaceInfo = this.workspaces.getWorkspace(workspaceId);
|
||||
const workspaceInfo = this._workspaces.find(workspaceId);
|
||||
assert(workspaceInfo, 'Workspace not found');
|
||||
const provider = this.providerMap.get(workspaceInfo.provider);
|
||||
if (provider) {
|
||||
@@ -235,13 +249,11 @@ export class DataCenter {
|
||||
*/
|
||||
public async closeCurrentWorkspace() {
|
||||
assert(this.currentWorkspace?.room, 'No workspace to close');
|
||||
const currentWorkspace = this.workspaces.getWorkspace(
|
||||
this.currentWorkspace.room
|
||||
);
|
||||
const currentWorkspace = this._workspaces.find(this.currentWorkspace.room);
|
||||
assert(currentWorkspace, 'Workspace not found');
|
||||
const provider = this.providerMap.get(currentWorkspace.provider);
|
||||
assert(provider, 'Provider not found');
|
||||
await provider.close(currentWorkspace.id);
|
||||
await provider.closeWorkspace(currentWorkspace.id);
|
||||
}
|
||||
|
||||
private async _transWorkspaceProvider(
|
||||
@@ -249,7 +261,7 @@ export class DataCenter {
|
||||
providerId: string
|
||||
) {
|
||||
assert(workspace.room, 'No workspace id');
|
||||
const workspaceInfo = this.workspaces.getWorkspace(workspace.room);
|
||||
const workspaceInfo = this._workspaces.find(workspace.room);
|
||||
assert(workspaceInfo, 'Workspace not found');
|
||||
if (workspaceInfo.provider === providerId) {
|
||||
this._logger('Workspace provider is same');
|
||||
@@ -270,8 +282,7 @@ export class DataCenter {
|
||||
);
|
||||
applyUpdate(newWorkspace.doc, encodeStateAsUpdate(workspace.doc));
|
||||
assert(newWorkspace, 'Create workspace failed');
|
||||
await currentProvider.delete(workspace.room);
|
||||
this.workspaces.refreshWorkspaces();
|
||||
await currentProvider.deleteWorkspace(workspace.room);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -119,9 +119,8 @@ export class AffineProvider extends BaseProvider {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
});
|
||||
await (
|
||||
await Promise.all(workspaceInstances)
|
||||
).forEach((workspace, i) => {
|
||||
|
||||
(await Promise.all(workspaceInstances)).forEach((workspace, i) => {
|
||||
if (workspace) {
|
||||
workspaces[i] = {
|
||||
...workspaces[i],
|
||||
@@ -159,6 +158,11 @@ export class AffineProvider extends BaseProvider {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
workspaces.forEach(workspace => {
|
||||
this._workspaces.add(workspace);
|
||||
});
|
||||
|
||||
return workspaces;
|
||||
}
|
||||
|
||||
@@ -185,17 +189,19 @@ export class AffineProvider extends BaseProvider {
|
||||
return this._user;
|
||||
}
|
||||
|
||||
public override async delete(id: string): Promise<void> {
|
||||
await this.close(id);
|
||||
public override async deleteWorkspace(id: string): Promise<void> {
|
||||
await this.closeWorkspace(id);
|
||||
IndexedDBProvider.delete(id);
|
||||
await deleteWorkspace({ id });
|
||||
this._workspaces.remove(id);
|
||||
}
|
||||
|
||||
public override async clear(): Promise<void> {
|
||||
for (const w of this._workspacesCache.values()) {
|
||||
if (w.room) {
|
||||
try {
|
||||
await this.delete(w.room);
|
||||
await this.deleteWorkspace(w.room);
|
||||
this._workspaces.remove(w.room);
|
||||
} catch (e) {
|
||||
this._logger('has a problem of delete workspace ', e);
|
||||
}
|
||||
@@ -204,14 +210,14 @@ export class AffineProvider extends BaseProvider {
|
||||
this._workspacesCache.clear();
|
||||
}
|
||||
|
||||
public override async close(id: string) {
|
||||
public override async closeWorkspace(id: string) {
|
||||
const idb = this._idbMap.get(id);
|
||||
idb?.destroy();
|
||||
const ws = this._wsMap.get(id);
|
||||
ws?.disconnect();
|
||||
}
|
||||
|
||||
public override async leave(id: string): Promise<void> {
|
||||
public override async leaveWorkspace(id: string): Promise<void> {
|
||||
await leaveWorkspace({ id });
|
||||
}
|
||||
|
||||
@@ -251,6 +257,19 @@ export class AffineProvider extends BaseProvider {
|
||||
nw.meta.setName(meta.name);
|
||||
nw.meta.setAvatar(meta.avatar);
|
||||
this._initWorkspaceDb(nw);
|
||||
|
||||
const workspaceInfo: WS = {
|
||||
name: meta.name,
|
||||
id,
|
||||
isPublish: false,
|
||||
avatar: '',
|
||||
owner: undefined,
|
||||
isLocal: true,
|
||||
memberCount: 1,
|
||||
provider: 'local',
|
||||
};
|
||||
|
||||
this._workspaces.add(workspaceInfo);
|
||||
return nw;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { BlobStorage, Workspace } from '@blocksuite/store';
|
||||
import { Logger, User, Workspace as WS, WorkspaceMeta } from '../types';
|
||||
import { Workspaces } from '../workspaces';
|
||||
import type { WorkspacesScope } from '../workspaces';
|
||||
|
||||
export class BaseProvider {
|
||||
public readonly id: string = 'base';
|
||||
protected _workspaces!: Workspaces;
|
||||
protected _workspaces!: WorkspacesScope;
|
||||
protected _logger!: Logger;
|
||||
protected _blobs!: BlobStorage;
|
||||
|
||||
@@ -13,7 +13,7 @@ export class BaseProvider {
|
||||
workspaces,
|
||||
}: {
|
||||
logger: Logger;
|
||||
workspaces: Workspaces;
|
||||
workspaces: WorkspacesScope;
|
||||
}) {
|
||||
this._logger = logger;
|
||||
this._workspaces = workspaces;
|
||||
@@ -83,7 +83,7 @@ export class BaseProvider {
|
||||
* delete workspace include all data
|
||||
* @param id workspace id
|
||||
*/
|
||||
public async delete(id: string): Promise<void> {
|
||||
public async deleteWorkspace(id: string): Promise<void> {
|
||||
id;
|
||||
return;
|
||||
}
|
||||
@@ -92,7 +92,7 @@ export class BaseProvider {
|
||||
* leave workspace by workspace id
|
||||
* @param id workspace id
|
||||
*/
|
||||
public async leave(id: string): Promise<void> {
|
||||
public async leaveWorkspace(id: string): Promise<void> {
|
||||
id;
|
||||
return;
|
||||
}
|
||||
@@ -101,7 +101,7 @@ export class BaseProvider {
|
||||
* close db link and websocket connection and other resources
|
||||
* @param id workspace id
|
||||
*/
|
||||
public async close(id: string) {
|
||||
public async closeWorkspace(id: string) {
|
||||
id;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { BaseProvider } from '../base';
|
||||
import { varStorage as storage } from 'lib0/storage';
|
||||
import { Workspace as WS, WorkspaceMeta } from '../../types';
|
||||
import { Workspace } from '@blocksuite/store';
|
||||
import { Workspace, uuidv4 } from '@blocksuite/store';
|
||||
import { IndexedDBProvider } from '../indexeddb';
|
||||
import assert from 'assert';
|
||||
import { getDefaultHeadImgBlob } from '../../utils';
|
||||
@@ -11,11 +11,10 @@ const WORKSPACE_KEY = 'workspaces';
|
||||
export class LocalProvider extends BaseProvider {
|
||||
public id = 'local';
|
||||
private _idbMap: Map<string, IndexedDBProvider> = new Map();
|
||||
private _workspacesList: WS[] = [];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._workspacesList = [];
|
||||
this.loadWorkspaces();
|
||||
}
|
||||
|
||||
private _storeWorkspaces(workspaces: WS[]) {
|
||||
@@ -46,6 +45,9 @@ export class LocalProvider extends BaseProvider {
|
||||
if (workspaceStr) {
|
||||
try {
|
||||
workspaces = JSON.parse(workspaceStr) as WS[];
|
||||
workspaces.forEach(workspace => {
|
||||
this._workspaces.add(workspace);
|
||||
});
|
||||
} catch (error) {
|
||||
this._logger(`Failed to parse workspaces from storage`);
|
||||
}
|
||||
@@ -53,12 +55,12 @@ export class LocalProvider extends BaseProvider {
|
||||
return Promise.resolve(workspaces);
|
||||
}
|
||||
|
||||
public override async delete(id: string): Promise<void> {
|
||||
const index = this._workspacesList.findIndex(ws => ws.id === id);
|
||||
if (index !== -1) {
|
||||
public override async deleteWorkspace(id: string): Promise<void> {
|
||||
const workspace = this._workspaces.get(id);
|
||||
if (workspace) {
|
||||
IndexedDBProvider.delete(id);
|
||||
this._workspacesList.splice(index, 1);
|
||||
this._storeWorkspaces(this._workspacesList);
|
||||
this._workspaces.remove(id);
|
||||
this._storeWorkspaces(this._workspaces.list());
|
||||
} else {
|
||||
this._logger(`Failed to delete workspace ${id}`);
|
||||
}
|
||||
@@ -68,15 +70,8 @@ export class LocalProvider extends BaseProvider {
|
||||
id: string,
|
||||
meta: Partial<WorkspaceMeta>
|
||||
) {
|
||||
const index = this._workspacesList.findIndex(ws => ws.id === id);
|
||||
if (index !== -1) {
|
||||
const workspace = this._workspacesList[index];
|
||||
meta.name && (workspace.name = meta.name);
|
||||
meta.avatar && (workspace.avatar = meta.avatar);
|
||||
this._storeWorkspaces(this._workspacesList);
|
||||
} else {
|
||||
this._logger(`Failed to update workspace ${id}`);
|
||||
}
|
||||
this._workspaces.update(id, meta);
|
||||
this._storeWorkspaces(this._workspaces.list());
|
||||
}
|
||||
|
||||
public override async createWorkspace(
|
||||
@@ -88,13 +83,27 @@ export class LocalProvider extends BaseProvider {
|
||||
const blob = await getDefaultHeadImgBlob(meta.name);
|
||||
meta.avatar = (await this.setBlob(blob)) || '';
|
||||
}
|
||||
const workspaceInfos = this._workspaces.addLocalWorkspace(meta.name);
|
||||
this._logger('Creating affine workspace');
|
||||
const workspace = new Workspace({ room: workspaceInfos.id });
|
||||
|
||||
const workspaceInfo: WS = {
|
||||
name: meta.name,
|
||||
id: uuidv4(),
|
||||
isPublish: false,
|
||||
avatar: '',
|
||||
owner: undefined,
|
||||
isLocal: true,
|
||||
memberCount: 1,
|
||||
provider: 'local',
|
||||
};
|
||||
|
||||
const workspace = new Workspace({ room: workspaceInfo.id });
|
||||
this._initWorkspaceDb(workspace);
|
||||
workspace.meta.setName(meta.name);
|
||||
workspace.meta.setAvatar(meta.avatar);
|
||||
this._storeWorkspaces([...this._workspacesList, workspaceInfos]);
|
||||
this._initWorkspaceDb(workspace);
|
||||
|
||||
this._workspaces.add(workspaceInfo);
|
||||
this._storeWorkspaces(this._workspaces.list());
|
||||
|
||||
return workspace;
|
||||
}
|
||||
|
||||
@@ -102,5 +111,6 @@ export class LocalProvider extends BaseProvider {
|
||||
const workspaces = await this.loadWorkspaces();
|
||||
workspaces.forEach(ws => IndexedDBProvider.delete(ws.id));
|
||||
this._storeWorkspaces([]);
|
||||
this._workspaces.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export { Workspaces } from './workspaces';
|
||||
export type { WorkspacesScope, WorkspacesChangeEvent } from './workspaces';
|
||||
|
||||
@@ -1,101 +1,127 @@
|
||||
import { Workspace as WS } from '../types';
|
||||
|
||||
import { Observable } from 'lib0/observable';
|
||||
import { uuidv4 } from '@blocksuite/store';
|
||||
import { DataCenter } from '../datacenter';
|
||||
import type { Workspace, WorkspaceMeta } from '../types';
|
||||
|
||||
export class Workspaces extends Observable<string> {
|
||||
private _workspaces: WS[];
|
||||
private readonly _dc: DataCenter;
|
||||
export interface WorkspacesScope {
|
||||
get: (workspaceId: string) => Workspace | undefined;
|
||||
list: () => Workspace[];
|
||||
add: (workspace: Workspace) => void;
|
||||
remove: (workspaceId: string) => boolean;
|
||||
clear: () => void;
|
||||
update: (workspaceId: string, workspaceMeta: Partial<WorkspaceMeta>) => void;
|
||||
}
|
||||
|
||||
constructor(dc: DataCenter) {
|
||||
super();
|
||||
this._workspaces = [];
|
||||
this._dc = dc;
|
||||
export interface WorkspacesChangeEvent {
|
||||
added?: Workspace;
|
||||
deleted?: Workspace;
|
||||
updated?: Workspace;
|
||||
}
|
||||
|
||||
export class Workspaces extends Observable<'change'> {
|
||||
private _workspacesMap = new Map<string, Workspace>();
|
||||
|
||||
get workspaces(): Workspace[] {
|
||||
return Object.values(this._workspacesMap);
|
||||
}
|
||||
|
||||
public init() {
|
||||
this._loadWorkspaces();
|
||||
find(workspaceId: string) {
|
||||
return this._workspacesMap.get(workspaceId);
|
||||
}
|
||||
|
||||
get workspaces() {
|
||||
return this._workspaces;
|
||||
}
|
||||
createScope(): WorkspacesScope {
|
||||
const scopedWorkspaceIds = new Set<string>();
|
||||
|
||||
/**
|
||||
* emit when workspaces changed
|
||||
* @param {(workspace: WS[]) => void} cb
|
||||
*/
|
||||
onWorkspacesChange(cb: (workspace: WS[]) => void) {
|
||||
this.on('change', cb);
|
||||
}
|
||||
const get = (workspaceId: string) => {
|
||||
if (!scopedWorkspaceIds.has(workspaceId)) {
|
||||
return;
|
||||
}
|
||||
return this._workspacesMap.get(workspaceId);
|
||||
};
|
||||
|
||||
private async _loadWorkspaces() {
|
||||
const providers = this._dc.providers;
|
||||
let workspaces: WS[] = [];
|
||||
providers.forEach(async p => {
|
||||
const pWorkspaces = await p.loadWorkspaces();
|
||||
workspaces = [...workspaces, ...pWorkspaces];
|
||||
this._updateWorkspaces([...workspaces, ...pWorkspaces]);
|
||||
});
|
||||
}
|
||||
const add = (workspace: Workspace) => {
|
||||
if (this._workspacesMap.has(workspace.id)) {
|
||||
throw new Error(`Duplicate workspace id.`);
|
||||
}
|
||||
this._workspacesMap.set(workspace.id, workspace);
|
||||
scopedWorkspaceIds.add(workspace.id);
|
||||
|
||||
/**
|
||||
* focus load all workspaces list
|
||||
*/
|
||||
public async refreshWorkspaces() {
|
||||
this._loadWorkspaces();
|
||||
}
|
||||
this.emit('change', [
|
||||
{
|
||||
added: workspace,
|
||||
} as WorkspacesChangeEvent,
|
||||
]);
|
||||
};
|
||||
|
||||
private _updateWorkspaces(workspaces: WS[]) {
|
||||
this._workspaces = workspaces;
|
||||
this.emit('change', this._workspaces);
|
||||
}
|
||||
const remove = (workspaceId: string) => {
|
||||
if (!scopedWorkspaceIds.has(workspaceId)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const workspace = this._workspacesMap.get(workspaceId);
|
||||
if (workspace) {
|
||||
const ret = this._workspacesMap.delete(workspaceId);
|
||||
// If deletion failed, return.
|
||||
if (!ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
scopedWorkspaceIds.delete(workspaceId);
|
||||
|
||||
this.emit('change', [
|
||||
{
|
||||
deleted: workspace,
|
||||
} as WorkspacesChangeEvent,
|
||||
]);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const clear = () => {
|
||||
scopedWorkspaceIds.forEach(id => {
|
||||
remove(id);
|
||||
});
|
||||
};
|
||||
|
||||
const update = (
|
||||
workspaceId: string,
|
||||
workspaceMeta: Partial<WorkspaceMeta>
|
||||
) => {
|
||||
if (!scopedWorkspaceIds.has(workspaceId)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const workspace = this._workspacesMap.get(workspaceId);
|
||||
if (!workspace) {
|
||||
return true;
|
||||
}
|
||||
|
||||
this._workspacesMap.set(workspaceId, { ...workspace, ...workspaceMeta });
|
||||
|
||||
this.emit('change', [
|
||||
{
|
||||
updated: this._workspacesMap.get(workspaceId),
|
||||
} as WorkspacesChangeEvent,
|
||||
]);
|
||||
};
|
||||
|
||||
// TODO: need to optimize
|
||||
const list = () => {
|
||||
const workspaces: Workspace[] = [];
|
||||
scopedWorkspaceIds.forEach(id => {
|
||||
const workspace = this._workspacesMap.get(id);
|
||||
if (workspace) {
|
||||
workspaces.push(workspace);
|
||||
}
|
||||
});
|
||||
return workspaces;
|
||||
};
|
||||
|
||||
private _getDefaultWorkspace(name: string): WS {
|
||||
return {
|
||||
name,
|
||||
id: uuidv4(),
|
||||
isPublish: false,
|
||||
avatar: '',
|
||||
owner: undefined,
|
||||
isLocal: true,
|
||||
memberCount: 1,
|
||||
provider: 'local',
|
||||
get,
|
||||
list,
|
||||
add,
|
||||
remove,
|
||||
clear,
|
||||
update,
|
||||
};
|
||||
}
|
||||
|
||||
/** add a local workspaces */
|
||||
public addLocalWorkspace(name: string) {
|
||||
const workspace = this._getDefaultWorkspace(name);
|
||||
this._updateWorkspaces([...this._workspaces, workspace]);
|
||||
return workspace;
|
||||
}
|
||||
|
||||
/** delete a workspaces by id */
|
||||
public delete(id: string) {
|
||||
const index = this._workspaces.findIndex(w => w.id === id);
|
||||
if (index >= 0) {
|
||||
this._workspaces.splice(index, 1);
|
||||
this._updateWorkspaces(this._workspaces);
|
||||
}
|
||||
}
|
||||
|
||||
/** get workspace info by id */
|
||||
public getWorkspace(id: string) {
|
||||
return this._workspaces.find(w => w.id === id);
|
||||
}
|
||||
|
||||
/** check if workspace exists */
|
||||
public hasWorkspace(id: string) {
|
||||
return this._workspaces.some(w => w.id === id);
|
||||
}
|
||||
|
||||
public updateWorkspaceInfo(id: string, info: Partial<WS>) {
|
||||
const index = this._workspaces.findIndex(w => w.id === id);
|
||||
if (index >= 0) {
|
||||
this._workspaces[index] = { ...this._workspaces[index], ...info };
|
||||
this._updateWorkspaces(this._workspaces);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
101
packages/data-center/src/workspaces/workspaces.ts.bak
Normal file
101
packages/data-center/src/workspaces/workspaces.ts.bak
Normal file
@@ -0,0 +1,101 @@
|
||||
import { Workspace as WS } from '../types';
|
||||
|
||||
import { Observable } from 'lib0/observable';
|
||||
import { uuidv4 } from '@blocksuite/store';
|
||||
import { DataCenter } from '../datacenter';
|
||||
|
||||
export class Workspaces extends Observable<string> {
|
||||
private _workspaces: WS[];
|
||||
private readonly _dc: DataCenter;
|
||||
|
||||
constructor(dc: DataCenter) {
|
||||
super();
|
||||
this._workspaces = [];
|
||||
this._dc = dc;
|
||||
}
|
||||
|
||||
public init() {
|
||||
this._loadWorkspaces();
|
||||
}
|
||||
|
||||
get workspaces() {
|
||||
return this._workspaces;
|
||||
}
|
||||
|
||||
/**
|
||||
* emit when workspaces changed
|
||||
* @param {(workspace: WS[]) => void} cb
|
||||
*/
|
||||
onWorkspacesChange(cb: (workspace: WS[]) => void) {
|
||||
this.on('change', cb);
|
||||
}
|
||||
|
||||
private async _loadWorkspaces() {
|
||||
const providers = this._dc.providers;
|
||||
let workspaces: WS[] = [];
|
||||
providers.forEach(async p => {
|
||||
const pWorkspaces = await p.loadWorkspaces();
|
||||
workspaces = [...workspaces, ...pWorkspaces];
|
||||
this._updateWorkspaces([...workspaces, ...pWorkspaces]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* focus load all workspaces list
|
||||
*/
|
||||
public async refreshWorkspaces() {
|
||||
this._loadWorkspaces();
|
||||
}
|
||||
|
||||
private _updateWorkspaces(workspaces: WS[]) {
|
||||
this._workspaces = workspaces;
|
||||
this.emit('change', this._workspaces);
|
||||
}
|
||||
|
||||
private _getDefaultWorkspace(name: string): WS {
|
||||
return {
|
||||
name,
|
||||
id: uuidv4(),
|
||||
isPublish: false,
|
||||
avatar: '',
|
||||
owner: undefined,
|
||||
isLocal: true,
|
||||
memberCount: 1,
|
||||
provider: 'local',
|
||||
};
|
||||
}
|
||||
|
||||
/** add a local workspaces */
|
||||
public addLocalWorkspace(name: string) {
|
||||
const workspace = this._getDefaultWorkspace(name);
|
||||
this._updateWorkspaces([...this._workspaces, workspace]);
|
||||
return workspace;
|
||||
}
|
||||
|
||||
/** delete a workspaces by id */
|
||||
public delete(id: string) {
|
||||
const index = this._workspaces.findIndex(w => w.id === id);
|
||||
if (index >= 0) {
|
||||
this._workspaces.splice(index, 1);
|
||||
this._updateWorkspaces(this._workspaces);
|
||||
}
|
||||
}
|
||||
|
||||
/** get workspace info by id */
|
||||
public getWorkspace(id: string) {
|
||||
return this._workspaces.find(w => w.id === id);
|
||||
}
|
||||
|
||||
/** check if workspace exists */
|
||||
public hasWorkspace(id: string) {
|
||||
return this._workspaces.some(w => w.id === id);
|
||||
}
|
||||
|
||||
public updateWorkspaceInfo(id: string, info: Partial<WS>) {
|
||||
const index = this._workspaces.findIndex(w => w.id === id);
|
||||
if (index >= 0) {
|
||||
this._workspaces[index] = { ...this._workspaces[index], ...info };
|
||||
this._updateWorkspaces(this._workspaces);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user