refactor operationManager with appModel

This commit is contained in:
Bowen Tan 2022-01-21 09:53:49 +08:00
parent 5a89419c5c
commit 5ad0d6fea5
27 changed files with 188 additions and 227 deletions

View File

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

View File

@ -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)) {

View File

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

View File

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

View File

@ -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 {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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, {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -30,7 +30,6 @@ export class EditorStore {
// when componentsChange event is triggered, currentComponentsVersion++
currentComponentsVersion = 0;
lastSavedComponentsVersion = 0;
schemaValidator: SchemaValidator;
constructor(