mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-13 20:36:34 +00:00
fix: fix workspace api ts defined
This commit is contained in:
parent
12a22de169
commit
6d4ca29466
@ -52,6 +52,6 @@ module.exports = {
|
|||||||
'error',
|
'error',
|
||||||
{ default: ['signature', 'field', 'constructor', 'method'] }
|
{ default: ['signature', 'field', 'constructor', 'method'] }
|
||||||
],
|
],
|
||||||
'no-unused-vars': ['error', { "destructuredArrayIgnorePattern": "^_" }]
|
'@typescript-eslint/no-unused-vars': ['error']
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,9 +13,9 @@ import { observer, computed, Tip, globalContext } from '@alilc/lowcode-editor-co
|
|||||||
import { createIcon, isReactComponent, isActionContentObject } from '@alilc/lowcode-utils';
|
import { createIcon, isReactComponent, isActionContentObject } from '@alilc/lowcode-utils';
|
||||||
import { IPublicTypeActionContentObject } from '@alilc/lowcode-types';
|
import { IPublicTypeActionContentObject } from '@alilc/lowcode-types';
|
||||||
import { BuiltinSimulatorHost } from '../host';
|
import { BuiltinSimulatorHost } from '../host';
|
||||||
import { OffsetObserver } from '../../designer';
|
import { INode, OffsetObserver } from '../../designer';
|
||||||
import { Node } from '../../document';
|
|
||||||
import NodeSelector from '../node-selector';
|
import NodeSelector from '../node-selector';
|
||||||
|
import { ISimulatorHost } from '../../simulator';
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class BorderSelectingInstance extends Component<{
|
export class BorderSelectingInstance extends Component<{
|
||||||
@ -116,8 +116,8 @@ class Toolbar extends Component<{ observed: OffsetObserver }> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAction(content: ReactNode | ComponentType<any> | IPublicTypeActionContentObject, key: string, node: Node) {
|
function createAction(content: ReactNode | ComponentType<any> | IPublicTypeActionContentObject, key: string, node: INode) {
|
||||||
if (isValidElement(content)) {
|
if (isValidElement<{ key: string; node: INode }>(content)) {
|
||||||
return cloneElement(content, { key, node });
|
return cloneElement(content, { key, node });
|
||||||
}
|
}
|
||||||
if (isReactComponent(content)) {
|
if (isReactComponent(content)) {
|
||||||
@ -130,7 +130,7 @@ function createAction(content: ReactNode | ComponentType<any> | IPublicTypeActio
|
|||||||
key={key}
|
key={key}
|
||||||
className="lc-borders-action"
|
className="lc-borders-action"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
action && action(node);
|
action && action(node.internalToShellNode()!);
|
||||||
const workspace = globalContext.get('workspace');
|
const workspace = globalContext.get('workspace');
|
||||||
const editor = workspace.isActive ? workspace.window.editor : globalContext.get('editor');
|
const editor = workspace.isActive ? workspace.window.editor : globalContext.get('editor');
|
||||||
const npm = node?.componentMeta?.npm;
|
const npm = node?.componentMeta?.npm;
|
||||||
@ -153,8 +153,8 @@ function createAction(content: ReactNode | ComponentType<any> | IPublicTypeActio
|
|||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class BorderSelectingForNode extends Component<{ host: BuiltinSimulatorHost; node: Node }> {
|
export class BorderSelectingForNode extends Component<{ host: ISimulatorHost; node: INode }> {
|
||||||
get host(): BuiltinSimulatorHost {
|
get host(): ISimulatorHost {
|
||||||
return this.props.host;
|
return this.props.host;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -47,26 +47,26 @@ import {
|
|||||||
getRectTarget,
|
getRectTarget,
|
||||||
CanvasPoint,
|
CanvasPoint,
|
||||||
Designer,
|
Designer,
|
||||||
|
IDesigner,
|
||||||
} from '../designer';
|
} from '../designer';
|
||||||
import { parseMetadata } from './utils/parse-metadata';
|
import { parseMetadata } from './utils/parse-metadata';
|
||||||
import { getClosestClickableNode } from './utils/clickable';
|
import { getClosestClickableNode } from './utils/clickable';
|
||||||
import {
|
import {
|
||||||
IPublicTypeComponentMetadata,
|
IPublicTypeComponentMetadata,
|
||||||
IPublicTypeComponentSchema,
|
|
||||||
IPublicTypePackage,
|
IPublicTypePackage,
|
||||||
IPublicEnumTransitionType,
|
IPublicEnumTransitionType,
|
||||||
IPublicEnumDragObjectType,
|
IPublicEnumDragObjectType,
|
||||||
IPublicTypeDragNodeObject,
|
|
||||||
IPublicTypeNodeInstance,
|
IPublicTypeNodeInstance,
|
||||||
IPublicTypeComponentInstance,
|
IPublicTypeComponentInstance,
|
||||||
IPublicTypeLocationChildrenDetail,
|
IPublicTypeLocationChildrenDetail,
|
||||||
IPublicTypeLocationDetailType,
|
IPublicTypeLocationDetailType,
|
||||||
IPublicTypeRect,
|
IPublicTypeRect,
|
||||||
|
IPublicModelNode,
|
||||||
} from '@alilc/lowcode-types';
|
} from '@alilc/lowcode-types';
|
||||||
import { BuiltinSimulatorRenderer } from './renderer';
|
import { BuiltinSimulatorRenderer } from './renderer';
|
||||||
import { clipboard } from '../designer/clipboard';
|
import { clipboard } from '../designer/clipboard';
|
||||||
import { LiveEditing } from './live-editing/live-editing';
|
import { LiveEditing } from './live-editing/live-editing';
|
||||||
import { Project } from '../project';
|
import { IProject, Project } from '../project';
|
||||||
import { IScroller } from '../designer/scroller';
|
import { IScroller } from '../designer/scroller';
|
||||||
import { isElementNode, isDOMNodeVisible } from '../utils/misc';
|
import { isElementNode, isDOMNodeVisible } from '../utils/misc';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
@ -164,9 +164,9 @@ const defaultRaxEnvironment = [
|
|||||||
export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProps> {
|
export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProps> {
|
||||||
readonly isSimulator = true;
|
readonly isSimulator = true;
|
||||||
|
|
||||||
readonly project: Project;
|
readonly project: IProject;
|
||||||
|
|
||||||
readonly designer: Designer;
|
readonly designer: IDesigner;
|
||||||
|
|
||||||
readonly viewport = new Viewport();
|
readonly viewport = new Viewport();
|
||||||
|
|
||||||
@ -217,7 +217,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
return this.get('requestHandlersMap') || null;
|
return this.get('requestHandlersMap') || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
get thisRequiredInJSE(): any {
|
get thisRequiredInJSE(): boolean {
|
||||||
return engineConfig.get('thisRequiredInJSE') ?? true;
|
return engineConfig.get('thisRequiredInJSE') ?? true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,8 +559,8 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// FIXME: dirty fix remove label-for fro liveEditing
|
// FIXME: dirty fix remove label-for fro liveEditing
|
||||||
(downEvent.target as HTMLElement).removeAttribute('for');
|
downEvent.target?.removeAttribute('for');
|
||||||
const nodeInst = this.getNodeInstanceFromElement(downEvent.target as Element);
|
const nodeInst = this.getNodeInstanceFromElement(downEvent.target);
|
||||||
const { focusNode } = documentModel;
|
const { focusNode } = documentModel;
|
||||||
const node = getClosestClickableNode(nodeInst?.node || focusNode, downEvent);
|
const node = getClosestClickableNode(nodeInst?.node || focusNode, downEvent);
|
||||||
// 如果找不到可点击的节点,直接返回
|
// 如果找不到可点击的节点,直接返回
|
||||||
@ -675,11 +675,11 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
const x = new Event('click');
|
const x = new Event('click');
|
||||||
x.initEvent('click', true);
|
x.initEvent('click', true);
|
||||||
this._iframe?.dispatchEvent(x);
|
this._iframe?.dispatchEvent(x);
|
||||||
const target = e.target as HTMLElement;
|
const target = e.target;
|
||||||
|
|
||||||
const customizeIgnoreSelectors = engineConfig.get('customizeIgnoreSelectors');
|
const customizeIgnoreSelectors = engineConfig.get('customizeIgnoreSelectors');
|
||||||
// TODO: need more elegant solution to ignore click events of components in designer
|
// TODO: need more elegant solution to ignore click events of components in designer
|
||||||
const defaultIgnoreSelectors: any = [
|
const defaultIgnoreSelectors: string[] = [
|
||||||
'.next-input-group',
|
'.next-input-group',
|
||||||
'.next-checkbox-group',
|
'.next-checkbox-group',
|
||||||
'.next-checkbox-wrapper',
|
'.next-checkbox-wrapper',
|
||||||
@ -741,7 +741,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const leave = () => {
|
const leave = () => {
|
||||||
this.project.currentDocument && detecting.leave(this.project.currentDocument)
|
this.project.currentDocument && detecting.leave(this.project.currentDocument);
|
||||||
};
|
};
|
||||||
|
|
||||||
doc.addEventListener('mouseover', hover, true);
|
doc.addEventListener('mouseover', hover, true);
|
||||||
@ -812,7 +812,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
/**
|
/**
|
||||||
* @see ISimulator
|
* @see ISimulator
|
||||||
*/
|
*/
|
||||||
setSuspense(suspended: boolean) {
|
setSuspense(/** _suspended: boolean */) {
|
||||||
return false;
|
return false;
|
||||||
// if (suspended) {
|
// if (suspended) {
|
||||||
// /*
|
// /*
|
||||||
@ -897,7 +897,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
return this.renderer?.getComponent(componentName) || null;
|
return this.renderer?.getComponent(componentName) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
createComponent(schema: IPublicTypeComponentSchema): Component | null {
|
createComponent(/** _schema: IPublicTypeComponentSchema */): Component | null {
|
||||||
return null;
|
return null;
|
||||||
// return this.renderer?.createComponent(schema) || null;
|
// return this.renderer?.createComponent(schema) || null;
|
||||||
}
|
}
|
||||||
@ -1018,7 +1018,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (last) {
|
if (last) {
|
||||||
const r: any = new DOMRect(last.x, last.y, last.r - last.x, last.b - last.y);
|
const r: IPublicTypeRect = new DOMRect(last.x, last.y, last.r - last.x, last.b - last.y);
|
||||||
r.elements = elements;
|
r.elements = elements;
|
||||||
r.computed = _computed;
|
r.computed = _computed;
|
||||||
return r;
|
return r;
|
||||||
@ -1186,13 +1186,14 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
*/
|
*/
|
||||||
locate(e: ILocateEvent): any {
|
locate(e: ILocateEvent): any {
|
||||||
const { dragObject } = e;
|
const { dragObject } = e;
|
||||||
const { nodes } = dragObject as IPublicTypeDragNodeObject;
|
|
||||||
|
const nodes = dragObject?.nodes;
|
||||||
|
|
||||||
const operationalNodes = nodes?.filter((node) => {
|
const operationalNodes = nodes?.filter((node) => {
|
||||||
const onMoveHook = node.componentMeta?.advanced.callbacks?.onMoveHook;
|
const onMoveHook = node.componentMeta?.advanced.callbacks?.onMoveHook;
|
||||||
const canMove = onMoveHook && typeof onMoveHook === 'function' ? onMoveHook(node.internalToShellNode()) : true;
|
const canMove = onMoveHook && typeof onMoveHook === 'function' ? onMoveHook(node.internalToShellNode()) : true;
|
||||||
|
|
||||||
let parentContainerNode: Node | null = null;
|
let parentContainerNode: INode | null = null;
|
||||||
let parentNode = node.parent;
|
let parentNode = node.parent;
|
||||||
|
|
||||||
while (parentNode) {
|
while (parentNode) {
|
||||||
@ -1254,7 +1255,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
};
|
};
|
||||||
|
|
||||||
const locationData = {
|
const locationData = {
|
||||||
target: container as INode,
|
target: container,
|
||||||
detail,
|
detail,
|
||||||
source: `simulator${document.id}`,
|
source: `simulator${document.id}`,
|
||||||
event: e,
|
event: e,
|
||||||
@ -1279,12 +1280,12 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
return this.designer.createLocation(locationData);
|
return this.designer.createLocation(locationData);
|
||||||
}
|
}
|
||||||
|
|
||||||
let nearRect = null;
|
let nearRect: IPublicTypeRect | null = null;
|
||||||
let nearIndex = 0;
|
let nearIndex: number = 0;
|
||||||
let nearNode = null;
|
let nearNode: INode | null = null;
|
||||||
let nearDistance = null;
|
let nearDistance: number | null = null;
|
||||||
let minTop = null;
|
let minTop: number | null = null;
|
||||||
let maxBottom = null;
|
let maxBottom: number | null = null;
|
||||||
|
|
||||||
for (let i = 0, l = children.size; i < l; i++) {
|
for (let i = 0, l = children.size; i < l; i++) {
|
||||||
const node = children.get(i)!;
|
const node = children.get(i)!;
|
||||||
@ -1341,8 +1342,13 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
const vertical = inline || row;
|
const vertical = inline || row;
|
||||||
|
|
||||||
// TODO: fix type
|
// TODO: fix type
|
||||||
const near: any = {
|
const near: {
|
||||||
node: nearNode,
|
node: IPublicModelNode;
|
||||||
|
pos: 'before' | 'after' | 'replace';
|
||||||
|
rect?: IPublicTypeRect;
|
||||||
|
align?: 'V' | 'H';
|
||||||
|
} = {
|
||||||
|
node: nearNode.internalToShellNode()!,
|
||||||
pos: 'before',
|
pos: 'before',
|
||||||
align: vertical ? 'V' : 'H',
|
align: vertical ? 'V' : 'H',
|
||||||
};
|
};
|
||||||
@ -1465,7 +1471,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
container = container.parent;
|
container = container.parent;
|
||||||
instance = this.getClosestNodeInstance(dropContainer.instance, container.id)?.instance;
|
instance = this.getClosestNodeInstance(dropContainer.instance, container.id)?.instance;
|
||||||
dropContainer = {
|
dropContainer = {
|
||||||
container: container,
|
container,
|
||||||
instance,
|
instance,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
@ -1483,12 +1489,12 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
/**
|
/**
|
||||||
* 控制接受
|
* 控制接受
|
||||||
*/
|
*/
|
||||||
handleAccept({ container, instance }: DropContainer, e: ILocateEvent): boolean {
|
handleAccept({ container }: DropContainer, e: ILocateEvent): boolean {
|
||||||
const { dragObject } = e;
|
const { dragObject } = e;
|
||||||
const document = this.currentDocument!;
|
const document = this.currentDocument!;
|
||||||
const focusNode = document.focusNode;
|
const focusNode = document.focusNode;
|
||||||
if (isRootNode(container) || container.contains(focusNode)) {
|
if (isRootNode(container) || container.contains(focusNode)) {
|
||||||
return document.checkNesting(focusNode, dragObject as any);
|
return document.checkNesting(focusNode!, dragObject as any);
|
||||||
}
|
}
|
||||||
|
|
||||||
const meta = (container as Node).componentMeta;
|
const meta = (container as Node).componentMeta;
|
||||||
@ -1509,15 +1515,12 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
getNearByContainer(
|
getNearByContainer(
|
||||||
{ container, instance }: DropContainer,
|
{ container, instance }: DropContainer,
|
||||||
drillDownExcludes: Set<INode>,
|
drillDownExcludes: Set<INode>,
|
||||||
e: ILocateEvent,
|
|
||||||
) {
|
) {
|
||||||
const { children } = container;
|
const { children } = container;
|
||||||
const document = this.project.currentDocument!;
|
|
||||||
if (!children || children.isEmpty()) {
|
if (!children || children.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const nearDistance: any = null;
|
|
||||||
const nearBy: any = null;
|
const nearBy: any = null;
|
||||||
for (let i = 0, l = children.size; i < l; i++) {
|
for (let i = 0, l = children.size; i < l; i++) {
|
||||||
let child = children.get(i);
|
let child = children.get(i);
|
||||||
|
|||||||
@ -1,19 +1,19 @@
|
|||||||
import { Overlay } from '@alifd/next';
|
import { Overlay } from '@alifd/next';
|
||||||
import React from 'react';
|
import React, { MouseEvent } from 'react';
|
||||||
import { Title, globalContext } from '@alilc/lowcode-editor-core';
|
import { Title, globalContext } from '@alilc/lowcode-editor-core';
|
||||||
import { canClickNode } from '@alilc/lowcode-utils';
|
import { canClickNode } from '@alilc/lowcode-utils';
|
||||||
import './index.less';
|
import './index.less';
|
||||||
|
|
||||||
import { Node, INode } from '@alilc/lowcode-designer';
|
import { INode } from '@alilc/lowcode-designer';
|
||||||
|
|
||||||
const { Popup } = Overlay;
|
const { Popup } = Overlay;
|
||||||
|
|
||||||
export interface IProps {
|
export interface IProps {
|
||||||
node: Node;
|
node: INode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IState {
|
export interface IState {
|
||||||
parentNodes: Node[];
|
parentNodes: INode[];
|
||||||
}
|
}
|
||||||
|
|
||||||
type UnionNode = INode | null;
|
type UnionNode = INode | null;
|
||||||
@ -26,14 +26,18 @@ export default class InstanceNodeSelector extends React.Component<IProps, IState
|
|||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const parentNodes = this.getParentNodes(this.props.node);
|
const parentNodes = this.getParentNodes(this.props.node);
|
||||||
this.setState({
|
this.setState({
|
||||||
parentNodes,
|
parentNodes: parentNodes ?? [],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取节点的父级节点(最多获取 5 层)
|
// 获取节点的父级节点(最多获取 5 层)
|
||||||
getParentNodes = (node: Node) => {
|
getParentNodes = (node: INode) => {
|
||||||
const parentNodes: any[] = [];
|
const parentNodes: any[] = [];
|
||||||
const { focusNode } = node.document;
|
const focusNode = node.document?.focusNode;
|
||||||
|
|
||||||
|
if (!focusNode) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (node.contains(focusNode) || !focusNode.contains(node)) {
|
if (node.contains(focusNode) || !focusNode.contains(node)) {
|
||||||
return parentNodes;
|
return parentNodes;
|
||||||
@ -53,12 +57,12 @@ export default class InstanceNodeSelector extends React.Component<IProps, IState
|
|||||||
return parentNodes;
|
return parentNodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
onSelect = (node: Node) => (e: unknown) => {
|
onSelect = (node: INode) => (event: MouseEvent) => {
|
||||||
if (!node) {
|
if (!node) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canClick = canClickNode(node, e as MouseEvent);
|
const canClick = canClickNode(node.internalToShellNode()!, event);
|
||||||
|
|
||||||
if (canClick && typeof node.select === 'function') {
|
if (canClick && typeof node.select === 'function') {
|
||||||
node.select();
|
node.select();
|
||||||
@ -76,19 +80,19 @@ export default class InstanceNodeSelector extends React.Component<IProps, IState
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onMouseOver = (node: Node) => (_: any, flag = true) => {
|
onMouseOver = (node: INode) => (_: any, flag = true) => {
|
||||||
if (node && typeof node.hover === 'function') {
|
if (node && typeof node.hover === 'function') {
|
||||||
node.hover(flag);
|
node.hover(flag);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onMouseOut = (node: Node) => (_: any, flag = false) => {
|
onMouseOut = (node: INode) => (_: any, flag = false) => {
|
||||||
if (node && typeof node.hover === 'function') {
|
if (node && typeof node.hover === 'function') {
|
||||||
node.hover(flag);
|
node.hover(flag);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
renderNodes = (/* node: Node */) => {
|
renderNodes = () => {
|
||||||
const nodes = this.state.parentNodes;
|
const nodes = this.state.parentNodes;
|
||||||
if (!nodes || nodes.length < 1) {
|
if (!nodes || nodes.length < 1) {
|
||||||
return null;
|
return null;
|
||||||
@ -136,7 +140,7 @@ export default class InstanceNodeSelector extends React.Component<IProps, IState
|
|||||||
triggerType="hover"
|
triggerType="hover"
|
||||||
offset={[0, 0]}
|
offset={[0, 0]}
|
||||||
>
|
>
|
||||||
<div className="instance-node-selector">{this.renderNodes(node)}</div>
|
<div className="instance-node-selector">{this.renderNodes()}</div>
|
||||||
</Popup>
|
</Popup>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -16,17 +16,15 @@ import {
|
|||||||
IPublicModelScroller,
|
IPublicModelScroller,
|
||||||
IPublicTypeLocationData,
|
IPublicTypeLocationData,
|
||||||
IPublicEnumTransformStage,
|
IPublicEnumTransformStage,
|
||||||
IPublicModelDragon,
|
|
||||||
IPublicModelDropLocation,
|
|
||||||
IPublicModelLocateEvent,
|
IPublicModelLocateEvent,
|
||||||
} from '@alilc/lowcode-types';
|
} from '@alilc/lowcode-types';
|
||||||
import { megreAssets, IPublicTypeAssetsJson, isNodeSchema, isDragNodeObject, isDragNodeDataObject, isLocationChildrenDetail, Logger } from '@alilc/lowcode-utils';
|
import { megreAssets, IPublicTypeAssetsJson, isNodeSchema, isDragNodeObject, isDragNodeDataObject, isLocationChildrenDetail, Logger } from '@alilc/lowcode-utils';
|
||||||
import { Project } from '../project';
|
import { IProject, Project } from '../project';
|
||||||
import { Node, DocumentModel, insertChildren, INode } from '../document';
|
import { Node, DocumentModel, insertChildren, INode } from '../document';
|
||||||
import { ComponentMeta, IComponentMeta } from '../component-meta';
|
import { ComponentMeta, IComponentMeta } from '../component-meta';
|
||||||
import { INodeSelector, Component } from '../simulator';
|
import { INodeSelector, Component } from '../simulator';
|
||||||
import { Scroller } from './scroller';
|
import { Scroller } from './scroller';
|
||||||
import { Dragon, IDragon, ILocateEvent } from './dragon';
|
import { Dragon, IDragon } from './dragon';
|
||||||
import { ActiveTracker, IActiveTracker } from './active-tracker';
|
import { ActiveTracker, IActiveTracker } from './active-tracker';
|
||||||
import { Detecting } from './detecting';
|
import { Detecting } from './detecting';
|
||||||
import { DropLocation } from './location';
|
import { DropLocation } from './location';
|
||||||
@ -64,7 +62,11 @@ export interface DesignerProps {
|
|||||||
export interface IDesigner {
|
export interface IDesigner {
|
||||||
readonly shellModelFactory: IShellModelFactory;
|
readonly shellModelFactory: IShellModelFactory;
|
||||||
|
|
||||||
get dragon(): IPublicModelDragon;
|
viewName: string | undefined;
|
||||||
|
|
||||||
|
readonly project: IProject;
|
||||||
|
|
||||||
|
get dragon(): IDragon;
|
||||||
|
|
||||||
get activeTracker(): IActiveTracker;
|
get activeTracker(): IActiveTracker;
|
||||||
|
|
||||||
@ -78,6 +80,10 @@ export interface IDesigner {
|
|||||||
|
|
||||||
createScroller(scrollable: IPublicTypeScrollable): IPublicModelScroller;
|
createScroller(scrollable: IPublicTypeScrollable): IPublicModelScroller;
|
||||||
|
|
||||||
|
refreshComponentMetasMap(): void;
|
||||||
|
|
||||||
|
createOffsetObserver(nodeInstance: INodeSelector): OffsetObserver | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建插入位置,考虑放到 dragon 中
|
* 创建插入位置,考虑放到 dragon 中
|
||||||
*/
|
*/
|
||||||
@ -92,6 +98,8 @@ export interface IDesigner {
|
|||||||
generateMetadata?: () => IPublicTypeComponentMetadata | null,
|
generateMetadata?: () => IPublicTypeComponentMetadata | null,
|
||||||
): IComponentMeta;
|
): IComponentMeta;
|
||||||
|
|
||||||
|
clearLocation(): void;
|
||||||
|
|
||||||
createComponentMeta(data: IPublicTypeComponentMetadata): IComponentMeta | null;
|
createComponentMeta(data: IPublicTypeComponentMetadata): IComponentMeta | null;
|
||||||
|
|
||||||
getComponentMetasMap(): Map<string, IComponentMeta>;
|
getComponentMetasMap(): Map<string, IComponentMeta>;
|
||||||
@ -118,7 +126,7 @@ export class Designer implements IDesigner {
|
|||||||
|
|
||||||
readonly detecting = new Detecting();
|
readonly detecting = new Detecting();
|
||||||
|
|
||||||
readonly project: Project;
|
readonly project: IProject;
|
||||||
|
|
||||||
readonly editor: IPublicModelEditor;
|
readonly editor: IPublicModelEditor;
|
||||||
|
|
||||||
@ -140,7 +148,7 @@ export class Designer implements IDesigner {
|
|||||||
|
|
||||||
@obx.ref private _simulatorComponent?: ComponentType<any>;
|
@obx.ref private _simulatorComponent?: ComponentType<any>;
|
||||||
|
|
||||||
@obx.ref private _simulatorProps?: Record<string, any> | ((project: Project) => object);
|
@obx.ref private _simulatorProps?: Record<string, any> | ((project: IProject) => object);
|
||||||
|
|
||||||
@obx.ref private _suspensed = false;
|
@obx.ref private _suspensed = false;
|
||||||
|
|
||||||
|
|||||||
@ -11,9 +11,9 @@ import {
|
|||||||
IPublicModelSensor,
|
IPublicModelSensor,
|
||||||
} from '@alilc/lowcode-types';
|
} from '@alilc/lowcode-types';
|
||||||
import { setNativeSelection, cursor } from '@alilc/lowcode-utils';
|
import { setNativeSelection, cursor } from '@alilc/lowcode-utils';
|
||||||
import { Node } from '../document';
|
import { INode, Node } from '../document';
|
||||||
import { ISimulatorHost, isSimulatorHost } from '../simulator';
|
import { ISimulatorHost, isSimulatorHost } from '../simulator';
|
||||||
import { Designer } from './designer';
|
import { IDesigner } from './designer';
|
||||||
import { makeEventsHandler } from '../utils/misc';
|
import { makeEventsHandler } from '../utils/misc';
|
||||||
|
|
||||||
export interface ILocateEvent extends IPublicModelLocateEvent {
|
export interface ILocateEvent extends IPublicModelLocateEvent {
|
||||||
@ -88,14 +88,14 @@ function getSourceSensor(dragObject: IPublicModelDragObject): ISimulatorHost | n
|
|||||||
if (!isDragNodeObject(dragObject)) {
|
if (!isDragNodeObject(dragObject)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return dragObject.nodes[0]?.document.simulator || null;
|
return dragObject.nodes[0]?.document?.simulator || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isDragEvent(e: any): e is DragEvent {
|
function isDragEvent(e: any): e is DragEvent {
|
||||||
return e?.type?.startsWith('drag');
|
return e?.type?.startsWith('drag');
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDragon extends IPublicModelDragon {
|
export interface IDragon extends IPublicModelDragon<INode> {
|
||||||
emitter: IEventBus;
|
emitter: IEventBus;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ export class Dragon implements IDragon {
|
|||||||
|
|
||||||
emitter: IEventBus = createModuleEventBus('Dragon');
|
emitter: IEventBus = createModuleEventBus('Dragon');
|
||||||
|
|
||||||
constructor(readonly designer: Designer) {
|
constructor(readonly designer: IDesigner) {
|
||||||
makeObservable(this);
|
makeObservable(this);
|
||||||
this.viewName = designer.viewName;
|
this.viewName = designer.viewName;
|
||||||
}
|
}
|
||||||
@ -167,7 +167,7 @@ export class Dragon implements IDragon {
|
|||||||
* @param dragObject 拖拽对象
|
* @param dragObject 拖拽对象
|
||||||
* @param boostEvent 拖拽初始时事件
|
* @param boostEvent 拖拽初始时事件
|
||||||
*/
|
*/
|
||||||
boost(dragObject: IPublicModelDragObject, boostEvent: MouseEvent | DragEvent, fromRglNode?: Node | IPublicModelNode) {
|
boost(dragObject: IPublicModelDragObject, boostEvent: MouseEvent | DragEvent, fromRglNode?: INode | IPublicModelNode) {
|
||||||
const { designer } = this;
|
const { designer } = this;
|
||||||
const masterSensors = this.getMasterSensors();
|
const masterSensors = this.getMasterSensors();
|
||||||
const handleEvents = makeEventsHandler(boostEvent, masterSensors);
|
const handleEvents = makeEventsHandler(boostEvent, masterSensors);
|
||||||
@ -264,7 +264,7 @@ export class Dragon implements IDragon {
|
|||||||
this.emitter.emit('rgl.add.placeholder', {
|
this.emitter.emit('rgl.add.placeholder', {
|
||||||
rglNode,
|
rglNode,
|
||||||
fromRglNode,
|
fromRglNode,
|
||||||
node: locateEvent.dragObject.nodes[0],
|
node: locateEvent.dragObject?.nodes[0],
|
||||||
event: e,
|
event: e,
|
||||||
});
|
});
|
||||||
designer.clearLocation();
|
designer.clearLocation();
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import requestIdleCallback, { cancelIdleCallback } from 'ric-shim';
|
|||||||
import { obx, computed, makeObservable } from '@alilc/lowcode-editor-core';
|
import { obx, computed, makeObservable } from '@alilc/lowcode-editor-core';
|
||||||
import { uniqueId } from '@alilc/lowcode-utils';
|
import { uniqueId } from '@alilc/lowcode-utils';
|
||||||
import { INodeSelector, IViewport } from '../simulator';
|
import { INodeSelector, IViewport } from '../simulator';
|
||||||
import { Node } from '../document';
|
import { INode } from '../document';
|
||||||
|
|
||||||
export class OffsetObserver {
|
export class OffsetObserver {
|
||||||
readonly id = uniqueId('oobx');
|
readonly id = uniqueId('oobx');
|
||||||
@ -93,11 +93,11 @@ export class OffsetObserver {
|
|||||||
|
|
||||||
private pid: number | undefined;
|
private pid: number | undefined;
|
||||||
|
|
||||||
readonly viewport: IViewport;
|
readonly viewport: IViewport | undefined;
|
||||||
|
|
||||||
private isRoot: boolean;
|
private isRoot: boolean;
|
||||||
|
|
||||||
readonly node: Node;
|
readonly node: INode;
|
||||||
|
|
||||||
readonly compute: () => void;
|
readonly compute: () => void;
|
||||||
|
|
||||||
@ -105,10 +105,10 @@ export class OffsetObserver {
|
|||||||
const { node, instance } = nodeInstance;
|
const { node, instance } = nodeInstance;
|
||||||
this.node = node;
|
this.node = node;
|
||||||
const doc = node.document;
|
const doc = node.document;
|
||||||
const host = doc.simulator!;
|
const host = doc?.simulator;
|
||||||
const focusNode = doc.focusNode;
|
const focusNode = doc?.focusNode;
|
||||||
this.isRoot = node.contains(focusNode!);
|
this.isRoot = node.contains(focusNode!);
|
||||||
this.viewport = host.viewport;
|
this.viewport = host?.viewport;
|
||||||
makeObservable(this);
|
makeObservable(this);
|
||||||
if (this.isRoot) {
|
if (this.isRoot) {
|
||||||
this.hasOffset = true;
|
this.hasOffset = true;
|
||||||
@ -118,7 +118,7 @@ export class OffsetObserver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let pid: number;
|
let pid: number | undefined;
|
||||||
const compute = () => {
|
const compute = () => {
|
||||||
if (pid !== this.pid) {
|
if (pid !== this.pid) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -35,7 +35,7 @@ import {
|
|||||||
isDragNodeDataObject,
|
isDragNodeDataObject,
|
||||||
isNode,
|
isNode,
|
||||||
} from '@alilc/lowcode-utils';
|
} from '@alilc/lowcode-utils';
|
||||||
import { IProject, Project } from '../project';
|
import { IProject } from '../project';
|
||||||
import { ISimulatorHost } from '../simulator';
|
import { ISimulatorHost } from '../simulator';
|
||||||
import { IComponentMeta } from '../component-meta';
|
import { IComponentMeta } from '../component-meta';
|
||||||
import { IDesigner, IHistory } from '../designer';
|
import { IDesigner, IHistory } from '../designer';
|
||||||
@ -56,7 +56,7 @@ export type GetDataType<T, NodeType> = T extends undefined
|
|||||||
export interface IDocumentModel extends Omit< IPublicModelDocumentModel<
|
export interface IDocumentModel extends Omit< IPublicModelDocumentModel<
|
||||||
ISelection,
|
ISelection,
|
||||||
IHistory,
|
IHistory,
|
||||||
INode | IRootNode,
|
INode,
|
||||||
IDropLocation,
|
IDropLocation,
|
||||||
IModalNodesManager,
|
IModalNodesManager,
|
||||||
IProject
|
IProject
|
||||||
@ -81,6 +81,8 @@ export interface IDocumentModel extends Omit< IPublicModelDocumentModel<
|
|||||||
|
|
||||||
readonly designer: IDesigner;
|
readonly designer: IDesigner;
|
||||||
|
|
||||||
|
selection: ISelection;
|
||||||
|
|
||||||
get rootNode(): INode | null;
|
get rootNode(): INode | null;
|
||||||
|
|
||||||
get simulator(): ISimulatorHost | null;
|
get simulator(): ISimulatorHost | null;
|
||||||
@ -98,8 +100,6 @@ export interface IDocumentModel extends Omit< IPublicModelDocumentModel<
|
|||||||
|
|
||||||
get currentRoot(): INode | null;
|
get currentRoot(): INode | null;
|
||||||
|
|
||||||
selection: ISelection;
|
|
||||||
|
|
||||||
isBlank(): boolean;
|
isBlank(): boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import {
|
|||||||
IPublicApiMaterial,
|
IPublicApiMaterial,
|
||||||
IPublicApiEvent,
|
IPublicApiEvent,
|
||||||
IPublicApiCommon,
|
IPublicApiCommon,
|
||||||
IPublicTypeCompositeObject,
|
|
||||||
IPublicApiPlugins,
|
IPublicApiPlugins,
|
||||||
IPublicTypePluginConfig,
|
IPublicTypePluginConfig,
|
||||||
IPublicApiLogger,
|
IPublicApiLogger,
|
||||||
@ -16,6 +15,7 @@ import {
|
|||||||
IPublicApiCanvas,
|
IPublicApiCanvas,
|
||||||
IPublicApiWorkspace,
|
IPublicApiWorkspace,
|
||||||
IPublicTypePluginMeta,
|
IPublicTypePluginMeta,
|
||||||
|
IPublicTypePluginRegisterOptions,
|
||||||
} from '@alilc/lowcode-types';
|
} from '@alilc/lowcode-types';
|
||||||
|
|
||||||
export type PluginPreference = Map<string, Record<string, IPublicTypePreferenceValueType>>;
|
export type PluginPreference = Map<string, Record<string, IPublicTypePreferenceValueType>>;
|
||||||
@ -72,7 +72,7 @@ export interface ILowCodePluginManagerCore {
|
|||||||
register(
|
register(
|
||||||
pluginModel: IPublicTypePlugin,
|
pluginModel: IPublicTypePlugin,
|
||||||
pluginOptions?: any,
|
pluginOptions?: any,
|
||||||
options?: IPublicTypeCompositeObject,
|
options?: IPublicTypePluginRegisterOptions,
|
||||||
): Promise<void>;
|
): Promise<void>;
|
||||||
init(pluginPreference?: Map<string, Record<string, IPublicTypePreferenceValueType>>): Promise<void>;
|
init(pluginPreference?: Map<string, Record<string, IPublicTypePreferenceValueType>>): Promise<void>;
|
||||||
get(pluginName: string): ILowCodePluginRuntime | undefined;
|
get(pluginName: string): ILowCodePluginRuntime | undefined;
|
||||||
|
|||||||
@ -41,6 +41,14 @@ export interface IProject extends Omit< IBaseApiProject<
|
|||||||
|
|
||||||
get documents(): IDocumentModel[];
|
get documents(): IDocumentModel[];
|
||||||
|
|
||||||
|
get i18n(): {
|
||||||
|
[local: string]: {
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
mountSimulator(simulator: ISimulatorHost): void;
|
||||||
|
|
||||||
open(doc?: string | IDocumentModel | IPublicTypeRootSchema): IDocumentModel | null;
|
open(doc?: string | IDocumentModel | IPublicTypeRootSchema): IDocumentModel | null;
|
||||||
|
|
||||||
getDocumentByFileName(fileName: string): IDocumentModel | null;
|
getDocumentByFileName(fileName: string): IDocumentModel | null;
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import { ComponentType } from 'react';
|
import { ComponentType } from 'react';
|
||||||
import { IPublicTypeComponentMetadata, IPublicTypeNodeSchema, IPublicTypeScrollable, IPublicTypeComponentInstance, IPublicModelSensor, IPublicTypeNodeInstance, IPublicTypePackage } from '@alilc/lowcode-types';
|
import { IPublicTypeComponentMetadata, IPublicTypeNodeSchema, IPublicTypeScrollable, IPublicTypeComponentInstance, IPublicModelSensor, IPublicTypeNodeInstance, IPublicTypePackage } from '@alilc/lowcode-types';
|
||||||
import { Point, ScrollTarget, ILocateEvent } from './designer';
|
import { Point, ScrollTarget, ILocateEvent, IDesigner } from './designer';
|
||||||
import { BuiltinSimulatorRenderer } from './builtin-simulator/renderer';
|
import { BuiltinSimulatorRenderer } from './builtin-simulator/renderer';
|
||||||
import { INode } from './document';
|
import { INode } from './document';
|
||||||
|
import { IProject } from './project';
|
||||||
|
|
||||||
export type AutoFit = '100%';
|
export type AutoFit = '100%';
|
||||||
// eslint-disable-next-line no-redeclare
|
// eslint-disable-next-line no-redeclare
|
||||||
@ -89,6 +90,10 @@ export interface ISimulatorHost<P = object> extends IPublicModelSensor<INode> {
|
|||||||
readonly contentDocument?: Document;
|
readonly contentDocument?: Document;
|
||||||
readonly renderer?: BuiltinSimulatorRenderer;
|
readonly renderer?: BuiltinSimulatorRenderer;
|
||||||
|
|
||||||
|
readonly project: IProject;
|
||||||
|
|
||||||
|
readonly designer: IDesigner;
|
||||||
|
|
||||||
// dependsAsset // like react jQuery lodash
|
// dependsAsset // like react jQuery lodash
|
||||||
// themesAsset
|
// themesAsset
|
||||||
// componentsAsset
|
// componentsAsset
|
||||||
|
|||||||
@ -339,8 +339,8 @@ function fireCallback(callback: IPublicTypeHotkeyCallback, e: KeyboardEvent, com
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IHotKey extends IPublicApiHotkey {
|
export interface IHotKey extends Omit<IPublicApiHotkey, 'bind' | 'callbacks'> {
|
||||||
|
activate(activate: boolean): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Hotkey implements IHotKey {
|
export class Hotkey implements IHotKey {
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { Component } from 'react';
|
import { Component } from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
import { TipItem } from './tip-item';
|
import { TipItem } from './tip-item';
|
||||||
import { tipHandler } from './tip-handler';
|
import { tipHandler } from './tip-handler';
|
||||||
|
|
||||||
@ -25,11 +26,13 @@ export class TipContainer extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return window.ReactDOM.createPortal(
|
ReactDOM.createPortal(
|
||||||
<div className="lc-tips-container">
|
<div className="lc-tips-container">
|
||||||
<TipItem />
|
<TipItem />
|
||||||
</div>,
|
</div>,
|
||||||
document.querySelector('body')!,
|
document.querySelector('body')!,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
LowCodePluginManager,
|
ILowCodePluginManager,
|
||||||
} from '@alilc/lowcode-designer';
|
} from '@alilc/lowcode-designer';
|
||||||
import { globalContext } from '@alilc/lowcode-editor-core';
|
import { globalContext } from '@alilc/lowcode-editor-core';
|
||||||
import {
|
import {
|
||||||
@ -14,8 +14,8 @@ import { pluginsSymbol } from '../symbols';
|
|||||||
|
|
||||||
const innerPluginsSymbol = Symbol('plugin');
|
const innerPluginsSymbol = Symbol('plugin');
|
||||||
export class Plugins implements IPublicApiPlugins {
|
export class Plugins implements IPublicApiPlugins {
|
||||||
private readonly [innerPluginsSymbol]: LowCodePluginManager;
|
private readonly [innerPluginsSymbol]: ILowCodePluginManager;
|
||||||
get [pluginsSymbol](): LowCodePluginManager {
|
get [pluginsSymbol](): ILowCodePluginManager {
|
||||||
if (this.workspaceMode) {
|
if (this.workspaceMode) {
|
||||||
return this[innerPluginsSymbol];
|
return this[innerPluginsSymbol];
|
||||||
}
|
}
|
||||||
@ -27,7 +27,7 @@ export class Plugins implements IPublicApiPlugins {
|
|||||||
return this[innerPluginsSymbol];
|
return this[innerPluginsSymbol];
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(plugins: LowCodePluginManager, public workspaceMode: boolean = false) {
|
constructor(plugins: ILowCodePluginManager, public workspaceMode: boolean = false) {
|
||||||
this[innerPluginsSymbol] = plugins;
|
this[innerPluginsSymbol] = plugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
import { IPublicApiWorkspace, IPublicResourceList, IPublicTypeDisposable, IPublicTypeResourceType } from '@alilc/lowcode-types';
|
import { IPublicApiWorkspace, IPublicResourceList, IPublicTypeDisposable, IPublicTypeResourceType } from '@alilc/lowcode-types';
|
||||||
import { Workspace as InnerWorkSpace } from '@alilc/lowcode-workspace';
|
import { IWorkspace } from '@alilc/lowcode-workspace';
|
||||||
import { Plugins } from '@alilc/lowcode-shell';
|
import { Plugins } from '@alilc/lowcode-shell';
|
||||||
import { workspaceSymbol } from '../symbols';
|
import { workspaceSymbol } from '../symbols';
|
||||||
import { Resource as ShellResource, Window as ShellWindow } from '../model';
|
import { Resource as ShellResource, Window as ShellWindow } from '../model';
|
||||||
|
|
||||||
export class Workspace implements IPublicApiWorkspace {
|
export class Workspace implements IPublicApiWorkspace {
|
||||||
readonly [workspaceSymbol]: InnerWorkSpace;
|
readonly [workspaceSymbol]: IWorkspace;
|
||||||
|
|
||||||
constructor(innerWorkspace: InnerWorkSpace) {
|
constructor(innerWorkspace: IWorkspace) {
|
||||||
this[workspaceSymbol] = innerWorkspace;
|
this[workspaceSymbol] = innerWorkspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import { IPublicModelResource } from '@alilc/lowcode-types';
|
import { IPublicModelResource } from '@alilc/lowcode-types';
|
||||||
import { Resource as InnerResource } from '@alilc/lowcode-workspace';
|
import { IResource } from '@alilc/lowcode-workspace';
|
||||||
import { resourceSymbol } from '../symbols';
|
import { resourceSymbol } from '../symbols';
|
||||||
|
|
||||||
export class Resource implements IPublicModelResource {
|
export class Resource implements IPublicModelResource {
|
||||||
readonly [resourceSymbol]: InnerResource;
|
readonly [resourceSymbol]: IResource;
|
||||||
|
|
||||||
constructor(resource: InnerResource) {
|
constructor(resource: IResource) {
|
||||||
this[resourceSymbol] = resource;
|
this[resourceSymbol] = resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import { windowSymbol } from '../symbols';
|
import { windowSymbol } from '../symbols';
|
||||||
import { IPublicModelResource, IPublicModelWindow, IPublicTypeDisposable } from '@alilc/lowcode-types';
|
import { IPublicModelResource, IPublicModelWindow, IPublicTypeDisposable } from '@alilc/lowcode-types';
|
||||||
import { EditorWindow } from '@alilc/lowcode-workspace';
|
import { IEditorWindow } from '@alilc/lowcode-workspace';
|
||||||
import { Resource as ShellResource } from './resource';
|
import { Resource as ShellResource } from './resource';
|
||||||
|
|
||||||
export class Window implements IPublicModelWindow {
|
export class Window implements IPublicModelWindow {
|
||||||
private readonly [windowSymbol]: EditorWindow;
|
private readonly [windowSymbol]: IEditorWindow;
|
||||||
|
|
||||||
get id() {
|
get id() {
|
||||||
return this[windowSymbol]?.id;
|
return this[windowSymbol]?.id;
|
||||||
@ -22,7 +22,7 @@ export class Window implements IPublicModelWindow {
|
|||||||
return new ShellResource(this[windowSymbol].resource);
|
return new ShellResource(this[windowSymbol].resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(editorWindow: EditorWindow) {
|
constructor(editorWindow: IEditorWindow) {
|
||||||
this[windowSymbol] = editorWindow;
|
this[windowSymbol] = editorWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,19 +2,20 @@ import { IPublicModelWindow } from '../model';
|
|||||||
import { IPublicApiPlugins, IPublicModelResource, IPublicResourceList, IPublicTypeDisposable, IPublicTypeResourceType } from '@alilc/lowcode-types';
|
import { IPublicApiPlugins, IPublicModelResource, IPublicResourceList, IPublicTypeDisposable, IPublicTypeResourceType } from '@alilc/lowcode-types';
|
||||||
|
|
||||||
export interface IPublicApiWorkspace<
|
export interface IPublicApiWorkspace<
|
||||||
Plugins = IPublicApiPlugins
|
Plugins = IPublicApiPlugins,
|
||||||
|
ModelWindow = IPublicModelWindow
|
||||||
> {
|
> {
|
||||||
|
|
||||||
/** 是否启用 workspace 模式 */
|
/** 是否启用 workspace 模式 */
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
|
|
||||||
/** 当前设计器窗口 */
|
/** 当前设计器窗口 */
|
||||||
window: IPublicModelWindow;
|
window: ModelWindow;
|
||||||
|
|
||||||
plugins: Plugins;
|
plugins: Plugins;
|
||||||
|
|
||||||
/** 当前设计器的编辑窗口 */
|
/** 当前设计器的编辑窗口 */
|
||||||
windows: IPublicModelWindow[];
|
windows: ModelWindow[];
|
||||||
|
|
||||||
/** 获取资源树列表 */
|
/** 获取资源树列表 */
|
||||||
get resourceList(): IPublicModelResource[];
|
get resourceList(): IPublicModelResource[];
|
||||||
|
|||||||
@ -1,8 +1,3 @@
|
|||||||
export interface IPublicModelDragObject {
|
import { IPublicTypeDragNodeDataObject, IPublicTypeDragNodeObject } from '../type';
|
||||||
|
|
||||||
get type(): any;
|
export type IPublicModelDragObject = Readonly<IPublicTypeDragNodeObject> | Readonly<IPublicTypeDragNodeDataObject>;
|
||||||
|
|
||||||
get nodes(): any;
|
|
||||||
|
|
||||||
get data(): any;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import { ReactElement } from 'react';
|
import { ReactElement } from 'react';
|
||||||
|
|
||||||
export interface IPublicModelResource {
|
export interface IBaseModelResource<
|
||||||
|
Resource
|
||||||
|
> {
|
||||||
get title(): string | undefined;
|
get title(): string | undefined;
|
||||||
|
|
||||||
get icon(): ReactElement | undefined;
|
get icon(): ReactElement | undefined;
|
||||||
@ -13,7 +15,9 @@ export interface IPublicModelResource {
|
|||||||
|
|
||||||
get category(): string | undefined;
|
get category(): string | undefined;
|
||||||
|
|
||||||
get children(): IPublicModelResource[];
|
get children(): Resource[];
|
||||||
|
|
||||||
get viewName(): string | undefined;
|
get viewName(): string | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type IPublicModelResource = IBaseModelResource<IPublicModelResource>;
|
||||||
|
|||||||
@ -2,7 +2,9 @@ import { ReactElement } from 'react';
|
|||||||
import { IPublicTypeDisposable, IPublicTypeNodeSchema } from '../type';
|
import { IPublicTypeDisposable, IPublicTypeNodeSchema } from '../type';
|
||||||
import { IPublicModelResource } from './resource';
|
import { IPublicModelResource } from './resource';
|
||||||
|
|
||||||
export interface IPublicModelWindow {
|
export interface IPublicModelWindow<
|
||||||
|
Resource = IPublicModelResource
|
||||||
|
> {
|
||||||
|
|
||||||
/** 窗口 id */
|
/** 窗口 id */
|
||||||
id: string;
|
id: string;
|
||||||
@ -14,7 +16,7 @@ export interface IPublicModelWindow {
|
|||||||
icon?: ReactElement;
|
icon?: ReactElement;
|
||||||
|
|
||||||
/** 窗口资源类型 */
|
/** 窗口资源类型 */
|
||||||
resource?: IPublicModelResource;
|
resource?: Resource;
|
||||||
|
|
||||||
/** 当前窗口导入 schema */
|
/** 当前窗口导入 schema */
|
||||||
importSchema(schema: IPublicTypeNodeSchema): void;
|
importSchema(schema: IPublicTypeNodeSchema): void;
|
||||||
|
|||||||
@ -1,19 +1,23 @@
|
|||||||
|
import { IPublicModelNode } from '../model';
|
||||||
import { IPublicTypeIconType, TipContent } from './';
|
import { IPublicTypeIconType, TipContent } from './';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 动作描述
|
* 动作描述
|
||||||
*/
|
*/
|
||||||
export interface IPublicTypeActionContentObject {
|
export interface IPublicTypeActionContentObject {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 图标
|
* 图标
|
||||||
*/
|
*/
|
||||||
icon?: IPublicTypeIconType;
|
icon?: IPublicTypeIconType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 描述
|
* 描述
|
||||||
*/
|
*/
|
||||||
title?: TipContent;
|
title?: TipContent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行动作
|
* 执行动作
|
||||||
*/
|
*/
|
||||||
action?: (currentNode: any) => void;
|
action?: (currentNode: IPublicModelNode) => void;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,13 +15,14 @@ export enum LocationDetailType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type IPublicTypeRect = DOMRect & {
|
export type IPublicTypeRect = DOMRect & {
|
||||||
elements: Array<Element | Text>;
|
elements?: Array<Element | Text>;
|
||||||
computed?: boolean;
|
computed?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface IPublicTypeLocationChildrenDetail {
|
export interface IPublicTypeLocationChildrenDetail {
|
||||||
type: IPublicTypeLocationDetailType.Children;
|
type: IPublicTypeLocationDetailType.Children;
|
||||||
index?: number | null;
|
index?: number | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否有效位置
|
* 是否有效位置
|
||||||
*/
|
*/
|
||||||
@ -43,8 +44,7 @@ export interface IPublicTypeLocationPropDetail {
|
|||||||
domNode?: HTMLElement;
|
domNode?: HTMLElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line max-len
|
export type IPublicTypeLocationDetail = IPublicTypeLocationChildrenDetail | IPublicTypeLocationPropDetail | { [key: string]: any; type: string };
|
||||||
export type IPublicTypeLocationDetail = IPublicTypeLocationChildrenDetail | IPublicTypeLocationPropDetail | { type: string; [key: string]: any };
|
|
||||||
|
|
||||||
export interface IPublicTypeLocationData<
|
export interface IPublicTypeLocationData<
|
||||||
Node = IPublicModelNode
|
Node = IPublicModelNode
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { MouseEvent } from 'react';
|
||||||
import { IPublicTypePropType, IPublicTypeComponentAction } from './';
|
import { IPublicTypePropType, IPublicTypeComponentAction } from './';
|
||||||
import { IPublicModelNode, IPublicModelProp, IPublicModelSettingField } from '../model';
|
import { IPublicModelNode, IPublicModelProp, IPublicModelSettingField } from '../model';
|
||||||
|
|
||||||
|
|||||||
@ -1,20 +1,27 @@
|
|||||||
import { ReactElement } from 'react';
|
import { ReactElement } from 'react';
|
||||||
|
|
||||||
export interface IPublicResourceData {
|
export interface IPublicResourceData {
|
||||||
|
|
||||||
/** 资源名字 */
|
/** 资源名字 */
|
||||||
resourceName: string;
|
resourceName: string;
|
||||||
|
|
||||||
/** 资源标题 */
|
/** 资源标题 */
|
||||||
title: string;
|
title?: string;
|
||||||
|
|
||||||
/** 分类 */
|
/** 分类 */
|
||||||
category?: string;
|
category?: string;
|
||||||
|
|
||||||
/** 资源视图 */
|
/** 资源视图 */
|
||||||
viewName?: string;
|
viewName?: string;
|
||||||
|
|
||||||
/** 资源 icon */
|
/** 资源 icon */
|
||||||
icon?: ReactElement;
|
icon?: ReactElement;
|
||||||
|
|
||||||
/** 资源其他配置 */
|
/** 资源其他配置 */
|
||||||
options: {
|
options: {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 资源子元素 */
|
/** 资源子元素 */
|
||||||
children?: IPublicResourceData[];
|
children?: IPublicResourceData[];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
|
import { IPublicTypeActionContentObject } from '@alilc/lowcode-types';
|
||||||
|
|
||||||
export function isActionContentObject(obj: any): boolean {
|
export function isActionContentObject(obj: any): obj is IPublicTypeActionContentObject {
|
||||||
return obj && typeof obj === 'object';
|
return obj && typeof obj === 'object';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
|
import { IPublicTypeLocationData } from '@alilc/lowcode-types';
|
||||||
|
|
||||||
export function isLocationData(obj: any): boolean {
|
export function isLocationData(obj: any): obj is IPublicTypeLocationData {
|
||||||
return obj && obj.target && obj.detail;
|
return obj && obj.target && obj.detail;
|
||||||
}
|
}
|
||||||
@ -10,14 +10,13 @@ const pseudoMap = ['hover', 'focus', 'active', 'visited'];
|
|||||||
|
|
||||||
const RE_CAMEL = /[A-Z]/g;
|
const RE_CAMEL = /[A-Z]/g;
|
||||||
const RE_HYPHEN = /[-\s]+(.)?/g;
|
const RE_HYPHEN = /[-\s]+(.)?/g;
|
||||||
const CSS_REG = /:root(.*)\{.*/i;
|
|
||||||
const PROPS_REG = /([^:]*):\s?(.*)/i;
|
const PROPS_REG = /([^:]*):\s?(.*)/i;
|
||||||
|
|
||||||
// 给 css 分组
|
// 给 css 分组
|
||||||
function groupingCss(css) {
|
function groupingCss(css: string) {
|
||||||
let stackLength = 0;
|
let stackLength = 0;
|
||||||
let startIndex = 0;
|
let startIndex = 0;
|
||||||
const group = [];
|
const group: string[] = [];
|
||||||
css.split('').forEach((char, index) => {
|
css.split('').forEach((char, index) => {
|
||||||
if (char === '{') {
|
if (char === '{') {
|
||||||
stackLength++;
|
stackLength++;
|
||||||
@ -33,38 +32,38 @@ function groupingCss(css) {
|
|||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isString(str: any): str is string {
|
||||||
function isString(str) {
|
|
||||||
return {}.toString.call(str) === '[object String]';
|
return {}.toString.call(str) === '[object String]';
|
||||||
}
|
}
|
||||||
|
|
||||||
function hyphenate(str) {
|
function hyphenate(str: string): string {
|
||||||
return str.replace(RE_CAMEL, w => `-${w}`).toLowerCase();
|
return str.replace(RE_CAMEL, w => `-${w}`).toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
function camelize(str) {
|
function camelize(str: string): string {
|
||||||
return str.replace(RE_HYPHEN, (m, w) => (w ? w.toUpperCase() : ''));
|
return str.replace(RE_HYPHEN, (m, w) => (w ? w.toUpperCase() : ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convert
|
* convert
|
||||||
* {background-color: "red"}
|
* {background-color: "red"}
|
||||||
* to
|
* to
|
||||||
* background-color: red;
|
* background-color: red;
|
||||||
*/
|
*/
|
||||||
function runtimeToCss(runtime) {
|
function runtimeToCss(runtime: Record<string, string>) {
|
||||||
const css = [];
|
const css: string[] = [];
|
||||||
Object.keys(runtime).forEach((key) => {
|
Object.keys(runtime).forEach((key) => {
|
||||||
css.push(` ${key}: ${runtime[key]};`);
|
css.push(` ${key}: ${runtime[key]};`);
|
||||||
});
|
});
|
||||||
return css.join('\n');
|
return css.join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
function toNativeStyle(runtime) {
|
function toNativeStyle(runtime: Record<string, string> | undefined) {
|
||||||
if (!runtime) {
|
if (!runtime) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (runtime.default) {
|
if (runtime.default) {
|
||||||
const normalized = {};
|
const normalized: Record<string, string> = {};
|
||||||
Object.keys(runtime).forEach((pseudo) => {
|
Object.keys(runtime).forEach((pseudo) => {
|
||||||
if (pseudo === 'extra') {
|
if (pseudo === 'extra') {
|
||||||
normalized[pseudo] = runtime[pseudo];
|
normalized[pseudo] = runtime[pseudo];
|
||||||
@ -98,14 +97,13 @@ function normalizeStyle(style) {
|
|||||||
return normalized;
|
return normalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
const normalized = {};
|
const normalized: Record<string, string | Record<string, string>> = {};
|
||||||
Object.keys(style).forEach((key) => {
|
Object.keys(style).forEach((key) => {
|
||||||
normalized[hyphenate(key)] = style[key];
|
normalized[hyphenate(key)] = style[key];
|
||||||
});
|
});
|
||||||
return normalized;
|
return normalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function toCss(runtime) {
|
function toCss(runtime) {
|
||||||
if (!runtime) {
|
if (!runtime) {
|
||||||
return (
|
return (
|
||||||
@ -115,7 +113,7 @@ function toCss(runtime) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (runtime.default) {
|
if (runtime.default) {
|
||||||
const css = [];
|
const css: string[] = [];
|
||||||
Object.keys(runtime).forEach((pseudo) => {
|
Object.keys(runtime).forEach((pseudo) => {
|
||||||
if (pseudo === 'extra') {
|
if (pseudo === 'extra') {
|
||||||
Array.isArray(runtime.extra) && css.push(runtime.extra.join('\n'));
|
Array.isArray(runtime.extra) && css.push(runtime.extra.join('\n'));
|
||||||
@ -140,11 +138,14 @@ ${runtimeToCss(normalizeStyle(runtime))}
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function cssToRuntime(css) {
|
function cssToRuntime(css: string) {
|
||||||
if (!css) {
|
if (!css) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
const runtime = {};
|
const runtime: {
|
||||||
|
extra?: string[];
|
||||||
|
default?: Record<string, string>;
|
||||||
|
} = {};
|
||||||
const groups = groupingCss(css);
|
const groups = groupingCss(css);
|
||||||
groups.forEach((cssItem) => {
|
groups.forEach((cssItem) => {
|
||||||
if (!cssItem.startsWith(':root')) {
|
if (!cssItem.startsWith(':root')) {
|
||||||
@ -153,7 +154,7 @@ function cssToRuntime(css) {
|
|||||||
} else {
|
} else {
|
||||||
const res = /:root:?(.*)?{(.*)/ig.exec(cssItem.replace(/[\r\n]+/ig, '').trim());
|
const res = /:root:?(.*)?{(.*)/ig.exec(cssItem.replace(/[\r\n]+/ig, '').trim());
|
||||||
if (res) {
|
if (res) {
|
||||||
let pseudo;
|
let pseudo: string | undefined;
|
||||||
|
|
||||||
if (res[1] && res[1].trim() && some(pseudoMap, pse => res[1].indexOf(pse) === 0)) {
|
if (res[1] && res[1].trim() && some(pseudoMap, pse => res[1].indexOf(pse) === 0)) {
|
||||||
pseudo = res[1].trim();
|
pseudo = res[1].trim();
|
||||||
@ -161,8 +162,8 @@ function cssToRuntime(css) {
|
|||||||
pseudo = res[1];
|
pseudo = res[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
const s = {};
|
const s: Record<string, string> = {};
|
||||||
res[2].split(';').reduce((prev, next) => {
|
res[2].split(';').reduce<string[]>((prev, next) => {
|
||||||
if (next.indexOf('base64') > -1) {
|
if (next.indexOf('base64') > -1) {
|
||||||
prev[prev.length - 1] += `;${next}`;
|
prev[prev.length - 1] += `;${next}`;
|
||||||
} else {
|
} else {
|
||||||
@ -173,8 +174,8 @@ function cssToRuntime(css) {
|
|||||||
if (item) {
|
if (item) {
|
||||||
if (PROPS_REG.test(item)) {
|
if (PROPS_REG.test(item)) {
|
||||||
const props = item.match(PROPS_REG);
|
const props = item.match(PROPS_REG);
|
||||||
const key = props[1];
|
const key = props?.[1];
|
||||||
const value = props[2];
|
const value = props?.[2];
|
||||||
if (key && value) {
|
if (key && value) {
|
||||||
s[key.trim()] = value.trim();
|
s[key.trim()] = value.trim();
|
||||||
}
|
}
|
||||||
@ -182,10 +183,7 @@ function cssToRuntime(css) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!pseudo) {
|
runtime[pseudo || 'default'] = s;
|
||||||
pseudo = 'default';
|
|
||||||
}
|
|
||||||
runtime[pseudo] = s;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -23,7 +23,8 @@ export function isReactComponent(obj: any): obj is ComponentType<any> {
|
|||||||
export function wrapReactClass(view: FunctionComponent) {
|
export function wrapReactClass(view: FunctionComponent) {
|
||||||
let ViewComponentClass = class extends Component {
|
let ViewComponentClass = class extends Component {
|
||||||
render() {
|
render() {
|
||||||
return createElement(view, this.props);
|
const { children, ...other } = this.props;
|
||||||
|
return createElement(view, other, children);
|
||||||
}
|
}
|
||||||
} as any;
|
} as any;
|
||||||
ViewComponentClass = cloneEnumerableProperty(ViewComponentClass, view);
|
ViewComponentClass = cloneEnumerableProperty(ViewComponentClass, view);
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
// 仅使用类型
|
// 仅使用类型
|
||||||
import { IPublicModelNode } from '@alilc/lowcode-types';
|
import { IPublicModelNode } from '@alilc/lowcode-types';
|
||||||
|
import { MouseEvent } from 'react';
|
||||||
|
|
||||||
export const getClosestNode = <Node extends IPublicModelNode = IPublicModelNode>(
|
export const getClosestNode = <Node extends IPublicModelNode = IPublicModelNode>(
|
||||||
node: Node,
|
node: Node,
|
||||||
@ -12,7 +13,7 @@ export const getClosestNode = <Node extends IPublicModelNode = IPublicModelNode>
|
|||||||
return node;
|
return node;
|
||||||
} else {
|
} else {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return getClosestNode(node.getParent(), until);
|
return getClosestNode(node.parent, until);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -22,8 +23,8 @@ export const getClosestNode = <Node extends IPublicModelNode = IPublicModelNode>
|
|||||||
* @param {unknown} e 点击事件
|
* @param {unknown} e 点击事件
|
||||||
* @returns {boolean} 是否可点击,true表示可点击
|
* @returns {boolean} 是否可点击,true表示可点击
|
||||||
*/
|
*/
|
||||||
export function canClickNode<Node extends IPublicModelNode = IPublicModelNode>(node: Node, e: unknown): boolean {
|
export function canClickNode<Node extends IPublicModelNode = IPublicModelNode>(node: Node, e: MouseEvent): boolean {
|
||||||
const onClickHook = node.componentMeta?.advanced?.callbacks?.onClickHook;
|
const onClickHook = node.componentMeta?.advanced?.callbacks?.onClickHook;
|
||||||
const canClick = typeof onClickHook === 'function' ? onClickHook(e as MouseEvent, node) : true;
|
const canClick = typeof onClickHook === 'function' ? onClickHook(e, node) : true;
|
||||||
return canClick;
|
return canClick;
|
||||||
};
|
}
|
||||||
|
|||||||
@ -3,13 +3,17 @@ import {
|
|||||||
engineConfig, Setters as InnerSetters,
|
engineConfig, Setters as InnerSetters,
|
||||||
Hotkey as InnerHotkey,
|
Hotkey as InnerHotkey,
|
||||||
commonEvent,
|
commonEvent,
|
||||||
|
IEngineConfig,
|
||||||
|
IHotKey,
|
||||||
} from '@alilc/lowcode-editor-core';
|
} from '@alilc/lowcode-editor-core';
|
||||||
import {
|
import {
|
||||||
Designer,
|
Designer,
|
||||||
ILowCodePluginContextApiAssembler,
|
ILowCodePluginContextApiAssembler,
|
||||||
LowCodePluginManager,
|
LowCodePluginManager,
|
||||||
ILowCodePluginContextPrivate,
|
ILowCodePluginContextPrivate,
|
||||||
Project as InnerProject,
|
IProject,
|
||||||
|
IDesigner,
|
||||||
|
ILowCodePluginManager,
|
||||||
} from '@alilc/lowcode-designer';
|
} from '@alilc/lowcode-designer';
|
||||||
import {
|
import {
|
||||||
Skeleton as InnerSkeleton,
|
Skeleton as InnerSkeleton,
|
||||||
@ -29,40 +33,72 @@ import {
|
|||||||
} from '@alilc/lowcode-shell';
|
} from '@alilc/lowcode-shell';
|
||||||
import {
|
import {
|
||||||
IPluginPreferenceMananger,
|
IPluginPreferenceMananger,
|
||||||
|
IPublicApiCanvas,
|
||||||
|
IPublicApiCommon,
|
||||||
IPublicApiEvent,
|
IPublicApiEvent,
|
||||||
IPublicApiWorkspace,
|
IPublicApiHotkey,
|
||||||
|
IPublicApiMaterial,
|
||||||
|
IPublicApiPlugins,
|
||||||
|
IPublicApiProject,
|
||||||
|
IPublicApiSetters,
|
||||||
|
IPublicApiSkeleton,
|
||||||
IPublicModelPluginContext,
|
IPublicModelPluginContext,
|
||||||
IPublicTypePluginMeta,
|
IPublicTypePluginMeta,
|
||||||
} from '@alilc/lowcode-types';
|
} from '@alilc/lowcode-types';
|
||||||
import { getLogger } from '@alilc/lowcode-utils';
|
import { getLogger, Logger as InnerLogger } from '@alilc/lowcode-utils';
|
||||||
import { Workspace as InnerWorkspace } from '../workspace';
|
import { IWorkspace } from '../workspace';
|
||||||
import { EditorWindow } from '../window';
|
import { IEditorWindow } from '../window';
|
||||||
|
|
||||||
export class BasicContext implements IPublicModelPluginContext {
|
export interface IBasicContext extends Omit<IPublicModelPluginContext, 'workspace'> {
|
||||||
skeleton: Skeleton;
|
skeleton: IPublicApiSkeleton;
|
||||||
plugins: Plugins;
|
plugins: IPublicApiPlugins;
|
||||||
project: Project;
|
project: IPublicApiProject;
|
||||||
setters: Setters;
|
setters: IPublicApiSetters;
|
||||||
material: Material;
|
material: IPublicApiMaterial;
|
||||||
common: Common;
|
common: IPublicApiCommon;
|
||||||
config;
|
config: IEngineConfig;
|
||||||
event;
|
event: IPublicApiEvent;
|
||||||
logger;
|
logger: InnerLogger;
|
||||||
hotkey: Hotkey;
|
hotkey: IPublicApiHotkey;
|
||||||
innerProject: InnerProject;
|
innerProject: IProject;
|
||||||
editor: Editor;
|
editor: Editor;
|
||||||
designer: Designer;
|
designer: IDesigner;
|
||||||
registerInnerPlugins: () => Promise<void>;
|
registerInnerPlugins: () => Promise<void>;
|
||||||
innerSetters: InnerSetters;
|
innerSetters: InnerSetters;
|
||||||
innerSkeleton: InnerSkeleton;
|
innerSkeleton: InnerSkeleton;
|
||||||
innerHotkey: InnerHotkey;
|
innerHotkey: IHotKey;
|
||||||
innerPlugins: LowCodePluginManager;
|
innerPlugins: ILowCodePluginManager;
|
||||||
canvas: Canvas;
|
canvas: IPublicApiCanvas;
|
||||||
pluginEvent: IPublicApiEvent;
|
pluginEvent: IPublicApiEvent;
|
||||||
preference: IPluginPreferenceMananger;
|
preference: IPluginPreferenceMananger;
|
||||||
workspace: IPublicApiWorkspace;
|
workspace: IWorkspace;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(innerWorkspace: InnerWorkspace, viewName: string, public editorWindow?: EditorWindow) {
|
export class BasicContext implements IBasicContext {
|
||||||
|
skeleton: IPublicApiSkeleton;
|
||||||
|
plugins: IPublicApiPlugins;
|
||||||
|
project: IPublicApiProject;
|
||||||
|
setters: IPublicApiSetters;
|
||||||
|
material: IPublicApiMaterial;
|
||||||
|
common: IPublicApiCommon;
|
||||||
|
config: IEngineConfig;
|
||||||
|
event: IPublicApiEvent;
|
||||||
|
logger: InnerLogger;
|
||||||
|
hotkey: IPublicApiHotkey;
|
||||||
|
innerProject: IProject;
|
||||||
|
editor: Editor;
|
||||||
|
designer: IDesigner;
|
||||||
|
registerInnerPlugins: () => Promise<void>;
|
||||||
|
innerSetters: InnerSetters;
|
||||||
|
innerSkeleton: InnerSkeleton;
|
||||||
|
innerHotkey: IHotKey;
|
||||||
|
innerPlugins: ILowCodePluginManager;
|
||||||
|
canvas: IPublicApiCanvas;
|
||||||
|
pluginEvent: IPublicApiEvent;
|
||||||
|
preference: IPluginPreferenceMananger;
|
||||||
|
workspace: IWorkspace;
|
||||||
|
|
||||||
|
constructor(innerWorkspace: IWorkspace, viewName: string, public editorWindow?: IEditorWindow) {
|
||||||
const editor = new Editor(viewName, true);
|
const editor = new Editor(viewName, true);
|
||||||
|
|
||||||
const innerSkeleton = new InnerSkeleton(editor, viewName);
|
const innerSkeleton = new InnerSkeleton(editor, viewName);
|
||||||
@ -110,7 +146,7 @@ export class BasicContext implements IPublicModelPluginContext {
|
|||||||
this.canvas = canvas;
|
this.canvas = canvas;
|
||||||
const common = new Common(editor, innerSkeleton);
|
const common = new Common(editor, innerSkeleton);
|
||||||
this.common = common;
|
this.common = common;
|
||||||
let plugins: any;
|
let plugins: IPublicApiPlugins;
|
||||||
|
|
||||||
const pluginContextApiAssembler: ILowCodePluginContextApiAssembler = {
|
const pluginContextApiAssembler: ILowCodePluginContextApiAssembler = {
|
||||||
assembleApis: (context: ILowCodePluginContextPrivate, pluginName: string, meta: IPublicTypePluginMeta) => {
|
assembleApis: (context: ILowCodePluginContextPrivate, pluginName: string, meta: IPublicTypePluginMeta) => {
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import { computed, makeObservable, obx } from '@alilc/lowcode-editor-core';
|
import { computed, makeObservable, obx } from '@alilc/lowcode-editor-core';
|
||||||
import { IPublicEditorViewConfig, IPublicTypeEditorView } from '@alilc/lowcode-types';
|
import { IPublicEditorViewConfig, IPublicTypeEditorView } from '@alilc/lowcode-types';
|
||||||
import { flow } from 'mobx';
|
import { flow } from 'mobx';
|
||||||
import { Workspace as InnerWorkspace } from '../workspace';
|
import { IWorkspace } from '../workspace';
|
||||||
import { BasicContext } from './base-context';
|
import { BasicContext } from './base-context';
|
||||||
import { EditorWindow } from '../window';
|
import { IEditorWindow } from '../window';
|
||||||
import { getWebviewPlugin } from '../inner-plugins/webview';
|
import { getWebviewPlugin } from '../inner-plugins/webview';
|
||||||
|
|
||||||
export class Context extends BasicContext {
|
export class Context extends BasicContext {
|
||||||
@ -21,7 +21,7 @@ export class Context extends BasicContext {
|
|||||||
return this._activate;
|
return this._activate;
|
||||||
}
|
}
|
||||||
|
|
||||||
init = flow(function* (this: any) {
|
init = flow(function* (this: Context) {
|
||||||
if (this.viewType === 'webview') {
|
if (this.viewType === 'webview') {
|
||||||
const url = yield this.instance?.url?.();
|
const url = yield this.instance?.url?.();
|
||||||
yield this.plugins.register(getWebviewPlugin(url, this.viewName));
|
yield this.plugins.register(getWebviewPlugin(url, this.viewName));
|
||||||
@ -33,7 +33,7 @@ export class Context extends BasicContext {
|
|||||||
this.isInit = true;
|
this.isInit = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
constructor(public workspace: InnerWorkspace, public editorWindow: EditorWindow, public editorView: IPublicTypeEditorView, options: Object | undefined) {
|
constructor(public workspace: IWorkspace, public editorWindow: IEditorWindow, public editorView: IPublicTypeEditorView, options: Object | undefined) {
|
||||||
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;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
export { Workspace } from './workspace';
|
export { Workspace, IWorkspace } from './workspace';
|
||||||
export * from './window';
|
export * from './window';
|
||||||
export * from './layouts/workbench';
|
export * from './layouts/workbench';
|
||||||
export { Resource } from './resource';
|
export { Resource, IResource } from './resource';
|
||||||
|
|||||||
@ -1,6 +1,14 @@
|
|||||||
import { IPublicTypeResourceType } from '@alilc/lowcode-types';
|
import { IPublicTypeResourceType } from '@alilc/lowcode-types';
|
||||||
|
|
||||||
export class ResourceType {
|
export interface IResourceType extends Omit<IPublicTypeResourceType, 'resourceName' | 'resourceType'> {
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
type: 'editor' | 'webview';
|
||||||
|
|
||||||
|
resourceTypeModel: IPublicTypeResourceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ResourceType implements IResourceType {
|
||||||
constructor(readonly resourceTypeModel: IPublicTypeResourceType) {
|
constructor(readonly resourceTypeModel: IPublicTypeResourceType) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,31 @@
|
|||||||
import { IPublicTypeEditorView, IPublicModelResource, IPublicResourceData, IPublicResourceTypeConfig } from '@alilc/lowcode-types';
|
import { IPublicTypeEditorView, IPublicResourceData, IPublicResourceTypeConfig, IBaseModelResource } from '@alilc/lowcode-types';
|
||||||
import { Logger } from '@alilc/lowcode-utils';
|
import { Logger } from '@alilc/lowcode-utils';
|
||||||
import { BasicContext } from './context/base-context';
|
import { BasicContext, IBasicContext } from './context/base-context';
|
||||||
import { ResourceType } from './resource-type';
|
import { ResourceType, IResourceType } from './resource-type';
|
||||||
import { Workspace as InnerWorkSpace } from './workspace';
|
import { IWorkspace } from './workspace';
|
||||||
|
|
||||||
const logger = new Logger({ level: 'warn', bizName: 'workspace:resource' });
|
const logger = new Logger({ level: 'warn', bizName: 'workspace:resource' });
|
||||||
|
|
||||||
export class Resource implements IPublicModelResource {
|
export interface IBaseResource<T> extends IBaseModelResource<T> {
|
||||||
private context: BasicContext;
|
readonly resourceType: ResourceType;
|
||||||
|
|
||||||
|
get editorViews(): IPublicTypeEditorView[];
|
||||||
|
|
||||||
|
get defaultViewType(): string;
|
||||||
|
|
||||||
|
getEditorView(name: string): IPublicTypeEditorView | undefined;
|
||||||
|
|
||||||
|
import(schema: any): Promise<any>;
|
||||||
|
|
||||||
|
save(value: any): Promise<any>;
|
||||||
|
|
||||||
|
url(): Promise<string | undefined>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type IResource = IBaseResource<IResource>;
|
||||||
|
|
||||||
|
export class Resource implements IResource {
|
||||||
|
private context: IBasicContext;
|
||||||
|
|
||||||
resourceTypeInstance: IPublicResourceTypeConfig;
|
resourceTypeInstance: IPublicResourceTypeConfig;
|
||||||
|
|
||||||
@ -49,13 +67,13 @@ export class Resource implements IPublicModelResource {
|
|||||||
return this.context.innerSkeleton;
|
return this.context.innerSkeleton;
|
||||||
}
|
}
|
||||||
|
|
||||||
get children(): Resource[] {
|
get children(): IResource[] {
|
||||||
return this.resourceData?.children?.map(d => new Resource(d, this.resourceType, this.workspace)) || [];
|
return this.resourceData?.children?.map(d => new Resource(d, this.resourceType, this.workspace)) || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(readonly resourceData: IPublicResourceData, readonly resourceType: ResourceType, readonly workspace: InnerWorkSpace) {
|
constructor(readonly resourceData: IPublicResourceData, readonly resourceType: IResourceType, readonly workspace: IWorkspace) {
|
||||||
this.context = new BasicContext(workspace, `resource-${resourceData.resourceName || resourceType.name}`);
|
this.context = new BasicContext(workspace, `resource-${resourceData.resourceName || resourceType.name}`);
|
||||||
this.resourceTypeInstance = resourceType.resourceTypeModel(this.context, this.options);
|
this.resourceTypeInstance = resourceType.resourceTypeModel(this.context.innerPlugins._getLowCodePluginContext(), this.options);
|
||||||
this.init();
|
this.init();
|
||||||
if (this.resourceTypeInstance.editorViews) {
|
if (this.resourceTypeInstance.editorViews) {
|
||||||
this.resourceTypeInstance.editorViews.forEach((d: any) => {
|
this.resourceTypeInstance.editorViews.forEach((d: any) => {
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
import { uniqueId } from '@alilc/lowcode-utils';
|
import { uniqueId } from '@alilc/lowcode-utils';
|
||||||
import { createModuleEventBus, IEventBus, makeObservable, obx } from '@alilc/lowcode-editor-core';
|
import { createModuleEventBus, IEventBus, makeObservable, obx } from '@alilc/lowcode-editor-core';
|
||||||
import { Context } from './context/view-context';
|
import { Context } from './context/view-context';
|
||||||
import { Workspace } from './workspace';
|
import { IWorkspace } from './workspace';
|
||||||
import { Resource } from './resource';
|
import { IResource } from './resource';
|
||||||
import { IPublicTypeDisposable } from '../../types/es/shell/type/disposable';
|
import { IPublicTypeDisposable } from '../../types/es/shell/type/disposable';
|
||||||
|
import { IPublicModelWindow } from '@alilc/lowcode-types';
|
||||||
|
|
||||||
interface IWindowCOnfig {
|
interface IWindowCOnfig {
|
||||||
title: string | undefined;
|
title: string | undefined;
|
||||||
@ -11,7 +12,13 @@ interface IWindowCOnfig {
|
|||||||
viewType?: string | undefined;
|
viewType?: string | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class EditorWindow {
|
export interface IEditorWindow extends Omit<IPublicModelWindow<IResource>, 'changeViewType'> {
|
||||||
|
readonly resource: IResource;
|
||||||
|
|
||||||
|
changeViewType: (name: string, ignoreEmit?: boolean) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class EditorWindow implements IEditorWindow {
|
||||||
id: string = uniqueId('window');
|
id: string = uniqueId('window');
|
||||||
icon: React.ReactElement | undefined;
|
icon: React.ReactElement | undefined;
|
||||||
|
|
||||||
@ -27,7 +34,7 @@ export class EditorWindow {
|
|||||||
|
|
||||||
@obx initReady = false;
|
@obx initReady = false;
|
||||||
|
|
||||||
constructor(readonly resource: Resource, readonly workspace: Workspace, private config: IWindowCOnfig) {
|
constructor(readonly resource: IResource, readonly workspace: IWorkspace, private config: IWindowCOnfig) {
|
||||||
makeObservable(this);
|
makeObservable(this);
|
||||||
this.init();
|
this.init();
|
||||||
this.title = config.title;
|
this.title = config.title;
|
||||||
|
|||||||
@ -1,23 +1,33 @@
|
|||||||
import { Designer, LowCodePluginManager } from '@alilc/lowcode-designer';
|
import { IDesigner, ILowCodePluginManager, LowCodePluginManager } 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 { IPublicApiPlugins, IPublicApiWorkspace, IPublicResourceList, IPublicTypeResourceType, IShellModelFactory } from '@alilc/lowcode-types';
|
||||||
import { IPublicApiWorkspace, IPublicResourceList, IPublicTypeResourceType } from '@alilc/lowcode-types';
|
|
||||||
import { BasicContext } from './context/base-context';
|
import { BasicContext } from './context/base-context';
|
||||||
import { EditorWindow } from './window';
|
import { EditorWindow, IEditorWindow } from './window';
|
||||||
import { Resource } from './resource';
|
import { IResource, Resource } from './resource';
|
||||||
import { ResourceType } from './resource-type';
|
import { IResourceType, ResourceType } from './resource-type';
|
||||||
|
|
||||||
enum event {
|
enum EVENT {
|
||||||
ChangeWindow = 'change_window',
|
CHANGE_WINDOW = 'change_window',
|
||||||
|
|
||||||
ChangeActiveWindow = 'change_active_window',
|
CHANGE_ACTIVE_WINDOW = 'change_active_window',
|
||||||
}
|
}
|
||||||
|
|
||||||
const CHANGE_EVENT = 'resource.list.change';
|
const CHANGE_EVENT = 'resource.list.change';
|
||||||
|
|
||||||
interface IWorkspace extends Omit<IPublicApiWorkspace<
|
export interface IWorkspace extends Omit<IPublicApiWorkspace<
|
||||||
LowCodePluginManager
|
LowCodePluginManager,
|
||||||
>, 'resourceList'> {}
|
IEditorWindow
|
||||||
|
>, 'resourceList' | 'plugins'> {
|
||||||
|
readonly registryInnerPlugin: (designer: IDesigner, editor: Editor, plugins: IPublicApiPlugins) => Promise<void>;
|
||||||
|
|
||||||
|
readonly shellModelFactory: IShellModelFactory;
|
||||||
|
|
||||||
|
window: IEditorWindow;
|
||||||
|
|
||||||
|
plugins: ILowCodePluginManager;
|
||||||
|
|
||||||
|
getResourceList(): IResource[];
|
||||||
|
}
|
||||||
|
|
||||||
export class Workspace implements IWorkspace {
|
export class Workspace implements IWorkspace {
|
||||||
context: BasicContext;
|
context: BasicContext;
|
||||||
@ -28,7 +38,7 @@ export class Workspace implements IWorkspace {
|
|||||||
|
|
||||||
private resourceTypeMap: Map<string, ResourceType> = new Map();
|
private resourceTypeMap: Map<string, ResourceType> = new Map();
|
||||||
|
|
||||||
private resourceList: Resource[] = [];
|
private resourceList: IResource[] = [];
|
||||||
|
|
||||||
get skeleton() {
|
get skeleton() {
|
||||||
return this.context.innerSkeleton;
|
return this.context.innerSkeleton;
|
||||||
@ -50,14 +60,14 @@ export class Workspace implements IWorkspace {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@obx.ref windows: EditorWindow[] = [];
|
@obx.ref windows: IEditorWindow[] = [];
|
||||||
|
|
||||||
editorWindowMap: Map<string, EditorWindow> = new Map<string, EditorWindow>();
|
editorWindowMap: Map<string, IEditorWindow> = new Map<string, IEditorWindow>();
|
||||||
|
|
||||||
@obx.ref window: EditorWindow;
|
@obx.ref window: IEditorWindow;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
readonly registryInnerPlugin: (designer: Designer, editor: Editor, plugins: Plugins) => Promise<void>,
|
readonly registryInnerPlugin: (designer: IDesigner, editor: Editor, plugins: IPublicApiPlugins) => Promise<void>,
|
||||||
readonly shellModelFactory: any,
|
readonly shellModelFactory: any,
|
||||||
) {
|
) {
|
||||||
this.init();
|
this.init();
|
||||||
@ -74,7 +84,10 @@ export class Workspace implements IWorkspace {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const title = this.defaultResourceType.name;
|
const title = this.defaultResourceType.name;
|
||||||
const resource = new Resource({}, this.defaultResourceType, this);
|
const resource = new Resource({
|
||||||
|
resourceName: title,
|
||||||
|
options: {},
|
||||||
|
}, this.defaultResourceType, this);
|
||||||
this.window = new EditorWindow(resource, this, {
|
this.window = new EditorWindow(resource, this, {
|
||||||
title,
|
title,
|
||||||
});
|
});
|
||||||
@ -113,7 +126,7 @@ export class Workspace implements IWorkspace {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
getResourceType(resourceName: string): ResourceType {
|
getResourceType(resourceName: string): IResourceType {
|
||||||
return this.resourceTypeMap.get(resourceName)!;
|
return this.resourceTypeMap.get(resourceName)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +152,7 @@ export class Workspace implements IWorkspace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
removeEditorWindow(resourceName: string) {
|
removeEditorWindow(resourceName: string) {
|
||||||
const index = this.windows.findIndex(d => (d.resource.name === resourceName && d.title));
|
const index = this.windows.findIndex(d => (d.resource?.name === resourceName && d.title));
|
||||||
this.remove(index);
|
this.remove(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +170,7 @@ export class Workspace implements IWorkspace {
|
|||||||
console.error(`${name} resourceType is not available`);
|
console.error(`${name} resourceType is not available`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const filterWindows = this.windows.filter(d => (d.resource.name === name && d.resource.title == title));
|
const filterWindows = this.windows.filter(d => (d.resource?.name === name && d.resource.title == title));
|
||||||
if (filterWindows && filterWindows.length) {
|
if (filterWindows && filterWindows.length) {
|
||||||
this.window = filterWindows[0];
|
this.window = filterWindows[0];
|
||||||
this.emitChangeActiveWindow();
|
this.emitChangeActiveWindow();
|
||||||
@ -180,24 +193,24 @@ export class Workspace implements IWorkspace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onChangeWindows(fn: () => void) {
|
onChangeWindows(fn: () => void) {
|
||||||
this.emitter.on(event.ChangeWindow, fn);
|
this.emitter.on(EVENT.CHANGE_WINDOW, fn);
|
||||||
return () => {
|
return () => {
|
||||||
this.emitter.removeListener(event.ChangeWindow, fn);
|
this.emitter.removeListener(EVENT.CHANGE_WINDOW, fn);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
emitChangeWindow() {
|
emitChangeWindow() {
|
||||||
this.emitter.emit(event.ChangeWindow);
|
this.emitter.emit(EVENT.CHANGE_WINDOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
emitChangeActiveWindow() {
|
emitChangeActiveWindow() {
|
||||||
this.emitter.emit(event.ChangeActiveWindow);
|
this.emitter.emit(EVENT.CHANGE_ACTIVE_WINDOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
onChangeActiveWindow(fn: () => void) {
|
onChangeActiveWindow(fn: () => void) {
|
||||||
this.emitter.on(event.ChangeActiveWindow, fn);
|
this.emitter.on(EVENT.CHANGE_ACTIVE_WINDOW, fn);
|
||||||
return () => {
|
return () => {
|
||||||
this.emitter.removeListener(event.ChangeActiveWindow, fn);
|
this.emitter.removeListener(EVENT.CHANGE_ACTIVE_WINDOW, fn);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user