feat: workspace mode supports webview type views

This commit is contained in:
liujuping 2022-12-27 18:24:10 +08:00 committed by 林熠
parent 1342481942
commit 1f8d91f85f
17 changed files with 119 additions and 26 deletions

View File

@ -16,8 +16,10 @@ sidebar_position: 12
### importSchema(schema: IPublicTypeNodeSchema) ### importSchema(schema: IPublicTypeNodeSchema)
当前窗口导入 schema 当前窗口导入 schema
相关类型:[IPublicTypeNodeSchema](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/node-schema.ts)
### changeViewType(viewName: string) ### changeViewType(viewName: string)
修改当前窗口视图类型 修改当前窗口视图类型
### async save ### async save()
调用当前窗口视图保存钩子 调用当前窗口视图保存钩子

View File

@ -32,3 +32,5 @@ sidebar_position: 12
/** 注册资源 */ /** 注册资源 */
registerResourceType(resourceName: string, resourceType: 'editor', options: IPublicResourceOptions): void; registerResourceType(resourceName: string, resourceType: 'editor', options: IPublicResourceOptions): void;
``` ```
相关类型:[IPublicResourceOptions](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/resource-options.ts)

View File

@ -7,6 +7,9 @@ import { Area } from '../area';
export default class LeftArea extends Component<{ area: Area }> { export default class LeftArea extends Component<{ area: Area }> {
render() { render() {
const { area } = this.props; const { area } = this.props;
if (area.isEmpty()) {
return null;
}
return ( return (
<div className={classNames('lc-left-area', { <div className={classNames('lc-left-area', {
'lc-area-visible': area.visible, 'lc-area-visible': area.visible,

View File

@ -8,6 +8,9 @@ import { Panel } from '../widget/panel';
export default class RightArea extends Component<{ area: Area<any, Panel> }> { export default class RightArea extends Component<{ area: Area<any, Panel> }> {
render() { render() {
const { area } = this.props; const { area } = this.props;
if (area.isEmpty()) {
return null;
}
return ( return (
<div className={classNames('lc-right-area engine-tabpane', { <div className={classNames('lc-right-area engine-tabpane', {
'lc-area-visible': area.visible, 'lc-area-visible': area.visible,

View File

@ -7,6 +7,9 @@ import { Area } from '../area';
export default class TopArea extends Component<{ area: Area; itemClassName?: string }> { export default class TopArea extends Component<{ area: Area; itemClassName?: string }> {
render() { render() {
const { area, itemClassName } = this.props; const { area, itemClassName } = this.props;
if (area.isEmpty()) {
return null;
}
return ( return (
<div className={classNames('lc-top-area engine-actionpane', { <div className={classNames('lc-top-area engine-actionpane', {
'lc-area-visible': area.visible, 'lc-area-visible': area.visible,

View File

@ -154,6 +154,7 @@ body {
&.active { &.active {
z-index: 999; z-index: 999;
background: #edeff3;
} }
} }
} }

View File

@ -15,19 +15,25 @@ import { SkeletonContext } from '../context';
import { EditorConfig, PluginClassSet } from '@alilc/lowcode-types'; import { EditorConfig, PluginClassSet } from '@alilc/lowcode-types';
@observer @observer
export class Workbench extends Component<{ skeleton: Skeleton; config?: EditorConfig; components?: PluginClassSet; className?: string; topAreaItemClassName?: string }> { export class Workbench extends Component<{
skeleton: Skeleton;
config?: EditorConfig;
components?: PluginClassSet;
className?: string;
topAreaItemClassName?: string;
}> {
constructor(props: any) { constructor(props: any) {
super(props); super(props);
const { config, components, skeleton } = this.props; const { config, components, skeleton } = this.props;
skeleton.buildFromConfig(config, components); skeleton.buildFromConfig(config, components);
} }
// componentDidCatch(error: any) {
// globalContext.get(Editor).emit('editor.skeleton.workbench.error', error);
// }
render() { render() {
const { skeleton, className, topAreaItemClassName } = this.props; const {
skeleton,
className,
topAreaItemClassName,
} = this.props;
return ( return (
<div className={classNames('lc-workbench', className)}> <div className={classNames('lc-workbench', className)}>
<SkeletonContext.Provider value={this.props.skeleton}> <SkeletonContext.Provider value={this.props.skeleton}>

View File

@ -66,7 +66,7 @@ async function registryInnerPlugin(designer: Designer, editor: Editor, plugins:
await plugins.register(OutlinePlugin, {}, { autoInit: true }); await plugins.register(OutlinePlugin, {}, { autoInit: true });
await plugins.register(componentMetaParser(designer)); await plugins.register(componentMetaParser(designer));
await plugins.register(setterRegistry, {}, { autoInit: true }); await plugins.register(setterRegistry, {}, { autoInit: true });
await plugins.register(defaultPanelRegistry(editor, designer)); await plugins.register(defaultPanelRegistry(editor));
await plugins.register(builtinHotkey); await plugins.register(builtinHotkey);
} }

View File

@ -3,7 +3,7 @@ import { SettingsPrimaryPane } from '@alilc/lowcode-editor-skeleton';
import DesignerPlugin from '@alilc/lowcode-plugin-designer'; import DesignerPlugin from '@alilc/lowcode-plugin-designer';
// 注册默认的面板 // 注册默认的面板
export const defaultPanelRegistry = (editor: any, designer: any) => { export const defaultPanelRegistry = (editor: any) => {
const fun = (ctx: IPublicModelPluginContext) => { const fun = (ctx: IPublicModelPluginContext) => {
return { return {
init() { init() {

View File

@ -8,7 +8,5 @@ export interface IPublicModelWindow {
changeViewType(viewName: string): void; changeViewType(viewName: string): void;
/** 调用当前窗口视图保存钩子 */ /** 调用当前窗口视图保存钩子 */
save(): Promise<{ save(): Promise<any>;
[viewName: string]: IPublicTypeNodeSchema | any;
}>;
} }

View File

@ -8,6 +8,8 @@ export interface IPublicViewFunctions {
export interface IPublicEditorView { export interface IPublicEditorView {
/** 资源名字 */ /** 资源名字 */
viewName: string; viewName: string;
/** 资源类型 */
viewType?: 'editor' | 'webview';
(ctx: any): IPublicViewFunctions; (ctx: any): IPublicViewFunctions;
} }
@ -25,8 +27,12 @@ export interface IPublicResourceOptions {
editorViews: IPublicEditorView[]; editorViews: IPublicEditorView[];
/** save 钩子 */ /** save 钩子 */
save?: () => Promise<void>; save?: (schema: {
[viewName: string]: any;
}) => Promise<void>;
/** import 钩子 */ /** import 钩子 */
import?: () => Promise<void>; import?: (schema: any) => Promise<{
[viewName: string]: any;
}>;
} }

View File

@ -35,6 +35,7 @@ import {
import { getLogger } from '@alilc/lowcode-utils'; import { getLogger } from '@alilc/lowcode-utils';
import { Workspace as InnerWorkspace } from './index'; import { Workspace as InnerWorkspace } from './index';
import { EditorWindow } from './editor-window/context'; import { EditorWindow } from './editor-window/context';
export class BasicContext { export class BasicContext {
skeleton: Skeleton; skeleton: Skeleton;
plugins: Plugins; plugins: Plugins;

View File

@ -1,16 +1,22 @@
import { makeObservable, obx } from '@alilc/lowcode-editor-core'; import { makeObservable, obx } from '@alilc/lowcode-editor-core';
import { EditorViewOptions, EditorWindow, ViewFunctions } from '@alilc/lowcode-workspace'; import { IPublicEditorView, IPublicViewFunctions } from '@alilc/lowcode-types';
import { flow } from 'mobx'; import { flow } from 'mobx';
import { Workspace as InnerWorkspace } from '../';
import { BasicContext } from '../base-context'; import { BasicContext } from '../base-context';
import { EditorWindow } from '../editor-window/context';
import { getWebviewPlugin } from '../inner-plugins/webview';
export class Context extends BasicContext { export class Context extends BasicContext {
name = 'editor-view'; viewName = 'editor-view';
instance: ViewFunctions; instance: IPublicViewFunctions;
constructor(public workspace: any, public editorWindow: EditorWindow, public editorView: EditorViewOptions) { viewType: 'editor' | 'webview';
constructor(public workspace: InnerWorkspace, public editorWindow: EditorWindow, public editorView: IPublicEditorView) {
super(workspace, editorView.viewName, editorWindow); super(workspace, editorView.viewName, editorWindow);
this.name = editorView.viewName; this.viewType = editorView.viewType || 'editor';
this.viewName = editorView.viewName;
this.instance = editorView(this.innerPlugins._getLowCodePluginContext({ this.instance = editorView(this.innerPlugins._getLowCodePluginContext({
pluginName: 'any', pluginName: 'any',
})); }));
@ -31,8 +37,13 @@ export class Context extends BasicContext {
@obx isInit: boolean = false; @obx isInit: boolean = false;
init = flow(function* (this: any) { init = flow(function* (this: any) {
yield this.registerInnerPlugins(); if (this.viewType === 'webview') {
yield this.instance?.init(); const url = yield this.instance?.url?.();
yield this.plugins.register(getWebviewPlugin(url, this.viewName));
} else {
yield this.registerInnerPlugins();
}
yield this.instance?.init?.();
yield this.innerPlugins.init(); yield this.innerPlugins.init();
this.isInit = true; this.isInit = true;
}); });

View File

@ -3,11 +3,15 @@ import {
Workbench, Workbench,
} from '@alilc/lowcode-editor-skeleton'; } from '@alilc/lowcode-editor-skeleton';
import { Component } from 'react'; import { Component } from 'react';
import { Context } from './context';
export * from '../base-context'; export * from '../base-context';
@observer @observer
export class EditorView extends Component<any, any> { export class EditorView extends Component<{
editorView: Context;
active: boolean;
}, any> {
render() { render() {
const { active } = this.props; const { active } = this.props;
const editorView = this.props.editorView; const editorView = this.props.editorView;

View File

@ -12,6 +12,10 @@ export class EditorWindow {
async importSchema(schema: any) { async importSchema(schema: any) {
const newSchema = await this.resource.import(schema); const newSchema = await this.resource.import(schema);
if (!newSchema) {
return;
}
Object.keys(newSchema).forEach(key => { Object.keys(newSchema).forEach(key => {
const view = this.editorViews.get(key); const view = this.editorViews.get(key);
view?.project.importSchema(newSchema[key]); view?.project.importSchema(newSchema[key]);

View File

@ -0,0 +1,49 @@
import { IPublicModelPluginContext } from '@alilc/lowcode-types';
function DesignerView(props: {
url: string;
viewName: string;
}) {
return (
<div className="lc-designer lowcode-plugin-designer">
<div className="lc-project">
<div className="lc-simulator-shell">
<iframe
name={`webview-view-${props.viewName}`}
className="lc-simulator-content-frame"
style={{
height: '100%',
width: '100%',
}}
src={props.url}
/>
</div>
</div>
</div>
);
}
export function getWebviewPlugin(url: string, viewName: string) {
function webviewPlugin(ctx: IPublicModelPluginContext) {
const { skeleton } = ctx;
return {
init() {
skeleton.add({
area: 'mainArea',
name: 'designer',
type: 'Widget',
content: DesignerView,
contentProps: {
ctx,
url,
viewName,
},
});
},
};
}
webviewPlugin.pluginName = '___webview_plugin___';
return webviewPlugin;
}

View File

@ -1,7 +1,7 @@
import { EditorViewOptions, ResourceOptions } from '.'; import { IPublicEditorView, IPublicResourceOptions } from '@alilc/lowcode-types';
export class Resource { export class Resource {
constructor(options: ResourceOptions) { constructor(options: IPublicResourceOptions) {
if (options.editorViews) { if (options.editorViews) {
options.editorViews.forEach((d: any) => { options.editorViews.forEach((d: any) => {
this.editorViewMap.set(d.viewName, d); this.editorViewMap.set(d.viewName, d);
@ -11,9 +11,9 @@ export class Resource {
this.options = options; this.options = options;
} }
options: ResourceOptions; options: IPublicResourceOptions;
editorViewMap: Map<string, EditorViewOptions> = new Map<string, EditorViewOptions>(); editorViewMap: Map<string, IPublicEditorView> = new Map<string, IPublicEditorView>();
init(ctx: any) { init(ctx: any) {
this.options.init(ctx); this.options.init(ctx);