mirror of
https://github.com/smartxworks/sunmao-ui.git
synced 2024-11-21 03:15:49 +08:00
refactor operationManager with appModel
This commit is contained in:
parent
5a89419c5c
commit
5ad0d6fea5
@ -1,3 +1,3 @@
|
||||
import { initSunmaoUIEditor } from '../src';
|
||||
import { sunmaoChakraUILib } from '@sunmao-ui/chakra-ui-lib';
|
||||
export const { registry } = initSunmaoUIEditor({libs: [sunmaoChakraUILib]});
|
||||
export const { registry } = initSunmaoUIEditor({ libs: [sunmaoChakraUILib] });
|
||||
|
@ -80,7 +80,7 @@ export class AppModel implements IAppModel {
|
||||
component.appModel = this;
|
||||
}
|
||||
|
||||
private genId(type: ComponentType): ComponentId {
|
||||
genId(type: ComponentType): ComponentId {
|
||||
const { name } = parseType(type);
|
||||
const newId = `${name}${this.componentsCount++}` as ComponentId;
|
||||
if (this.allComponents.some(c => c.id === newId)) {
|
||||
|
@ -170,9 +170,12 @@ export class ComponentModel implements IComponentModel {
|
||||
removeChild(child: IComponentModel) {
|
||||
const slotChildren = this.children[child.parentSlot!];
|
||||
if (slotChildren) {
|
||||
slotChildren.splice(slotChildren.indexOf(child), 1);
|
||||
child._isDirty = true;
|
||||
this._isDirty = true;
|
||||
const index = slotChildren.indexOf(child)
|
||||
if (index > -1) {
|
||||
slotChildren.splice(slotChildren.indexOf(child), 1);
|
||||
child._isDirty = true;
|
||||
this._isDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,7 @@ export interface IAppModel {
|
||||
// all components, including orphan component
|
||||
allComponentsWithOrphan: IComponentModel[];
|
||||
toSchema(): ComponentSchema[];
|
||||
genId(type: ComponentType): ComponentId;
|
||||
createComponent(type: ComponentType, id?: ComponentId): IComponentModel;
|
||||
getComponentById(id: ComponentId): IComponentModel | undefined;
|
||||
removeComponent(componentId: ComponentId): void;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import produce from 'immer';
|
||||
import { AddIcon, CloseIcon } from '@chakra-ui/icons';
|
||||
import {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Divider, HStack, IconButton, Text, Tooltip, VStack } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
import { Divider, HStack, IconButton, Text, Tooltip, VStack } from '@chakra-ui/react';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { AddIcon, DeleteIcon, EditIcon } from '@chakra-ui/icons';
|
||||
import { EditorServices } from '../../types';
|
||||
|
@ -5,6 +5,8 @@ import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { genOperation } from '../operations';
|
||||
import { PasteManager } from '../operations/PasteManager';
|
||||
import { EditorServices } from '../types';
|
||||
import { AppModel } from '../AppModel/AppModel';
|
||||
import { ComponentId } from '../AppModel/IAppModel';
|
||||
|
||||
type Props = {
|
||||
selectedComponentId: string;
|
||||
@ -18,7 +20,7 @@ export const KeyboardEventWrapper: React.FC<Props> = ({
|
||||
services,
|
||||
children,
|
||||
}) => {
|
||||
const { eventBus,registry } = services;
|
||||
const { eventBus, registry } = services;
|
||||
const pasteManager = useRef(new PasteManager());
|
||||
const style = css`
|
||||
&:focus {
|
||||
@ -55,12 +57,24 @@ export const KeyboardEventWrapper: React.FC<Props> = ({
|
||||
case 'c':
|
||||
// FIXME: detect os version and set redo/undo logic
|
||||
if (e.metaKey || e.ctrlKey) {
|
||||
pasteManager.current.setPasteComponents(selectedComponentId, components);
|
||||
const appModel = new AppModel(components, registry);
|
||||
const copiedComponent = appModel.getComponentById(
|
||||
selectedComponentId as ComponentId
|
||||
);
|
||||
if (copiedComponent) {
|
||||
pasteManager.current.setPasteComponents(selectedComponentId, copiedComponent);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'x':
|
||||
if (e.metaKey || e.ctrlKey) {
|
||||
pasteManager.current.setPasteComponents(selectedComponentId, components);
|
||||
const appModel = new AppModel(components, registry);
|
||||
const copiedComponent = appModel.getComponentById(
|
||||
selectedComponentId as ComponentId
|
||||
);
|
||||
if (copiedComponent) {
|
||||
pasteManager.current.setPasteComponents(selectedComponentId, copiedComponent);
|
||||
}
|
||||
eventBus.send(
|
||||
'operation',
|
||||
genOperation(registry, 'removeComponent', {
|
||||
@ -71,17 +85,19 @@ export const KeyboardEventWrapper: React.FC<Props> = ({
|
||||
break;
|
||||
case 'v':
|
||||
if (e.metaKey || e.ctrlKey) {
|
||||
eventBus.send(
|
||||
'operation',
|
||||
genOperation(registry, 'pasteComponent', {
|
||||
parentId: selectedComponentId,
|
||||
slot: 'content',
|
||||
rootComponentId: pasteManager.current.rootComponentId,
|
||||
components: pasteManager.current.componentsCache,
|
||||
copyTimes: pasteManager.current.copyTimes,
|
||||
})
|
||||
);
|
||||
pasteManager.current.copyTimes++;
|
||||
if (pasteManager.current.componentCache) {
|
||||
eventBus.send(
|
||||
'operation',
|
||||
genOperation(registry, 'pasteComponent', {
|
||||
parentId: selectedComponentId,
|
||||
slot: 'content',
|
||||
rootComponentId: pasteManager.current.rootComponentId,
|
||||
component: pasteManager.current.componentCache,
|
||||
copyTimes: pasteManager.current.copyTimes,
|
||||
})
|
||||
);
|
||||
pasteManager.current.copyTimes++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -8,9 +8,13 @@ export class AppModelManager implements IUndoRedoManager {
|
||||
appModel: AppModel;
|
||||
operationStack: OperationList<IOperation> = new OperationList();
|
||||
|
||||
constructor(private eventBus: EventBusType, private registry: Registry, initComponents: ComponentSchema[]) {
|
||||
this.appModel = new AppModel(initComponents, this.registry)
|
||||
|
||||
constructor(
|
||||
private eventBus: EventBusType,
|
||||
private registry: Registry,
|
||||
initComponents: ComponentSchema[]
|
||||
) {
|
||||
this.appModel = new AppModel(initComponents, this.registry);
|
||||
|
||||
eventBus.on('undo', () => this.undo());
|
||||
eventBus.on('redo', () => this.redo());
|
||||
eventBus.on('operation', o => this.do(o));
|
||||
@ -69,7 +73,7 @@ export class AppModelManager implements IUndoRedoManager {
|
||||
if (newComponents) {
|
||||
this.updateComponents(newComponents);
|
||||
} else {
|
||||
//rollback move prev
|
||||
// rollback move prev
|
||||
this.operationStack.moveNext();
|
||||
console.warn('cannot undo as cursor has no operation', this.operationStack);
|
||||
}
|
||||
|
@ -1,14 +1,12 @@
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { getComponentAndChildrens } from './util';
|
||||
import { IComponentModel } from '../AppModel/IAppModel';
|
||||
|
||||
export class PasteManager {
|
||||
rootComponentId = ''
|
||||
componentsCache: ComponentSchema[] = [];
|
||||
componentCache: IComponentModel | undefined;
|
||||
copyTimes = 0;
|
||||
|
||||
setPasteComponents(componentId: string, allComponents: ComponentSchema[]) {
|
||||
setPasteComponents(componentId: string, component: IComponentModel) {
|
||||
this.rootComponentId = componentId;
|
||||
const children = getComponentAndChildrens(componentId, allComponents);
|
||||
this.componentsCache = [...children];
|
||||
this.componentCache = component;
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { AppModel } from '../../AppModel/AppModel';
|
||||
import ReactGridLayout from 'react-grid-layout';
|
||||
import produce from 'immer';
|
||||
import { ComponentId, SlotName } from '../../AppModel/IAppModel';
|
||||
import { ComponentId, ComponentType, SlotName } from '../../AppModel/IAppModel';
|
||||
import {
|
||||
CreateComponentLeafOperation,
|
||||
ModifyComponentPropertiesLeafOperation,
|
||||
} from '../leaf';
|
||||
import { BaseBranchOperation } from '../type';
|
||||
import { genId } from '../util';
|
||||
|
||||
export type CreateComponentBranchOperationContext = {
|
||||
componentType: string;
|
||||
@ -17,10 +17,10 @@ export type CreateComponentBranchOperationContext = {
|
||||
};
|
||||
|
||||
export class CreateComponentBranchOperation extends BaseBranchOperation<CreateComponentBranchOperationContext> {
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
do(prev: AppModel): AppModel {
|
||||
// gen component id
|
||||
if (!this.context.componentId) {
|
||||
this.context.componentId = genId(this.context.componentType, prev);
|
||||
this.context.componentId = prev.genId(this.context.componentType as ComponentType);
|
||||
}
|
||||
// insert a new component to schema
|
||||
this.operationStack.insert(
|
||||
@ -34,9 +34,7 @@ export class CreateComponentBranchOperation extends BaseBranchOperation<CreateCo
|
||||
// add a slot trait if it has a parent
|
||||
if (this.context.parentId && this.context.slot) {
|
||||
// try to find parent
|
||||
const parentComponent = prev.find(
|
||||
c => c.id === this.context.parentId
|
||||
);
|
||||
const parentComponent = prev.getComponentById(this.context.parentId as ComponentId);
|
||||
|
||||
if (!parentComponent) {
|
||||
console.warn("insert element has an invalid parent, it won't show in the view");
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { AppModel } from '../../AppModel/AppModel';
|
||||
import { BaseBranchOperation } from '../type';
|
||||
import {
|
||||
ModifyComponentIdLeafOperation,
|
||||
@ -11,7 +11,7 @@ export type ModifyComponentIdBranchOperationContext = {
|
||||
};
|
||||
|
||||
export class ModifyComponentIdBranchOperation extends BaseBranchOperation<ModifyComponentIdBranchOperationContext> {
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
do(prev: AppModel): AppModel {
|
||||
this.operationStack.insert(new ModifyComponentIdLeafOperation(this.registry, this.context));
|
||||
|
||||
// update selectid
|
||||
|
@ -1,6 +1,11 @@
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { AppModel } from '../../AppModel/AppModel';
|
||||
import { BaseBranchOperation } from '../type';
|
||||
import { CreateTraitLeafOperation, ModifyTraitPropertiesLeafOperation, RemoveTraitLeafOperation } from '../leaf';
|
||||
import {
|
||||
CreateTraitLeafOperation,
|
||||
ModifyTraitPropertiesLeafOperation,
|
||||
RemoveTraitLeafOperation,
|
||||
} from '../leaf';
|
||||
import { ComponentId } from '../../AppModel/IAppModel';
|
||||
|
||||
export type MoveComponentBranchOperationContext = {
|
||||
fromId: string;
|
||||
@ -9,12 +14,12 @@ export type MoveComponentBranchOperationContext = {
|
||||
};
|
||||
|
||||
export class MoveComponentBranchOperation extends BaseBranchOperation<MoveComponentBranchOperationContext> {
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const from = prev.find(c => c.id === this.context.fromId);
|
||||
do(prev: AppModel): AppModel {
|
||||
const from = prev.getComponentById(this.context.fromId as ComponentId);
|
||||
if (!from) return prev;
|
||||
|
||||
|
||||
const traitIndex = from.traits.findIndex(t => t.type === 'core/v1/slot');
|
||||
|
||||
|
||||
if (this.context.toId === '__root__') {
|
||||
this.operationStack.insert(
|
||||
new RemoveTraitLeafOperation(this.registry, {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import produce from 'immer';
|
||||
import ReactGridLayout from 'react-grid-layout';
|
||||
import { AppModel } from '../../AppModel/AppModel';
|
||||
import { ComponentId } from '../../AppModel/IAppModel';
|
||||
import {
|
||||
@ -13,9 +13,8 @@ export type RemoveComponentBranchOperationContext = {
|
||||
};
|
||||
|
||||
export class RemoveComponentBranchOperation extends BaseBranchOperation<RemoveComponentBranchOperationContext> {
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev, this.registry);
|
||||
const parent = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
do(prev: AppModel): AppModel {
|
||||
const parent = prev.getComponentById(this.context.componentId as ComponentId);
|
||||
|
||||
if (parent && parent.type === 'core/v1/grid_layout') {
|
||||
// modify layout property of parent grid layout component
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { AppModel } from '../../../AppModel/AppModel';
|
||||
import { ComponentId } from '../../../AppModel/IAppModel';
|
||||
import { BaseLeafOperation } from '../../type';
|
||||
@ -8,20 +7,20 @@ export type AdjustComponentOrderLeafOperationContext = {
|
||||
};
|
||||
|
||||
export class AdjustComponentOrderLeafOperation extends BaseLeafOperation<AdjustComponentOrderLeafOperationContext> {
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
do(prev: AppModel): AppModel {
|
||||
return this.move(prev, this.context.orientation);
|
||||
}
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
return this.do(prev)
|
||||
|
||||
redo(prev: AppModel): AppModel {
|
||||
return this.do(prev);
|
||||
}
|
||||
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
undo(prev: AppModel): AppModel {
|
||||
return this.move(prev, this.context.orientation === 'up' ? 'down' : 'up');
|
||||
}
|
||||
|
||||
private move(prev: ComponentSchema[], orientation: 'up' | 'down'): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev, this.registry);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
private move(prev: AppModel, orientation: 'up' | 'down'): AppModel {
|
||||
const component = prev.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
console.warn('component not found');
|
||||
return prev;
|
||||
@ -43,6 +42,6 @@ export class AdjustComponentOrderLeafOperation extends BaseLeafOperation<AdjustC
|
||||
component.moveAfter(component.nextSilbing || null);
|
||||
break;
|
||||
}
|
||||
return appModel.toSchema();
|
||||
return prev;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { AppModel } from '../../../AppModel/AppModel';
|
||||
import { ComponentId, ComponentType, IComponentModel, SlotName } from '../../../AppModel/IAppModel';
|
||||
import {
|
||||
ComponentId,
|
||||
ComponentType,
|
||||
IComponentModel,
|
||||
SlotName,
|
||||
} from '../../../AppModel/IAppModel';
|
||||
import { BaseLeafOperation } from '../../type';
|
||||
|
||||
export type CreateComponentLeafOperationContext = {
|
||||
@ -13,11 +17,13 @@ export type CreateComponentLeafOperationContext = {
|
||||
export class CreateComponentLeafOperation extends BaseLeafOperation<CreateComponentLeafOperationContext> {
|
||||
private component!: IComponentModel;
|
||||
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev, this.registry);
|
||||
const component = appModel.createComponent(this.context.componentType as ComponentType, this.context.componentId as ComponentId);
|
||||
do(prev: AppModel): AppModel {
|
||||
const component = prev.createComponent(
|
||||
this.context.componentType as ComponentType,
|
||||
this.context.componentId as ComponentId
|
||||
);
|
||||
if (this.context.parentId) {
|
||||
const parent = appModel.getComponentById(this.context.parentId);
|
||||
const parent = prev.getComponentById(this.context.parentId);
|
||||
if (parent) {
|
||||
component.appendTo(parent, this.context.slot);
|
||||
}
|
||||
@ -25,17 +31,15 @@ export class CreateComponentLeafOperation extends BaseLeafOperation<CreateCompon
|
||||
component.appendTo();
|
||||
}
|
||||
this.component = component;
|
||||
const newSchema = appModel.toSchema()
|
||||
return newSchema
|
||||
return prev;
|
||||
}
|
||||
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
return this.do(prev)
|
||||
redo(prev: AppModel): AppModel {
|
||||
return this.do(prev);
|
||||
}
|
||||
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev, this.registry);
|
||||
appModel.removeComponent(this.component.id)
|
||||
return appModel.toSchema()
|
||||
undo(prev: AppModel): AppModel {
|
||||
prev.removeComponent(this.component.id);
|
||||
return prev;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { AppModel } from '../../../AppModel/AppModel';
|
||||
import { ComponentId } from '../../../AppModel/IAppModel';
|
||||
import { BaseLeafOperation } from '../../type';
|
||||
@ -9,23 +8,23 @@ export type ModifyComponentIdLeafOperationContext = {
|
||||
};
|
||||
|
||||
export class ModifyComponentIdLeafOperation extends BaseLeafOperation<ModifyComponentIdLeafOperationContext> {
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev, this.registry);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
do(prev: AppModel): AppModel {
|
||||
const component = prev.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
console.warn('component not found');
|
||||
return prev;
|
||||
}
|
||||
component.changeId(this.context.newId as ComponentId);
|
||||
return appModel.toSchema();
|
||||
return prev;
|
||||
}
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
|
||||
redo(prev: AppModel): AppModel {
|
||||
return this.do(prev);
|
||||
}
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev, this.registry);
|
||||
const component = appModel.getComponentById(this.context.newId as ComponentId)!;
|
||||
|
||||
undo(prev: AppModel): AppModel {
|
||||
const component = prev.getComponentById(this.context.newId as ComponentId)!;
|
||||
component.changeId(this.context.componentId as ComponentId);
|
||||
return appModel.toSchema();
|
||||
return prev;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { BaseLeafOperation } from '../../type';
|
||||
import _ from 'lodash-es';
|
||||
import { AppModel } from '../../../AppModel/AppModel';
|
||||
@ -10,9 +9,8 @@ export type ModifyComponentPropertiesLeafOperationContext = {
|
||||
|
||||
export class ModifyComponentPropertiesLeafOperation extends BaseLeafOperation<ModifyComponentPropertiesLeafOperationContext> {
|
||||
private previousState: Record<string, any> = {};
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev, this.registry);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
do(prev: AppModel): AppModel {
|
||||
const component = prev.getComponentById(this.context.componentId as ComponentId);
|
||||
if (component) {
|
||||
for (const property in this.context.properties) {
|
||||
const oldValue = component.rawProperties[property];
|
||||
@ -31,12 +29,11 @@ export class ModifyComponentPropertiesLeafOperation extends BaseLeafOperation<Mo
|
||||
return prev;
|
||||
}
|
||||
|
||||
const newSchema = appModel.toSchema();
|
||||
return newSchema;
|
||||
return prev;
|
||||
}
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev, this.registry);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
|
||||
redo(prev: AppModel): AppModel {
|
||||
const component = prev.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
console.warn('component not found');
|
||||
return prev;
|
||||
@ -45,11 +42,11 @@ export class ModifyComponentPropertiesLeafOperation extends BaseLeafOperation<Mo
|
||||
for (const property in this.context.properties) {
|
||||
component.updateComponentProperty(property, this.context.properties[property]);
|
||||
}
|
||||
return appModel.toSchema();
|
||||
return prev;
|
||||
}
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev, this.registry);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
|
||||
undo(prev: AppModel): AppModel {
|
||||
const component = prev.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
console.warn('component not found');
|
||||
return prev;
|
||||
@ -59,6 +56,6 @@ export class ModifyComponentPropertiesLeafOperation extends BaseLeafOperation<Mo
|
||||
component.updateComponentProperty(property, this.previousState[property]);
|
||||
}
|
||||
|
||||
return appModel.toSchema();
|
||||
return prev;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { AppModel } from '../../../AppModel/AppModel';
|
||||
import { ComponentId, IComponentModel, SlotName } from '../../../AppModel/IAppModel';
|
||||
import { BaseLeafOperation } from '../../type';
|
||||
@ -7,40 +6,37 @@ export type PasteComponentLeafOperationContext = {
|
||||
parentId: string;
|
||||
slot: string;
|
||||
rootComponentId: string;
|
||||
components: ComponentSchema[];
|
||||
component: IComponentModel;
|
||||
copyTimes: number;
|
||||
};
|
||||
|
||||
export class PasteComponentLeafOperation extends BaseLeafOperation<PasteComponentLeafOperationContext> {
|
||||
private componentCopy!: IComponentModel
|
||||
private componentCopy!: IComponentModel;
|
||||
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev, this.registry);
|
||||
const targetParent = appModel.getComponentById(this.context.parentId as ComponentId);
|
||||
do(prev: AppModel): AppModel {
|
||||
const targetParent = prev.getComponentById(this.context.parentId as ComponentId);
|
||||
if (!targetParent) {
|
||||
return prev
|
||||
}
|
||||
const copyComponents = new AppModel(this.context.components, this.registry);
|
||||
const component = copyComponents.getComponentById(this.context.rootComponentId as ComponentId);
|
||||
if (!component){
|
||||
return prev;
|
||||
}
|
||||
component.allComponents.forEach((c) => {
|
||||
c.changeId(`${c.id}_copy${this.context.copyTimes}` as ComponentId)
|
||||
})
|
||||
const component = this.context.component;
|
||||
if (!component) {
|
||||
return prev;
|
||||
}
|
||||
component.allComponents.forEach(c => {
|
||||
c.changeId(`${c.id}_copy${this.context.copyTimes}` as ComponentId);
|
||||
});
|
||||
targetParent.appendChild(component, this.context.slot as SlotName);
|
||||
this.componentCopy = component;
|
||||
|
||||
return appModel.toSchema();
|
||||
return prev;
|
||||
}
|
||||
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
return this.do(prev)
|
||||
redo(prev: AppModel): AppModel {
|
||||
return this.do(prev);
|
||||
}
|
||||
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev, this.registry);
|
||||
appModel.removeComponent(this.componentCopy.id);
|
||||
return appModel.toSchema()
|
||||
|
||||
undo(prev: AppModel): AppModel {
|
||||
prev.removeComponent(this.componentCopy.id);
|
||||
return prev;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
|
||||
import { AppModel } from '../../../AppModel/AppModel';
|
||||
import { ComponentId, IComponentModel, SlotName } from '../../../AppModel/IAppModel';
|
||||
import { BaseLeafOperation } from '../../type';
|
||||
@ -11,26 +11,24 @@ export class RemoveComponentLeafOperation extends BaseLeafOperation<RemoveCompon
|
||||
private deletedComponent?: IComponentModel;
|
||||
private prevComponent?: IComponentModel;
|
||||
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev, this.registry);
|
||||
this.deletedComponent = appModel.getComponentById(
|
||||
do(prev: AppModel): AppModel {
|
||||
this.deletedComponent = prev.getComponentById(
|
||||
this.context.componentId as ComponentId
|
||||
);
|
||||
this.prevComponent = this.deletedComponent?.prevSilbling || undefined;
|
||||
appModel.removeComponent(this.context.componentId as ComponentId);
|
||||
return appModel.toSchema();
|
||||
prev.removeComponent(this.context.componentId as ComponentId);
|
||||
return prev;
|
||||
}
|
||||
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
redo(prev: AppModel): AppModel {
|
||||
return this.do(prev);
|
||||
}
|
||||
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
undo(prev: AppModel): AppModel {
|
||||
if (!this.deletedComponent) {
|
||||
return prev;
|
||||
}
|
||||
const appModel = new AppModel(prev, this.registry);
|
||||
const parent = appModel.getComponentById(
|
||||
const parent = prev.getComponentById(
|
||||
this.deletedComponent.parentId as ComponentId
|
||||
);
|
||||
if (parent) {
|
||||
@ -39,9 +37,9 @@ export class RemoveComponentLeafOperation extends BaseLeafOperation<RemoveCompon
|
||||
this.deletedComponent.parentSlot as SlotName
|
||||
);
|
||||
} else {
|
||||
appModel.appendChild(this.deletedComponent);
|
||||
prev.appendChild(this.deletedComponent);
|
||||
}
|
||||
this.deletedComponent.moveAfter(this.prevComponent || null);
|
||||
return appModel.toSchema();
|
||||
return prev;
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +1,28 @@
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
|
||||
import produce from 'immer';
|
||||
import { AppModel } from '../../AppModel/AppModel';
|
||||
import { BaseLeafOperation } from '../type';
|
||||
|
||||
export type ReplaceAppLeafOperationContext = {
|
||||
app: ComponentSchema[];
|
||||
app: AppModel;
|
||||
};
|
||||
|
||||
export class ReplaceAppLeafOperation extends BaseLeafOperation<ReplaceAppLeafOperationContext> {
|
||||
private previousState!: ComponentSchema[];
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
private previousState!: AppModel;
|
||||
do(prev: AppModel): AppModel {
|
||||
this.previousState = prev;
|
||||
return produce(prev, () => {
|
||||
return this.context.app;
|
||||
});
|
||||
}
|
||||
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
redo(prev: AppModel): AppModel {
|
||||
return produce(prev, () => {
|
||||
return this.context.app;
|
||||
});
|
||||
}
|
||||
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
undo(prev: AppModel): AppModel {
|
||||
return produce(prev, () => {
|
||||
return this.previousState;
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
|
||||
import { AppModel } from '../../../AppModel/AppModel';
|
||||
import { ComponentId, TraitId, TraitType } from '../../../AppModel/IAppModel';
|
||||
import { BaseLeafOperation } from '../../type';
|
||||
@ -12,28 +12,26 @@ export type CreateTraitLeafOperationContext = {
|
||||
export class CreateTraitLeafOperation extends BaseLeafOperation<CreateTraitLeafOperationContext> {
|
||||
private traitId!: TraitId;
|
||||
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev, this.registry);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
do(prev: AppModel): AppModel {
|
||||
const component = prev.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
return prev
|
||||
}
|
||||
const trait = component.addTrait(this.context.traitType as TraitType, this.context.properties);
|
||||
this.traitId = trait.id;
|
||||
return appModel.toSchema()
|
||||
return prev
|
||||
}
|
||||
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
redo(prev: AppModel): AppModel {
|
||||
return this.do(prev);
|
||||
}
|
||||
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev, this.registry);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
undo(prev: AppModel): AppModel {
|
||||
const component = prev.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
return prev
|
||||
}
|
||||
component.removeTrait(this.traitId);
|
||||
return appModel.toSchema()
|
||||
return prev
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import _ from 'lodash-es';
|
||||
import { BaseLeafOperation } from '../../type';
|
||||
import { AppModel } from '../../../AppModel/AppModel';
|
||||
@ -12,9 +11,8 @@ export type ModifyTraitPropertiesLeafOperationContext = {
|
||||
|
||||
export class ModifyTraitPropertiesLeafOperation extends BaseLeafOperation<ModifyTraitPropertiesLeafOperationContext> {
|
||||
private previousState: Record<string, any> = {};
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev, this.registry);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
do(prev: AppModel): AppModel {
|
||||
const component = prev.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
console.warn('component not found');
|
||||
return prev;
|
||||
@ -32,11 +30,11 @@ export class ModifyTraitPropertiesLeafOperation extends BaseLeafOperation<Modify
|
||||
trait.updateProperty(property, this.context.properties[property]);
|
||||
}
|
||||
|
||||
return appModel.toSchema();
|
||||
return prev;
|
||||
}
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev, this.registry);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
|
||||
redo(prev: AppModel): AppModel {
|
||||
const component = prev.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
console.warn('component not found');
|
||||
return prev;
|
||||
@ -47,12 +45,11 @@ export class ModifyTraitPropertiesLeafOperation extends BaseLeafOperation<Modify
|
||||
trait.updateProperty(property, this.context.properties[property]);
|
||||
}
|
||||
|
||||
return appModel.toSchema();
|
||||
return prev;
|
||||
}
|
||||
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev, this.registry);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
undo(prev: AppModel): AppModel {
|
||||
const component = prev.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
console.warn('component not found');
|
||||
return prev;
|
||||
@ -63,6 +60,6 @@ export class ModifyTraitPropertiesLeafOperation extends BaseLeafOperation<Modify
|
||||
trait.updateProperty(property, this.previousState[property]);
|
||||
}
|
||||
|
||||
return appModel.toSchema();
|
||||
return prev;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { AppModel } from '../../../AppModel/AppModel';
|
||||
import { ComponentId, ITraitModel } from '../../../AppModel/IAppModel';
|
||||
import { BaseLeafOperation } from '../../type';
|
||||
@ -10,9 +9,8 @@ export type RemoveTraitLeafOperationContext = {
|
||||
|
||||
export class RemoveTraitLeafOperation extends BaseLeafOperation<RemoveTraitLeafOperationContext> {
|
||||
private deletedTrait!: ITraitModel;
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev, this.registry);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
do(prev: AppModel): AppModel {
|
||||
const component = prev.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
console.warn('component not found');
|
||||
return prev;
|
||||
@ -20,22 +18,21 @@ export class RemoveTraitLeafOperation extends BaseLeafOperation<RemoveTraitLeafO
|
||||
|
||||
this.deletedTrait = component.traits[this.context.index];
|
||||
component.removeTrait(this.deletedTrait.id);
|
||||
return appModel.toSchema();
|
||||
return prev;
|
||||
}
|
||||
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
redo(prev: AppModel): AppModel {
|
||||
return this.do(prev);
|
||||
}
|
||||
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
const appModel = new AppModel(prev, this.registry);
|
||||
const component = appModel.getComponentById(this.context.componentId as ComponentId);
|
||||
undo(prev: AppModel): AppModel {
|
||||
const component = prev.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
console.warn('component not found');
|
||||
return prev;
|
||||
}
|
||||
|
||||
component.addTrait(this.deletedTrait.type, this.deletedTrait.rawProperties);
|
||||
return appModel.toSchema();
|
||||
return prev;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
|
||||
import { AppModel } from '../../AppModel/AppModel';
|
||||
import { BaseLeafOperation } from '../type';
|
||||
|
||||
export type UpdateSelectComponentLeafOperationContext = {
|
||||
@ -8,22 +9,22 @@ export type UpdateSelectComponentLeafOperationContext = {
|
||||
|
||||
export class UpdateSelectComponentLeafOperation extends BaseLeafOperation<UpdateSelectComponentLeafOperationContext> {
|
||||
prevId!: string;
|
||||
do(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
this.prevId = this.context.componentId || prev[0].id;
|
||||
do(prev: AppModel): AppModel {
|
||||
this.prevId = this.context.componentId || prev.topComponents[0].id;
|
||||
setTimeout(() => {
|
||||
// eventBus.send('selectComponent', this.context.newId);
|
||||
});
|
||||
return prev;
|
||||
}
|
||||
|
||||
redo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
redo(prev: AppModel): AppModel {
|
||||
setTimeout(() => {
|
||||
// eventBus.send('selectComponent', this.context.newId);
|
||||
});
|
||||
return prev;
|
||||
}
|
||||
|
||||
undo(prev: ComponentSchema[]): ComponentSchema[] {
|
||||
undo(prev: AppModel): AppModel {
|
||||
setTimeout(() => {
|
||||
// eventBus.send('selectComponent', this.prevId);
|
||||
});
|
||||
|
@ -1,49 +0,0 @@
|
||||
import { ComponentSchema, parseType } from '@sunmao-ui/core';
|
||||
import { Registry } from '@sunmao-ui/runtime';
|
||||
import { isDraft, original } from 'immer';
|
||||
import { get } from 'lodash-es';
|
||||
|
||||
export function genComponent(registry: Registry, type: string, id: string): ComponentSchema {
|
||||
const { version, name } = parseType(type);
|
||||
const cImpl = registry.getComponent(version, name);
|
||||
const initProperties = cImpl.metadata.exampleProperties;
|
||||
return {
|
||||
id,
|
||||
type: type,
|
||||
properties: initProperties,
|
||||
traits: [],
|
||||
};
|
||||
}
|
||||
|
||||
export function genId(componentType: string, components: ComponentSchema[]): string {
|
||||
const { name } = parseType(componentType);
|
||||
const componentsCount = components.filter(
|
||||
component => component.type === componentType
|
||||
).length;
|
||||
return `${name}${componentsCount + 1}`;
|
||||
}
|
||||
|
||||
export function tryOriginal<T>(val: T): T {
|
||||
return isDraft(val) ? (original(val) as T) : val;
|
||||
}
|
||||
|
||||
export function getComponentAndChildrens(
|
||||
componentId: string,
|
||||
allComponents: ComponentSchema[]
|
||||
): ComponentSchema[] {
|
||||
const target = allComponents.find(c => c.id === componentId);
|
||||
if (!target) {
|
||||
return [];
|
||||
}
|
||||
return allComponents.reduce<ComponentSchema[]>(
|
||||
(result, component) => {
|
||||
const slotTrait = component.traits.find(trait => trait.type === 'core/v1/slot');
|
||||
const slotId = get(slotTrait, 'properties.container.id');
|
||||
if (slotId === componentId) {
|
||||
return result.concat(getComponentAndChildrens(component.id, allComponents));
|
||||
}
|
||||
return result;
|
||||
},
|
||||
[target]
|
||||
);
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { Flex, Box, ChakraProvider, Button } from '@chakra-ui/react';
|
||||
import { Application } from '@sunmao-ui/core';
|
||||
import { Registry } from '@sunmao-ui/runtime/lib/services/registry';
|
||||
import { StrictMode, useState } from 'react';
|
||||
import React, { StrictMode, useState } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './styles.css';
|
||||
|
||||
|
@ -30,7 +30,6 @@ export class EditorStore {
|
||||
// when componentsChange event is triggered, currentComponentsVersion++
|
||||
currentComponentsVersion = 0;
|
||||
lastSavedComponentsVersion = 0;
|
||||
|
||||
schemaValidator: SchemaValidator;
|
||||
|
||||
constructor(
|
||||
|
Loading…
Reference in New Issue
Block a user