From ea08173af0b40d1af90c0445328614c000696682 Mon Sep 17 00:00:00 2001 From: liujuping Date: Mon, 9 Jan 2023 17:18:30 +0800 Subject: [PATCH] feat: added apis support resource tree in workspace mode --- docs/docs/api/index.md | 4 ++ docs/docs/api/model/plugin-instance.md | 2 +- docs/docs/api/model/resource-type.md | 26 ++++++++ docs/docs/api/model/resource.md | 36 ++++++++++ docs/docs/api/model/window.md | 17 ++++- docs/docs/api/plugins.md | 2 +- docs/docs/api/workspace.md | 66 ++++++++++++++++++- packages/shell/src/api/workspace.ts | 23 +++++-- packages/shell/src/model/index.ts | 4 +- packages/shell/src/model/resource-type.ts | 22 +++++++ packages/shell/src/model/resource.ts | 28 ++++++++ packages/shell/src/model/window.ts | 5 +- packages/shell/src/symbols.ts | 4 +- packages/types/src/shell/api/workspace.ts | 24 +++++-- packages/types/src/shell/model/index.ts | 4 +- .../types/src/shell/model/resource-type.ts | 7 ++ packages/types/src/shell/model/resource.ts | 12 ++++ packages/types/src/shell/model/window.ts | 10 ++- .../types/src/shell/type/resource-options.ts | 20 ++++-- packages/workspace/src/editor-view/context.ts | 4 +- .../workspace/src/editor-window/context.ts | 26 ++++---- packages/workspace/src/index.ts | 3 +- packages/workspace/src/resource-type.ts | 53 +++++++++++++++ packages/workspace/src/resource.ts | 54 +++++---------- packages/workspace/src/workspace.ts | 64 ++++++++++++------ 25 files changed, 419 insertions(+), 101 deletions(-) create mode 100644 docs/docs/api/model/resource-type.md create mode 100644 docs/docs/api/model/resource.md create mode 100644 packages/shell/src/model/resource-type.ts create mode 100644 packages/shell/src/model/resource.ts create mode 100644 packages/types/src/shell/model/resource-type.ts create mode 100644 packages/types/src/shell/model/resource.ts create mode 100644 packages/workspace/src/resource-type.ts diff --git a/docs/docs/api/index.md b/docs/docs/api/index.md index 2bd735c84..993c39e88 100644 --- a/docs/docs/api/index.md +++ b/docs/docs/api/index.md @@ -44,3 +44,7 @@ sidebar_position: 0 2. 事件(events)的命名格式为:on[Will|Did]VerbNoun?,参考 [https://code.visualstudio.com/api/references/vscode-api#events](https://code.visualstudio.com/api/references/vscode-api#events) 3. 基于 Disposable 模式,对于事件的绑定、快捷键的绑定函数,返回值则是解绑函数 4. 对于属性的导出,统一用 .xxx 的 getter 模式,(尽量)不使用 .getXxx() + +## experimental + +说明此模块处于公测阶段, API 可能会发生改变. \ No newline at end of file diff --git a/docs/docs/api/model/plugin-instance.md b/docs/docs/api/model/plugin-instance.md index 9ca872a4f..8f764c68b 100644 --- a/docs/docs/api/model/plugin-instance.md +++ b/docs/docs/api/model/plugin-instance.md @@ -1,5 +1,5 @@ --- -title: plugin-instance +title: PluginInstance sidebar_position: 12 --- diff --git a/docs/docs/api/model/resource-type.md b/docs/docs/api/model/resource-type.md new file mode 100644 index 000000000..327788ce3 --- /dev/null +++ b/docs/docs/api/model/resource-type.md @@ -0,0 +1,26 @@ +--- +title: ResourceType +sidebar_position: 12 +--- + +> **[@experimental](./#experimental)**
+> **@types** [IPublicModelWindow](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/resource-type.ts)
+> **@since** v1.1.0 + +## 变量 + +### description + +资源描述 + +`@type {string}` + +### icon + +资源 icon + +`@type {ReactElement}` + +### name + +`@type {string}` diff --git a/docs/docs/api/model/resource.md b/docs/docs/api/model/resource.md new file mode 100644 index 000000000..fb3e8a6d8 --- /dev/null +++ b/docs/docs/api/model/resource.md @@ -0,0 +1,36 @@ +--- +title: Resource +sidebar_position: 12 +--- + +> **[@experimental](./#experimental)**
+> **@types** [IPublicModelWindow](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/resource.ts)
+> **@since** v1.1.0 + +## 变量 + +### title + +资源标题 + +`@type {string}` + +### icon + +资源 icon + +`@type {ReactElement}` + +### options + +资源配置信息 + +`@type {Object}` + +### resourceType + +资源所属的资源类型 + +`@type {IPublicModelResourceType}` + +关联模型 [IPublicModelResourceType](./resource-type) diff --git a/docs/docs/api/model/window.md b/docs/docs/api/model/window.md index 6a5413883..9d96f20a8 100644 --- a/docs/docs/api/model/window.md +++ b/docs/docs/api/model/window.md @@ -3,6 +3,7 @@ title: Window sidebar_position: 12 --- +> **[@experimental](./#experimental)**
> **@types** [IPublicModelWindow](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/window.ts)
> **@since** v1.1.0 @@ -17,13 +18,25 @@ sidebar_position: 12 窗口唯一 id +`@type {string}` + ### title 窗口标题 -### resourceName +`@type {string}` -窗口资源名字 +### icon + +`@type {ReactElement}` + +### resourceType + +窗口资源类型 + +`@type {IPublicModelResourceType}` + +关联模型 [IPublicModelResourceType](./resource-type) ## 方法签名 diff --git a/docs/docs/api/plugins.md b/docs/docs/api/plugins.md index 1b20bdabe..9b1993b10 100644 --- a/docs/docs/api/plugins.md +++ b/docs/docs/api/plugins.md @@ -222,7 +222,7 @@ your-plugin/package.json } ``` 转换后的结构: -```json +```typescript const debug = (ctx: IPublicModelPluginContext, options: any) => { return {}; } diff --git a/docs/docs/api/workspace.md b/docs/docs/api/workspace.md index 5a9ad2a44..bf0755537 100644 --- a/docs/docs/api/workspace.md +++ b/docs/docs/api/workspace.md @@ -3,10 +3,10 @@ title: workspace - 应用级 API sidebar_position: 12 --- +> **[@experimental](./#experimental)**
> **@types** [IPublicApiWorkspace](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/api/workspace.ts)
> **@since** v1.1.0 - ## 模块简介 通过该模块可以开发应用级低代码设计器。 @@ -47,6 +47,16 @@ get window(): IPublicModelWindow[] 关联模型 [IPublicModelWindow](./model/window) +### resourceList + +当前设计器的资源列表数据 + +``` +get resourceList(): IPublicModelResource; +``` + +关联模型 [IPublicModelResource](./model/resource) + ## 方法签名 ### registerResourceType @@ -54,7 +64,7 @@ get window(): IPublicModelWindow[] ```typescript /** 注册资源 */ -registerResourceType(resourceName: string, resourceType: 'editor', options: IPublicResourceOptions): void; +registerResourceType(name: string, type: 'editor', options: IPublicResourceOptions): void; ``` 相关类型:[IPublicResourceOptions](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/resource-options.ts) @@ -74,3 +84,55 @@ active 窗口变更事件 ```typescript function onChangeActiveWindow(fn: () => void): void; ``` + +### setResourceList + +设置设计器资源列表数据 + +```typescript +setResourceList(resourceList: IPublicResourceList) {} +``` + +相关类型:[IPublicResourceOptions](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/resource-options.ts) + +### onResourceListChange + +设计器资源列表数据变更事件 + +```typescript +onResourceListChange(fn: (resourceList: IPublicResourceList): void): (): void; +``` + +相关类型:[IPublicResourceOptions](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/resource-options.ts) + +### openEditorWindow + +打开视图窗口 + +```typescript +openEditorWindow(resourceName: string, title: string, options: Object, viewName?: string): void; +``` + +### openEditorWindowById + +通过视图 id 打开窗口 + +```typescript +openEditorWindowById(id: string): void; +``` + +### removeEditorWindow + +移除视图窗口 + +```typescript +removeEditorWindow(resourceName: string, title: string): void; +``` + +### removeEditorWindowById + +通过视图 id 移除窗口 + +```typescript +removeEditorWindowById(id: string): void; +``` \ No newline at end of file diff --git a/packages/shell/src/api/workspace.ts b/packages/shell/src/api/workspace.ts index 3440871c8..09e1b4ca6 100644 --- a/packages/shell/src/api/workspace.ts +++ b/packages/shell/src/api/workspace.ts @@ -1,8 +1,9 @@ -import { IPublicApiWorkspace } from '@alilc/lowcode-types'; +import { IPublicApiWorkspace, IPublicResourceList, IPublicResourceOptions } from '@alilc/lowcode-types'; import { Workspace as InnerWorkSpace } from '@alilc/lowcode-workspace'; import { Plugins } from '@alilc/lowcode-shell'; import { Window } from '../model/window'; import { workspaceSymbol } from '../symbols'; +import { Resource } from '../model'; export class Workspace implements IPublicApiWorkspace { readonly [workspaceSymbol]: InnerWorkSpace; @@ -11,6 +12,18 @@ export class Workspace implements IPublicApiWorkspace { this[workspaceSymbol] = innerWorkspace; } + get resourceList() { + return this[workspaceSymbol].getResourceList().map(d => new Resource(d)); + } + + setResourceList(resourceList: IPublicResourceList) { + this[workspaceSymbol].setResourceList(resourceList); + } + + onResourceListChange(fn: (resourceList: IPublicResourceList) => void): () => void { + return this[workspaceSymbol].onResourceListChange(fn); + } + get isActive() { return this[workspaceSymbol].isActive; } @@ -19,12 +32,12 @@ export class Workspace implements IPublicApiWorkspace { return new Window(this[workspaceSymbol].window); } - registerResourceType(resourceName: string, resourceType: 'editor', options: any): void { - this[workspaceSymbol].registerResourceType(resourceName, resourceType, options); + registerResourceType(name: string, type: 'editor', options: IPublicResourceOptions): void { + this[workspaceSymbol].registerResourceType(name, type, options); } - openEditorWindow(resourceName: string, title: string, viewType?: string) { - this[workspaceSymbol].openEditorWindow(resourceName, title, viewType); + openEditorWindow(resourceName: string, title: string, extra: Object, viewName?: string) { + this[workspaceSymbol].openEditorWindow(resourceName, title, extra, viewName); } openEditorWindowById(id: string) { diff --git a/packages/shell/src/model/index.ts b/packages/shell/src/model/index.ts index 1e0a77775..5f5e50220 100644 --- a/packages/shell/src/model/index.ts +++ b/packages/shell/src/model/index.ts @@ -13,4 +13,6 @@ export * from './prop'; export * from './props'; export * from './selection'; export * from './setting-prop-entry'; -export * from './setting-top-entry'; \ No newline at end of file +export * from './setting-top-entry'; +export * from './resource'; +export * from './resource-type'; \ No newline at end of file diff --git a/packages/shell/src/model/resource-type.ts b/packages/shell/src/model/resource-type.ts new file mode 100644 index 000000000..b5ed549f1 --- /dev/null +++ b/packages/shell/src/model/resource-type.ts @@ -0,0 +1,22 @@ +import { IPublicModelResourceType } from '@alilc/lowcode-types'; +import { ResourceType as InnerResourceType } from '@alilc/lowcode-workspace'; +import { resourceTypeSymbol } from '../symbols'; + +export class ResourceType implements IPublicModelResourceType { + readonly [resourceTypeSymbol]: InnerResourceType; + constructor(resourceType: InnerResourceType) { + this[resourceTypeSymbol] = resourceType; + } + + get name() { + return this[resourceTypeSymbol].name; + } + + get description() { + return this[resourceTypeSymbol].options.description; + } + + get icon() { + return this[resourceTypeSymbol].options.icon; + } +} \ No newline at end of file diff --git a/packages/shell/src/model/resource.ts b/packages/shell/src/model/resource.ts new file mode 100644 index 000000000..df8190549 --- /dev/null +++ b/packages/shell/src/model/resource.ts @@ -0,0 +1,28 @@ +import { IPublicModelResource } from '@alilc/lowcode-types'; +import { Resource as InnerResource } from '@alilc/lowcode-workspace'; +import { resourceSymbol } from '../symbols'; +import { ResourceType } from './resource-type'; + +export class Resource implements IPublicModelResource { + readonly [resourceSymbol]: InnerResource; + + constructor(resource: InnerResource) { + this[resourceSymbol] = resource; + } + + get title() { + return this[resourceSymbol].title; + } + + get icon() { + return this[resourceSymbol].icon; + } + + get options() { + return this[resourceSymbol].options; + } + + get resourceType() { + return new ResourceType(this[resourceSymbol].resourceType); + } +} \ No newline at end of file diff --git a/packages/shell/src/model/window.ts b/packages/shell/src/model/window.ts index fee783f53..fcb282490 100644 --- a/packages/shell/src/model/window.ts +++ b/packages/shell/src/model/window.ts @@ -1,6 +1,7 @@ import { windowSymbol } from '../symbols'; import { IPublicModelWindow } from '@alilc/lowcode-types'; import { EditorWindow } from '@alilc/lowcode-workspace'; +import { ResourceType } from './resource-type'; export class Window implements IPublicModelWindow { private readonly [windowSymbol]: EditorWindow; @@ -17,8 +18,8 @@ export class Window implements IPublicModelWindow { return this[windowSymbol].icon; } - get resourceName() { - return this[windowSymbol].resourceName; + get resourceType(): ResourceType { + return new ResourceType(this[windowSymbol].resourceType); } constructor(editorWindow: EditorWindow) { diff --git a/packages/shell/src/symbols.ts b/packages/shell/src/symbols.ts index b87e1f24b..cd164f62a 100644 --- a/packages/shell/src/symbols.ts +++ b/packages/shell/src/symbols.ts @@ -28,4 +28,6 @@ export const hotkeySymbol = Symbol('hotkey'); export const pluginsSymbol = Symbol('plugins'); export const workspaceSymbol = Symbol('workspace'); export const windowSymbol = Symbol('window'); -export const pluginInstanceSymbol = Symbol('plugin-instance'); \ No newline at end of file +export const pluginInstanceSymbol = Symbol('plugin-instance'); +export const resourceTypeSymbol = Symbol('resourceType'); +export const resourceSymbol = Symbol('resource'); \ No newline at end of file diff --git a/packages/types/src/shell/api/workspace.ts b/packages/types/src/shell/api/workspace.ts index b9cd29afa..165565fe7 100644 --- a/packages/types/src/shell/api/workspace.ts +++ b/packages/types/src/shell/api/workspace.ts @@ -1,23 +1,39 @@ import { IPublicModelWindow } from '../model'; import { IPublicResourceOptions } from '../type'; -import { IPublicApiPlugins } from '@alilc/lowcode-types'; +import { IPublicApiPlugins, IPublicModelResource, IPublicResourceList } from '@alilc/lowcode-types'; export interface IPublicApiWorkspace { + /** 是否启用 workspace 模式 */ isActive: boolean; /** 当前设计器窗口 */ window: IPublicModelWindow; + /** 获取资源树列表 */ + get resourceList(): IPublicModelResource[]; + + /** 设置资源树列表 */ + setResourceList(resourceList: IPublicResourceList): void; + + /** 资源树列表更新事件 */ + onResourceListChange(fn: (resourceList: IPublicResourceList) => void): () => void; + /** 注册资源 */ - registerResourceType(resourceName: string, resourceType: 'editor', options: IPublicResourceOptions): void; + registerResourceType(resourceName: string, type: 'editor', options: IPublicResourceOptions): void; /** 打开视图窗口 */ - openEditorWindow(resourceName: string, title: string, viewType?: string): void; + openEditorWindow(resourceName: string, title: string, extra: Object, viewName?: string): void; - /** 移除窗口 */ + /** 通过视图 id 打开窗口 */ + openEditorWindowById(id: string): void; + + /** 移除视图窗口 */ removeEditorWindow(resourceName: string, title: string): void; + /** 通过视图 id 移除窗口 */ + removeEditorWindowById(id: string): void; + plugins: IPublicApiPlugins; /** 当前设计器的编辑窗口 */ diff --git a/packages/types/src/shell/model/index.ts b/packages/types/src/shell/model/index.ts index 5b02d0224..669fdfc99 100644 --- a/packages/types/src/shell/model/index.ts +++ b/packages/types/src/shell/model/index.ts @@ -27,4 +27,6 @@ export * from './engine-config'; export * from './editor'; export * from './preference'; export * from './plugin-instance'; -export * from './sensor'; \ No newline at end of file +export * from './sensor'; +export * from './resource-type'; +export * from './resource'; \ No newline at end of file diff --git a/packages/types/src/shell/model/resource-type.ts b/packages/types/src/shell/model/resource-type.ts new file mode 100644 index 000000000..e8031145e --- /dev/null +++ b/packages/types/src/shell/model/resource-type.ts @@ -0,0 +1,7 @@ +import { ReactElement } from 'react'; + +export interface IPublicModelResourceType { + get description(): string | undefined; + + get icon(): ReactElement | undefined; +} \ No newline at end of file diff --git a/packages/types/src/shell/model/resource.ts b/packages/types/src/shell/model/resource.ts new file mode 100644 index 000000000..23dbfb50f --- /dev/null +++ b/packages/types/src/shell/model/resource.ts @@ -0,0 +1,12 @@ +import { ReactElement } from 'react'; +import { IPublicModelResourceType } from './resource-type'; + +export interface IPublicModelResource { + get title(): string; + + get icon(): ReactElement | undefined; + + get options(): Object; + + get resourceType(): IPublicModelResourceType | undefined; +} \ No newline at end of file diff --git a/packages/types/src/shell/model/window.ts b/packages/types/src/shell/model/window.ts index 1502f2a3c..7a12fc8e6 100644 --- a/packages/types/src/shell/model/window.ts +++ b/packages/types/src/shell/model/window.ts @@ -1,6 +1,9 @@ +import { ReactElement } from 'react'; import { IPublicTypeNodeSchema } from '../type'; +import { IPublicModelResourceType } from './resource-type'; export interface IPublicModelWindow { + /** 当前窗口导入 schema */ importSchema(schema: IPublicTypeNodeSchema): void; @@ -16,6 +19,9 @@ export interface IPublicModelWindow { /** 窗口标题 */ title?: string; - /** 窗口资源名字 */ - resourceName?: string; + /** 窗口 icon */ + icon?: ReactElement; + + /** 窗口资源类型 */ + resourceType?: IPublicModelResourceType; } \ No newline at end of file diff --git a/packages/types/src/shell/type/resource-options.ts b/packages/types/src/shell/type/resource-options.ts index e82db194c..4954aa7fa 100644 --- a/packages/types/src/shell/type/resource-options.ts +++ b/packages/types/src/shell/type/resource-options.ts @@ -1,21 +1,23 @@ export interface IPublicViewFunctions { + /** 视图初始化钩子 */ init?: () => Promise; + /** 资源保存时,会调用视图的钩子 */ save?: () => Promise; } export interface IPublicEditorView { + /** 资源名字 */ viewName: string; + /** 资源类型 */ viewType?: 'editor' | 'webview'; - (ctx: any): IPublicViewFunctions; + (ctx: any, options: any): IPublicViewFunctions; } export interface IPublicResourceOptions { - /** 资源名字 */ - name: string; /** 资源描述 */ description?: string; @@ -41,4 +43,14 @@ export interface IPublicResourceOptions { /** 默认标题 */ defaultTitle?: string; -} \ No newline at end of file +} + +export interface IPublicResourceData { + resourceName: string; + title: string; + options: { + [key: string]: any; + }; +} + +export type IPublicResourceList = IPublicResourceData[]; \ No newline at end of file diff --git a/packages/workspace/src/editor-view/context.ts b/packages/workspace/src/editor-view/context.ts index a845d36c1..12e63b255 100644 --- a/packages/workspace/src/editor-view/context.ts +++ b/packages/workspace/src/editor-view/context.ts @@ -13,13 +13,13 @@ export class Context extends BasicContext { viewType: 'editor' | 'webview'; - constructor(public workspace: InnerWorkspace, public editorWindow: EditorWindow, public editorView: IPublicEditorView) { + constructor(public workspace: InnerWorkspace, public editorWindow: EditorWindow, public editorView: IPublicEditorView, options: Object) { super(workspace, editorView.viewName, editorWindow); this.viewType = editorView.viewType || 'editor'; this.viewName = editorView.viewName; this.instance = editorView(this.innerPlugins._getLowCodePluginContext({ pluginName: 'any', - })); + }), options); makeObservable(this); } diff --git a/packages/workspace/src/editor-window/context.ts b/packages/workspace/src/editor-window/context.ts index 2c1eee719..5e3fb172f 100644 --- a/packages/workspace/src/editor-window/context.ts +++ b/packages/workspace/src/editor-window/context.ts @@ -2,24 +2,20 @@ import { uniqueId } from '@alilc/lowcode-utils'; import { makeObservable, obx } from '@alilc/lowcode-editor-core'; import { Context } from '../editor-view/context'; import { Workspace } from '../workspace'; -import { Resource } from '../resource'; +import { ResourceType } from '../resource-type'; export class EditorWindow { id: string = uniqueId('window'); icon: React.ReactElement | undefined; - constructor(readonly resource: Resource, readonly workspace: Workspace, public title: string | undefined = '') { + constructor(readonly resourceType: ResourceType, readonly workspace: Workspace, public title: string | undefined = '', private options: Object = {}) { makeObservable(this); this.init(); - this.icon = resource.icon; - } - - get resourceName(): string { - return this.resource.options.name; + this.icon = resourceType.icon; } async importSchema(schema: any) { - const newSchema = await this.resource.import(schema); + const newSchema = await this.resourceType.import(schema); if (!newSchema) { return; @@ -33,13 +29,13 @@ export class EditorWindow { async save() { const value: any = {}; - const editorViews = this.resource.editorViews; + const editorViews = this.resourceType.editorViews; for (let i = 0; i < editorViews.length; i++) { const name = editorViews[i].viewName; const saveResult = await this.editorViews.get(name)?.save(); value[name] = saveResult; } - return await this.resource.save(value); + return await this.resourceType.save(value); } async init() { @@ -49,7 +45,7 @@ export class EditorWindow { } initViewTypes = async () => { - const editorViews = this.resource.editorViews; + const editorViews = this.resourceType.editorViews; for (let i = 0; i < editorViews.length; i++) { const name = editorViews[i].viewName; await this.initViewType(name); @@ -60,7 +56,7 @@ export class EditorWindow { }; execViewTypesInit = async () => { - const editorViews = this.resource.editorViews; + const editorViews = this.resourceType.editorViews; for (let i = 0; i < editorViews.length; i++) { const name = editorViews[i].viewName; this.changeViewType(name); @@ -69,7 +65,7 @@ export class EditorWindow { }; setDefaultViewType = () => { - this.changeViewType(this.resource.defaultViewType); + this.changeViewType(this.resourceType.defaultViewType); }; @obx.ref editorView: Context; @@ -77,11 +73,11 @@ export class EditorWindow { @obx editorViews: Map = new Map(); initViewType = async (name: string) => { - const viewInfo = this.resource.getEditorView(name); + const viewInfo = this.resourceType.getEditorView(name); if (this.editorViews.get(name)) { return; } - const editorView = new Context(this.workspace, this, viewInfo as any); + const editorView = new Context(this.workspace, this, viewInfo as any, this.options); this.editorViews.set(name, editorView); }; diff --git a/packages/workspace/src/index.ts b/packages/workspace/src/index.ts index 91dc20a54..8c71771a9 100644 --- a/packages/workspace/src/index.ts +++ b/packages/workspace/src/index.ts @@ -1,4 +1,5 @@ export { Workspace } from './workspace'; -export { Resource } from './resource'; +export { ResourceType } from './resource-type'; export * from './editor-window/context'; export * from './layouts/workbench'; +export { Resource } from './resource'; diff --git a/packages/workspace/src/resource-type.ts b/packages/workspace/src/resource-type.ts new file mode 100644 index 000000000..60a2832ee --- /dev/null +++ b/packages/workspace/src/resource-type.ts @@ -0,0 +1,53 @@ +import { IPublicEditorView, IPublicModelResourceType, IPublicResourceOptions } from '@alilc/lowcode-types'; + +export class ResourceType implements IPublicModelResourceType { + constructor(readonly name: string, readonly type: 'editor' | 'webview', options: IPublicResourceOptions) { + if (options.editorViews) { + options.editorViews.forEach((d: any) => { + this.editorViewMap.set(d.viewName, d); + }); + } + + this.options = options; + } + + get description() { + return this.options.description; + } + + options: IPublicResourceOptions; + + editorViewMap: Map = new Map(); + + init(ctx: any) { + this.options.init(ctx); + } + + get icon() { + return this.options.icon; + } + + async import(schema: any) { + return await this.options.import?.(schema); + } + + getEditorView(name: string) { + return this.editorViewMap.get(name); + } + + get defaultViewType() { + return this.options.defaultViewType || this.editorViewMap.keys().next().value; + } + + get editorViews() { + return Array.from(this.editorViewMap.values()); + } + + async save(value: any) { + return await this.options.save?.(value); + } + + get title() { + return this.options.defaultTitle; + } +} \ No newline at end of file diff --git a/packages/workspace/src/resource.ts b/packages/workspace/src/resource.ts index f881caf0f..5c44785ce 100644 --- a/packages/workspace/src/resource.ts +++ b/packages/workspace/src/resource.ts @@ -1,49 +1,29 @@ -import { IPublicEditorView, IPublicResourceOptions } from '@alilc/lowcode-types'; +import { IPublicModelResource, IPublicResourceData } from '@alilc/lowcode-types'; +import { Logger } from '@alilc/lowcode-utils'; +import { ResourceType } from './resource-type'; -export class Resource { - constructor(options: IPublicResourceOptions) { - if (options.editorViews) { - options.editorViews.forEach((d: any) => { - this.editorViewMap.set(d.viewName, d); - }); +const logger = new Logger({ level: 'warn', bizName: 'workspace:resource' }); + +export class Resource implements IPublicModelResource { + constructor(readonly resourceData: IPublicResourceData, readonly resourceType: ResourceType) { + if (!resourceType) { + logger.error(`resourceType[${resourceType}] is unValid.`); } - - this.options = options; - } - - options: IPublicResourceOptions; - - editorViewMap: Map = new Map(); - - init(ctx: any) { - this.options.init(ctx); } get icon() { - return this.options.icon; + return this.resourceType?.icon; } - async import(schema: any) { - return await this.options.import?.(schema); - } - - getEditorView(name: string) { - return this.editorViewMap.get(name); - } - - get defaultViewType() { - return this.options.defaultViewType || this.editorViewMap.keys().next().value; - } - - get editorViews() { - return Array.from(this.editorViewMap.values()); - } - - async save(value: any) { - return await this.options.save?.(value); + get type() { + return this.resourceData.resourceName; } get title() { - return this.options.defaultTitle; + return this.resourceData.title; + } + + get options() { + return this.resourceData.options; } } \ No newline at end of file diff --git a/packages/workspace/src/workspace.ts b/packages/workspace/src/workspace.ts index 05d2e666a..ca7265cb3 100644 --- a/packages/workspace/src/workspace.ts +++ b/packages/workspace/src/workspace.ts @@ -1,10 +1,11 @@ import { Designer } from '@alilc/lowcode-designer'; import { createModuleEventBus, Editor, IEventBus, makeObservable, obx } from '@alilc/lowcode-editor-core'; import { Plugins } from '@alilc/lowcode-shell'; -import { IPublicApiWorkspace, IPublicResourceOptions } from '@alilc/lowcode-types'; +import { IPublicApiWorkspace, IPublicResourceList, IPublicResourceOptions } from '@alilc/lowcode-types'; import { BasicContext } from './base-context'; import { EditorWindow } from './editor-window/context'; import { Resource } from './resource'; +import { ResourceType } from './resource-type'; enum event { ChangeWindow = 'change_window', @@ -12,6 +13,8 @@ enum event { ChangeActiveWindow = 'change_active_window', } +const CHANGE_EVENT = 'resource.list.change'; + export class Workspace implements IPublicApiWorkspace { private context: BasicContext; @@ -42,7 +45,7 @@ export class Workspace implements IPublicApiWorkspace { if (!this.defaultResource) { return; } - const title = this.defaultResource.title; + const title = this.defaultResource.description; this.window = new EditorWindow(this.defaultResource, this, title); this.editorWindowMap.set(this.window.id, this.window); this.windows.push(this.window); @@ -50,7 +53,6 @@ export class Workspace implements IPublicApiWorkspace { this.emitChangeActiveWindow(); } - private _isActive = false; get isActive() { @@ -67,12 +69,14 @@ export class Workspace implements IPublicApiWorkspace { @obx.ref window: EditorWindow; - private resources: Map = new Map(); + private resourceTypeMap: Map = new Map(); - async registerResourceType(resourceName: string, resourceType: 'editor' | 'webview', options: IPublicResourceOptions): Promise { - if (resourceType === 'editor') { - const resource = new Resource(options); - this.resources.set(resourceName, resource); + private resourceList: Resource[] = []; + + async registerResourceType(resourceName: string, type: 'editor' | 'webview', options: IPublicResourceOptions): Promise { + if (type === 'editor') { + const resourceType = new ResourceType(resourceName, type, options); + this.resourceTypeMap.set(resourceName, resourceType); if (!this.window && this.defaultResource) { this.initWindow(); @@ -80,17 +84,37 @@ export class Workspace implements IPublicApiWorkspace { } } - get defaultResource(): Resource | null { - if (this.resources.size > 1) { - return this.resources.values().next().value; + getResourceList() { + return this.resourceList; + } + + setResourceList(resourceList: IPublicResourceList) { + this.resourceList = resourceList.map(d => new Resource(d, this.getResourceType(d.resourceName))); + this.emitter.emit(CHANGE_EVENT, resourceList); + } + + onResourceListChange(fn: (resourceList: IPublicResourceList) => void): () => void { + this.emitter.on(CHANGE_EVENT, fn); + return () => { + this.emitter.off(CHANGE_EVENT, fn); + }; + } + + getResourceType(resourceName: string): ResourceType { + return this.resourceTypeMap.get(resourceName)!; + } + + get defaultResource(): ResourceType | null { + if (this.resourceTypeMap.size > 1) { + return this.resourceTypeMap.values().next().value; } return null; } removeResourceType(resourceName: string) { - if (this.resources.has(resourceName)) { - this.resources.delete(resourceName); + if (this.resourceTypeMap.has(resourceName)) { + this.resourceTypeMap.delete(resourceName); } } @@ -110,7 +134,7 @@ export class Workspace implements IPublicApiWorkspace { } removeEditorWindow(resourceName: string, title: string) { - const index = this.windows.findIndex(d => (d.resourceName === resourceName && d.title)); + const index = this.windows.findIndex(d => (d.resourceType.name === resourceName && d.title)); this.remove(index); } @@ -122,19 +146,19 @@ export class Workspace implements IPublicApiWorkspace { } } - openEditorWindow(resourceName: string, title: string, viewType?: string) { - const resource = this.resources.get(resourceName); - if (!resource) { - console.error(`${resourceName} is not available`); + openEditorWindow(name: string, title: string, options: Object, viewType?: string) { + const resourceType = this.resourceTypeMap.get(name); + if (!resourceType) { + console.error(`${name} is not available`); return; } - const filterWindows = this.windows.filter(d => (d.resourceName === resourceName && d.title == title)); + const filterWindows = this.windows.filter(d => (d.resourceType.name === name && d.title == title)); if (filterWindows && filterWindows.length) { this.window = filterWindows[0]; this.emitChangeActiveWindow(); return; } - this.window = new EditorWindow(resource, this, title); + this.window = new EditorWindow(resourceType, this, title, options); this.windows.push(this.window); this.editorWindowMap.set(this.window.id, this.window); this.emitChangeWindow();