feat: added apis support resource tree in workspace mode

This commit is contained in:
liujuping 2023-01-09 17:18:30 +08:00 committed by 林熠
parent a37a647ef6
commit ea08173af0
25 changed files with 419 additions and 101 deletions

View File

@ -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) 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 模式,对于事件的绑定、快捷键的绑定函数,返回值则是解绑函数 3. 基于 Disposable 模式,对于事件的绑定、快捷键的绑定函数,返回值则是解绑函数
4. 对于属性的导出,统一用 .xxx 的 getter 模式,(尽量)不使用 .getXxx() 4. 对于属性的导出,统一用 .xxx 的 getter 模式,(尽量)不使用 .getXxx()
## experimental
说明此模块处于公测阶段, API 可能会发生改变.

View File

@ -1,5 +1,5 @@
--- ---
title: plugin-instance title: PluginInstance
sidebar_position: 12 sidebar_position: 12
--- ---

View File

@ -0,0 +1,26 @@
---
title: ResourceType
sidebar_position: 12
---
> **[@experimental](./#experimental)**<br/>
> **@types** [IPublicModelWindow](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/resource-type.ts)<br/>
> **@since** v1.1.0
## 变量
### description
资源描述
`@type {string}`
### icon
资源 icon
`@type {ReactElement}`
### name
`@type {string}`

View File

@ -0,0 +1,36 @@
---
title: Resource
sidebar_position: 12
---
> **[@experimental](./#experimental)**<br/>
> **@types** [IPublicModelWindow](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/resource.ts)<br/>
> **@since** v1.1.0
## 变量
### title
资源标题
`@type {string}`
### icon
资源 icon
`@type {ReactElement}`
### options
资源配置信息
`@type {Object}`
### resourceType
资源所属的资源类型
`@type {IPublicModelResourceType}`
关联模型 [IPublicModelResourceType](./resource-type)

View File

@ -3,6 +3,7 @@ title: Window
sidebar_position: 12 sidebar_position: 12
--- ---
> **[@experimental](./#experimental)**<br/>
> **@types** [IPublicModelWindow](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/window.ts)<br/> > **@types** [IPublicModelWindow](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/window.ts)<br/>
> **@since** v1.1.0 > **@since** v1.1.0
@ -17,13 +18,25 @@ sidebar_position: 12
窗口唯一 id 窗口唯一 id
`@type {string}`
### title ### title
窗口标题 窗口标题
### resourceName `@type {string}`
窗口资源名字 ### icon
`@type {ReactElement}`
### resourceType
窗口资源类型
`@type {IPublicModelResourceType}`
关联模型 [IPublicModelResourceType](./resource-type)
## 方法签名 ## 方法签名

View File

@ -222,7 +222,7 @@ your-plugin/package.json
} }
``` ```
转换后的结构: 转换后的结构:
```json ```typescript
const debug = (ctx: IPublicModelPluginContext, options: any) => { const debug = (ctx: IPublicModelPluginContext, options: any) => {
return {}; return {};
} }

View File

@ -3,10 +3,10 @@ title: workspace - 应用级 API
sidebar_position: 12 sidebar_position: 12
--- ---
> **[@experimental](./#experimental)**<br/>
> **@types** [IPublicApiWorkspace](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/api/workspace.ts)<br/> > **@types** [IPublicApiWorkspace](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/api/workspace.ts)<br/>
> **@since** v1.1.0 > **@since** v1.1.0
## 模块简介 ## 模块简介
通过该模块可以开发应用级低代码设计器。 通过该模块可以开发应用级低代码设计器。
@ -47,6 +47,16 @@ get window(): IPublicModelWindow[]
关联模型 [IPublicModelWindow](./model/window) 关联模型 [IPublicModelWindow](./model/window)
### resourceList
当前设计器的资源列表数据
```
get resourceList(): IPublicModelResource;
```
关联模型 [IPublicModelResource](./model/resource)
## 方法签名 ## 方法签名
### registerResourceType ### registerResourceType
@ -54,7 +64,7 @@ get window(): IPublicModelWindow[]
```typescript ```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) 相关类型:[IPublicResourceOptions](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/resource-options.ts)
@ -74,3 +84,55 @@ active 窗口变更事件
```typescript ```typescript
function onChangeActiveWindow(fn: () => void): void; 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;
```

View File

@ -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 { Workspace as InnerWorkSpace } from '@alilc/lowcode-workspace';
import { Plugins } from '@alilc/lowcode-shell'; import { Plugins } from '@alilc/lowcode-shell';
import { Window } from '../model/window'; import { Window } from '../model/window';
import { workspaceSymbol } from '../symbols'; import { workspaceSymbol } from '../symbols';
import { Resource } from '../model';
export class Workspace implements IPublicApiWorkspace { export class Workspace implements IPublicApiWorkspace {
readonly [workspaceSymbol]: InnerWorkSpace; readonly [workspaceSymbol]: InnerWorkSpace;
@ -11,6 +12,18 @@ export class Workspace implements IPublicApiWorkspace {
this[workspaceSymbol] = innerWorkspace; 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() { get isActive() {
return this[workspaceSymbol].isActive; return this[workspaceSymbol].isActive;
} }
@ -19,12 +32,12 @@ export class Workspace implements IPublicApiWorkspace {
return new Window(this[workspaceSymbol].window); return new Window(this[workspaceSymbol].window);
} }
registerResourceType(resourceName: string, resourceType: 'editor', options: any): void { registerResourceType(name: string, type: 'editor', options: IPublicResourceOptions): void {
this[workspaceSymbol].registerResourceType(resourceName, resourceType, options); this[workspaceSymbol].registerResourceType(name, type, options);
} }
openEditorWindow(resourceName: string, title: string, viewType?: string) { openEditorWindow(resourceName: string, title: string, extra: Object, viewName?: string) {
this[workspaceSymbol].openEditorWindow(resourceName, title, viewType); this[workspaceSymbol].openEditorWindow(resourceName, title, extra, viewName);
} }
openEditorWindowById(id: string) { openEditorWindowById(id: string) {

View File

@ -13,4 +13,6 @@ export * from './prop';
export * from './props'; export * from './props';
export * from './selection'; export * from './selection';
export * from './setting-prop-entry'; export * from './setting-prop-entry';
export * from './setting-top-entry'; export * from './setting-top-entry';
export * from './resource';
export * from './resource-type';

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -1,6 +1,7 @@
import { windowSymbol } from '../symbols'; import { windowSymbol } from '../symbols';
import { IPublicModelWindow } from '@alilc/lowcode-types'; import { IPublicModelWindow } from '@alilc/lowcode-types';
import { EditorWindow } from '@alilc/lowcode-workspace'; import { EditorWindow } from '@alilc/lowcode-workspace';
import { ResourceType } from './resource-type';
export class Window implements IPublicModelWindow { export class Window implements IPublicModelWindow {
private readonly [windowSymbol]: EditorWindow; private readonly [windowSymbol]: EditorWindow;
@ -17,8 +18,8 @@ export class Window implements IPublicModelWindow {
return this[windowSymbol].icon; return this[windowSymbol].icon;
} }
get resourceName() { get resourceType(): ResourceType {
return this[windowSymbol].resourceName; return new ResourceType(this[windowSymbol].resourceType);
} }
constructor(editorWindow: EditorWindow) { constructor(editorWindow: EditorWindow) {

View File

@ -28,4 +28,6 @@ export const hotkeySymbol = Symbol('hotkey');
export const pluginsSymbol = Symbol('plugins'); export const pluginsSymbol = Symbol('plugins');
export const workspaceSymbol = Symbol('workspace'); export const workspaceSymbol = Symbol('workspace');
export const windowSymbol = Symbol('window'); export const windowSymbol = Symbol('window');
export const pluginInstanceSymbol = Symbol('plugin-instance'); export const pluginInstanceSymbol = Symbol('plugin-instance');
export const resourceTypeSymbol = Symbol('resourceType');
export const resourceSymbol = Symbol('resource');

View File

@ -1,23 +1,39 @@
import { IPublicModelWindow } from '../model'; import { IPublicModelWindow } from '../model';
import { IPublicResourceOptions } from '../type'; import { IPublicResourceOptions } from '../type';
import { IPublicApiPlugins } from '@alilc/lowcode-types'; import { IPublicApiPlugins, IPublicModelResource, IPublicResourceList } from '@alilc/lowcode-types';
export interface IPublicApiWorkspace { export interface IPublicApiWorkspace {
/** 是否启用 workspace 模式 */ /** 是否启用 workspace 模式 */
isActive: boolean; isActive: boolean;
/** 当前设计器窗口 */ /** 当前设计器窗口 */
window: IPublicModelWindow; 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; removeEditorWindow(resourceName: string, title: string): void;
/** 通过视图 id 移除窗口 */
removeEditorWindowById(id: string): void;
plugins: IPublicApiPlugins; plugins: IPublicApiPlugins;
/** 当前设计器的编辑窗口 */ /** 当前设计器的编辑窗口 */

View File

@ -27,4 +27,6 @@ export * from './engine-config';
export * from './editor'; export * from './editor';
export * from './preference'; export * from './preference';
export * from './plugin-instance'; export * from './plugin-instance';
export * from './sensor'; export * from './sensor';
export * from './resource-type';
export * from './resource';

View File

@ -0,0 +1,7 @@
import { ReactElement } from 'react';
export interface IPublicModelResourceType {
get description(): string | undefined;
get icon(): ReactElement | undefined;
}

View File

@ -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;
}

View File

@ -1,6 +1,9 @@
import { ReactElement } from 'react';
import { IPublicTypeNodeSchema } from '../type'; import { IPublicTypeNodeSchema } from '../type';
import { IPublicModelResourceType } from './resource-type';
export interface IPublicModelWindow { export interface IPublicModelWindow {
/** 当前窗口导入 schema */ /** 当前窗口导入 schema */
importSchema(schema: IPublicTypeNodeSchema): void; importSchema(schema: IPublicTypeNodeSchema): void;
@ -16,6 +19,9 @@ export interface IPublicModelWindow {
/** 窗口标题 */ /** 窗口标题 */
title?: string; title?: string;
/** 窗口资源名字 */ /** 窗口 icon */
resourceName?: string; icon?: ReactElement;
/** 窗口资源类型 */
resourceType?: IPublicModelResourceType;
} }

View File

@ -1,21 +1,23 @@
export interface IPublicViewFunctions { export interface IPublicViewFunctions {
/** 视图初始化钩子 */ /** 视图初始化钩子 */
init?: () => Promise<void>; init?: () => Promise<void>;
/** 资源保存时,会调用视图的钩子 */ /** 资源保存时,会调用视图的钩子 */
save?: () => Promise<void>; save?: () => Promise<void>;
} }
export interface IPublicEditorView { export interface IPublicEditorView {
/** 资源名字 */ /** 资源名字 */
viewName: string; viewName: string;
/** 资源类型 */ /** 资源类型 */
viewType?: 'editor' | 'webview'; viewType?: 'editor' | 'webview';
(ctx: any): IPublicViewFunctions; (ctx: any, options: any): IPublicViewFunctions;
} }
export interface IPublicResourceOptions { export interface IPublicResourceOptions {
/** 资源名字 */
name: string;
/** 资源描述 */ /** 资源描述 */
description?: string; description?: string;
@ -41,4 +43,14 @@ export interface IPublicResourceOptions {
/** 默认标题 */ /** 默认标题 */
defaultTitle?: string; defaultTitle?: string;
} }
export interface IPublicResourceData {
resourceName: string;
title: string;
options: {
[key: string]: any;
};
}
export type IPublicResourceList = IPublicResourceData[];

View File

@ -13,13 +13,13 @@ export class Context extends BasicContext {
viewType: 'editor' | 'webview'; 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); super(workspace, editorView.viewName, editorWindow);
this.viewType = editorView.viewType || 'editor'; this.viewType = editorView.viewType || 'editor';
this.viewName = editorView.viewName; this.viewName = editorView.viewName;
this.instance = editorView(this.innerPlugins._getLowCodePluginContext({ this.instance = editorView(this.innerPlugins._getLowCodePluginContext({
pluginName: 'any', pluginName: 'any',
})); }), options);
makeObservable(this); makeObservable(this);
} }

View File

@ -2,24 +2,20 @@ import { uniqueId } from '@alilc/lowcode-utils';
import { makeObservable, obx } from '@alilc/lowcode-editor-core'; import { makeObservable, obx } from '@alilc/lowcode-editor-core';
import { Context } from '../editor-view/context'; import { Context } from '../editor-view/context';
import { Workspace } from '../workspace'; import { Workspace } from '../workspace';
import { Resource } from '../resource'; import { ResourceType } from '../resource-type';
export class EditorWindow { export class EditorWindow {
id: string = uniqueId('window'); id: string = uniqueId('window');
icon: React.ReactElement | undefined; 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); makeObservable(this);
this.init(); this.init();
this.icon = resource.icon; this.icon = resourceType.icon;
}
get resourceName(): string {
return this.resource.options.name;
} }
async importSchema(schema: any) { async importSchema(schema: any) {
const newSchema = await this.resource.import(schema); const newSchema = await this.resourceType.import(schema);
if (!newSchema) { if (!newSchema) {
return; return;
@ -33,13 +29,13 @@ export class EditorWindow {
async save() { async save() {
const value: any = {}; const value: any = {};
const editorViews = this.resource.editorViews; const editorViews = this.resourceType.editorViews;
for (let i = 0; i < editorViews.length; i++) { for (let i = 0; i < editorViews.length; i++) {
const name = editorViews[i].viewName; const name = editorViews[i].viewName;
const saveResult = await this.editorViews.get(name)?.save(); const saveResult = await this.editorViews.get(name)?.save();
value[name] = saveResult; value[name] = saveResult;
} }
return await this.resource.save(value); return await this.resourceType.save(value);
} }
async init() { async init() {
@ -49,7 +45,7 @@ export class EditorWindow {
} }
initViewTypes = async () => { initViewTypes = async () => {
const editorViews = this.resource.editorViews; const editorViews = this.resourceType.editorViews;
for (let i = 0; i < editorViews.length; i++) { for (let i = 0; i < editorViews.length; i++) {
const name = editorViews[i].viewName; const name = editorViews[i].viewName;
await this.initViewType(name); await this.initViewType(name);
@ -60,7 +56,7 @@ export class EditorWindow {
}; };
execViewTypesInit = async () => { execViewTypesInit = async () => {
const editorViews = this.resource.editorViews; const editorViews = this.resourceType.editorViews;
for (let i = 0; i < editorViews.length; i++) { for (let i = 0; i < editorViews.length; i++) {
const name = editorViews[i].viewName; const name = editorViews[i].viewName;
this.changeViewType(name); this.changeViewType(name);
@ -69,7 +65,7 @@ export class EditorWindow {
}; };
setDefaultViewType = () => { setDefaultViewType = () => {
this.changeViewType(this.resource.defaultViewType); this.changeViewType(this.resourceType.defaultViewType);
}; };
@obx.ref editorView: Context; @obx.ref editorView: Context;
@ -77,11 +73,11 @@ export class EditorWindow {
@obx editorViews: Map<string, Context> = new Map<string, Context>(); @obx editorViews: Map<string, Context> = new Map<string, Context>();
initViewType = async (name: string) => { initViewType = async (name: string) => {
const viewInfo = this.resource.getEditorView(name); const viewInfo = this.resourceType.getEditorView(name);
if (this.editorViews.get(name)) { if (this.editorViews.get(name)) {
return; 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); this.editorViews.set(name, editorView);
}; };

View File

@ -1,4 +1,5 @@
export { Workspace } from './workspace'; export { Workspace } from './workspace';
export { Resource } from './resource'; export { ResourceType } from './resource-type';
export * from './editor-window/context'; export * from './editor-window/context';
export * from './layouts/workbench'; export * from './layouts/workbench';
export { Resource } from './resource';

View File

@ -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<string, IPublicEditorView> = new Map<string, IPublicEditorView>();
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;
}
}

View File

@ -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 { const logger = new Logger({ level: 'warn', bizName: 'workspace:resource' });
constructor(options: IPublicResourceOptions) {
if (options.editorViews) { export class Resource implements IPublicModelResource {
options.editorViews.forEach((d: any) => { constructor(readonly resourceData: IPublicResourceData, readonly resourceType: ResourceType) {
this.editorViewMap.set(d.viewName, d); if (!resourceType) {
}); logger.error(`resourceType[${resourceType}] is unValid.`);
} }
this.options = options;
}
options: IPublicResourceOptions;
editorViewMap: Map<string, IPublicEditorView> = new Map<string, IPublicEditorView>();
init(ctx: any) {
this.options.init(ctx);
} }
get icon() { get icon() {
return this.options.icon; return this.resourceType?.icon;
} }
async import(schema: any) { get type() {
return await this.options.import?.(schema); return this.resourceData.resourceName;
}
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() { get title() {
return this.options.defaultTitle; return this.resourceData.title;
}
get options() {
return this.resourceData.options;
} }
} }

View File

@ -1,10 +1,11 @@
import { Designer } from '@alilc/lowcode-designer'; import { Designer } from '@alilc/lowcode-designer';
import { createModuleEventBus, Editor, IEventBus, makeObservable, obx } from '@alilc/lowcode-editor-core'; import { createModuleEventBus, Editor, IEventBus, makeObservable, obx } from '@alilc/lowcode-editor-core';
import { Plugins } from '@alilc/lowcode-shell'; 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 { BasicContext } from './base-context';
import { EditorWindow } from './editor-window/context'; import { EditorWindow } from './editor-window/context';
import { Resource } from './resource'; import { Resource } from './resource';
import { ResourceType } from './resource-type';
enum event { enum event {
ChangeWindow = 'change_window', ChangeWindow = 'change_window',
@ -12,6 +13,8 @@ enum event {
ChangeActiveWindow = 'change_active_window', ChangeActiveWindow = 'change_active_window',
} }
const CHANGE_EVENT = 'resource.list.change';
export class Workspace implements IPublicApiWorkspace { export class Workspace implements IPublicApiWorkspace {
private context: BasicContext; private context: BasicContext;
@ -42,7 +45,7 @@ export class Workspace implements IPublicApiWorkspace {
if (!this.defaultResource) { if (!this.defaultResource) {
return; return;
} }
const title = this.defaultResource.title; const title = this.defaultResource.description;
this.window = new EditorWindow(this.defaultResource, this, title); this.window = new EditorWindow(this.defaultResource, this, title);
this.editorWindowMap.set(this.window.id, this.window); this.editorWindowMap.set(this.window.id, this.window);
this.windows.push(this.window); this.windows.push(this.window);
@ -50,7 +53,6 @@ export class Workspace implements IPublicApiWorkspace {
this.emitChangeActiveWindow(); this.emitChangeActiveWindow();
} }
private _isActive = false; private _isActive = false;
get isActive() { get isActive() {
@ -67,12 +69,14 @@ export class Workspace implements IPublicApiWorkspace {
@obx.ref window: EditorWindow; @obx.ref window: EditorWindow;
private resources: Map<string, Resource> = new Map(); private resourceTypeMap: Map<string, ResourceType> = new Map();
async registerResourceType(resourceName: string, resourceType: 'editor' | 'webview', options: IPublicResourceOptions): Promise<void> { private resourceList: Resource[] = [];
if (resourceType === 'editor') {
const resource = new Resource(options); async registerResourceType(resourceName: string, type: 'editor' | 'webview', options: IPublicResourceOptions): Promise<void> {
this.resources.set(resourceName, resource); if (type === 'editor') {
const resourceType = new ResourceType(resourceName, type, options);
this.resourceTypeMap.set(resourceName, resourceType);
if (!this.window && this.defaultResource) { if (!this.window && this.defaultResource) {
this.initWindow(); this.initWindow();
@ -80,17 +84,37 @@ export class Workspace implements IPublicApiWorkspace {
} }
} }
get defaultResource(): Resource | null { getResourceList() {
if (this.resources.size > 1) { return this.resourceList;
return this.resources.values().next().value; }
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; return null;
} }
removeResourceType(resourceName: string) { removeResourceType(resourceName: string) {
if (this.resources.has(resourceName)) { if (this.resourceTypeMap.has(resourceName)) {
this.resources.delete(resourceName); this.resourceTypeMap.delete(resourceName);
} }
} }
@ -110,7 +134,7 @@ export class Workspace implements IPublicApiWorkspace {
} }
removeEditorWindow(resourceName: string, title: string) { 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); this.remove(index);
} }
@ -122,19 +146,19 @@ export class Workspace implements IPublicApiWorkspace {
} }
} }
openEditorWindow(resourceName: string, title: string, viewType?: string) { openEditorWindow(name: string, title: string, options: Object, viewType?: string) {
const resource = this.resources.get(resourceName); const resourceType = this.resourceTypeMap.get(name);
if (!resource) { if (!resourceType) {
console.error(`${resourceName} is not available`); console.error(`${name} is not available`);
return; 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) { if (filterWindows && filterWindows.length) {
this.window = filterWindows[0]; this.window = filterWindows[0];
this.emitChangeActiveWindow(); this.emitChangeActiveWindow();
return; return;
} }
this.window = new EditorWindow(resource, this, title); this.window = new EditorWindow(resourceType, this, title, options);
this.windows.push(this.window); this.windows.push(this.window);
this.editorWindowMap.set(this.window.id, this.window); this.editorWindowMap.set(this.window.id, this.window);
this.emitChangeWindow(); this.emitChangeWindow();