mirror of
https://github.com/smartxworks/sunmao-ui.git
synced 2024-11-21 03:15:49 +08:00
add AppModel
This commit is contained in:
parent
3d51429240
commit
3a505db5e2
69
packages/editor/src/operations/AppModel/AppModel.ts
Normal file
69
packages/editor/src/operations/AppModel/AppModel.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { ComponentModel } from './ComponentModel';
|
||||
import {
|
||||
ComponentId,
|
||||
ComponentType,
|
||||
IApplicationModel,
|
||||
IComponentModel,
|
||||
IModuleModel,
|
||||
ModuleId,
|
||||
ModuleType,
|
||||
SlotName,
|
||||
} from './IAppModel';
|
||||
export class ApplicationModel implements IApplicationModel {
|
||||
components: IComponentModel[] = [];
|
||||
modules: IModuleModel[] = [];
|
||||
allComponents: IComponentModel[] = [];
|
||||
private origin: ApplicationComponent[] = [];
|
||||
private componentMap: Record<ComponentId, IComponentModel> = {};
|
||||
|
||||
constructor(components: ApplicationComponent[]) {
|
||||
this.origin = components;
|
||||
this.resolveTree(components);
|
||||
}
|
||||
|
||||
resolveTree(components: ApplicationComponent[]) {
|
||||
this.allComponents = components.map(c => {
|
||||
const comp = new ComponentModel(c);
|
||||
this.componentMap[c.id as ComponentId] = comp;
|
||||
return comp;
|
||||
});
|
||||
|
||||
this.allComponents.forEach(child => {
|
||||
if (child.parentId && child.parentSlot) {
|
||||
const parent = this.componentMap[child.parentId];
|
||||
if (parent) {
|
||||
if (parent.children[child.parentSlot]) {
|
||||
parent.children[child.parentSlot].push(child);
|
||||
} else {
|
||||
parent.children[child.parentSlot] = [child];
|
||||
}
|
||||
}
|
||||
child.parent = parent;
|
||||
} else {
|
||||
this.components.push(child);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
get json(): ApplicationComponent[] {
|
||||
return this.origin;
|
||||
}
|
||||
// createComponent (
|
||||
// componentType: ComponentType,
|
||||
// componentId: ComponentId,
|
||||
// properties: Record<string, string>
|
||||
// ) {
|
||||
// return
|
||||
// }
|
||||
// createModule: (moduleId: ModuleId, moduleType: ModuleType) => IModuleModel;
|
||||
// removeComponent: (componentId: ComponentId) => void;
|
||||
// removeModule: (moduleId: ModuleId) => void;
|
||||
// findComponent: (componentId: ComponentId) => IComponentModel | undefined;
|
||||
// moveComponent: (
|
||||
// fromId: ComponentId,
|
||||
// toId: ComponentId,
|
||||
// slot: SlotName,
|
||||
// afterId: ComponentId
|
||||
// ) => void;
|
||||
}
|
86
packages/editor/src/operations/AppModel/ComponentModel.ts
Normal file
86
packages/editor/src/operations/AppModel/ComponentModel.ts
Normal file
@ -0,0 +1,86 @@
|
||||
import { ApplicationComponent, RuntimeComponentSpec } from '@sunmao-ui/core';
|
||||
import { registry } from '../../setup';
|
||||
import {
|
||||
ComponentId,
|
||||
ComponentType,
|
||||
IApplicationModel,
|
||||
IComponentModel,
|
||||
IModuleModel,
|
||||
ModuleId,
|
||||
ModuleType,
|
||||
SlotName,
|
||||
StyleSlotName,
|
||||
MethodName,
|
||||
StateKey,
|
||||
ITraitModel,
|
||||
IFieldModel,
|
||||
EventName,
|
||||
} from './IAppModel';
|
||||
import { TraitModel } from './TraitModel';
|
||||
|
||||
export class ComponentModel implements IComponentModel {
|
||||
private origin: ApplicationComponent;
|
||||
private spec: RuntimeComponentSpec;
|
||||
|
||||
id: ComponentId;
|
||||
type: ComponentType;
|
||||
properties: Record<string, IFieldModel> = {};
|
||||
children: Record<SlotName, IComponentModel[]> = {};
|
||||
parent: IComponentModel | null = null;
|
||||
parentId: ComponentId | null = null;
|
||||
parentSlot: SlotName | null = null;
|
||||
traits: ITraitModel[] = [];
|
||||
|
||||
constructor(component: ApplicationComponent) {
|
||||
this.origin = component;
|
||||
|
||||
this.id = component.id as ComponentId;
|
||||
this.type = component.type as ComponentType;
|
||||
this.spec = registry.getComponentByType(this.type);
|
||||
|
||||
this.traits = component.traits.map(t => new TraitModel(t, this));
|
||||
// find slot trait
|
||||
this.traits.forEach(t => {
|
||||
if (t.type === 'core/v1/slot') {
|
||||
this.parentId = t.properties.container.id;
|
||||
this.parentSlot = t.properties.container.slot;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
get slots() {
|
||||
return (this.spec ? this.spec.spec.slots : []) as SlotName[];
|
||||
}
|
||||
|
||||
get stateKeys() {
|
||||
if (!this.spec) return [];
|
||||
const componentStateKeys = Object.keys(this.spec.spec.state) as StateKey[];
|
||||
const traitStateKeys: StateKey[] = this.traits.reduce(
|
||||
(acc, t) => acc.concat(t.stateKeys),
|
||||
[] as StateKey[]
|
||||
);
|
||||
return [...componentStateKeys, ...traitStateKeys]
|
||||
}
|
||||
|
||||
get events() {
|
||||
return (this.spec ? this.spec.spec.events : []) as EventName[];
|
||||
}
|
||||
|
||||
get methods() {
|
||||
if (!this.spec) return [];
|
||||
const componentMethods = this.spec.spec.methods.map(m => m.name) as MethodName[];
|
||||
const traitMethods: MethodName[] = this.traits.reduce(
|
||||
(acc, t) => acc.concat(t.methods),
|
||||
[] as MethodName[]
|
||||
);
|
||||
return [...componentMethods, ...traitMethods]
|
||||
}
|
||||
|
||||
get styleSlots() {
|
||||
return (this.spec ? this.spec.spec.styleSlots : []) as StyleSlotName[];
|
||||
}
|
||||
|
||||
get json(): ApplicationComponent {
|
||||
return this.origin;
|
||||
}
|
||||
}
|
14
packages/editor/src/operations/AppModel/FieldModel.ts
Normal file
14
packages/editor/src/operations/AppModel/FieldModel.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { IFieldModel } from './IAppModel';
|
||||
|
||||
const regExp = new RegExp('.*{{.*}}.*');
|
||||
|
||||
export class FieldModel implements IFieldModel {
|
||||
value: any;
|
||||
isDynamic = false;
|
||||
// refs: Array<ComponentId | ModuleId> = []
|
||||
|
||||
constructor(value: unknown) {
|
||||
this.value = value;
|
||||
this.isDynamic = typeof value === 'string' && regExp.test(value);
|
||||
}
|
||||
}
|
89
packages/editor/src/operations/AppModel/IAppModel.ts
Normal file
89
packages/editor/src/operations/AppModel/IAppModel.ts
Normal file
@ -0,0 +1,89 @@
|
||||
import { ApplicationComponent } from "@sunmao-ui/core";
|
||||
|
||||
export type ComponentId = string & {
|
||||
kind: 'componentId';
|
||||
};
|
||||
export type ComponentType = string & {
|
||||
kind: 'componentType';
|
||||
};
|
||||
export type ModuleId = string & {
|
||||
kind: 'moduleId';
|
||||
};
|
||||
export type ModuleType = string & {
|
||||
kind: 'moduleType';
|
||||
};
|
||||
export type TraitType = string & {
|
||||
kind: 'traitType';
|
||||
};
|
||||
export type SlotName = string & {
|
||||
kind: 'slotName';
|
||||
};
|
||||
export type MethodName = string & {
|
||||
kind: 'methodName';
|
||||
};
|
||||
export type StyleSlotName = string & {
|
||||
kind: 'styleSlotName';
|
||||
};
|
||||
export type StateKey = string & {
|
||||
kind: 'stateKey';
|
||||
};
|
||||
export type EventName = string & {
|
||||
kind: 'eventName';
|
||||
};
|
||||
|
||||
export interface IApplicationModel {
|
||||
components: IComponentModel[];
|
||||
modules: IModuleModel[];
|
||||
allComponents: IComponentModel[];
|
||||
json: ApplicationComponent[];
|
||||
// createComponent: (componentType: ComponentType, componentId: ComponentId, properties: Record<string, string>) => IComponentModel;
|
||||
// createModule: (moduleId: ModuleId, moduleType: ModuleType) => IModuleModel;
|
||||
// removeComponent: (componentId: ComponentId) => void;
|
||||
// removeModule: (moduleId: ModuleId) => void;
|
||||
// findComponent: (componentId: ComponentId) => IComponentModel | undefined;
|
||||
// moveComponent: (fromId: ComponentId, toId: ComponentId, slot: SlotName, afterId: ComponentId) => void;
|
||||
}
|
||||
|
||||
export interface IModuleModel {
|
||||
id: ModuleId;
|
||||
type: ModuleType;
|
||||
property: Record<string, IFieldModel>;
|
||||
}
|
||||
|
||||
export interface IComponentModel {
|
||||
id: ComponentId;
|
||||
get json (): ApplicationComponent;
|
||||
type: ComponentType;
|
||||
properties: Record<string, IFieldModel>;
|
||||
children: Record<SlotName, IComponentModel[]>;
|
||||
parent: IComponentModel | null;
|
||||
parentId: ComponentId | null;
|
||||
parentSlot: SlotName | null;
|
||||
traits: ITraitModel[];
|
||||
stateKeys: StateKey[];
|
||||
slots: SlotName[];
|
||||
styleSlots: StyleSlotName[];
|
||||
methods: MethodName[];
|
||||
events: EventName[];
|
||||
|
||||
// addTrait: (traitType: TraitType, properties: Record<string, string>) => ITraitModel;
|
||||
// removeTrait: (traitType: TraitType) => void;
|
||||
// modifyProperty: (propertyName: string, value: any) => void;
|
||||
// modifyId: (newId: ComponentId) => void;
|
||||
}
|
||||
|
||||
export interface ITraitModel {
|
||||
parent: IComponentModel;
|
||||
type: TraitType;
|
||||
properties: Record<string, any>;
|
||||
propertiesMedatadata: Record<string, IFieldModel>;
|
||||
methods: MethodName[];
|
||||
stateKeys: StateKey[];
|
||||
}
|
||||
|
||||
export interface IFieldModel {
|
||||
value: any;
|
||||
isDynamic: boolean;
|
||||
// used components' id in the expression
|
||||
// refs: Array<ComponentId | ModuleId>;
|
||||
}
|
49
packages/editor/src/operations/AppModel/TraitModel.ts
Normal file
49
packages/editor/src/operations/AppModel/TraitModel.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import {
|
||||
ComponentTrait,
|
||||
RuntimeTraitSpec,
|
||||
} from '@sunmao-ui/core';
|
||||
import { registry } from '../../setup';
|
||||
import {
|
||||
IComponentModel,
|
||||
MethodName,
|
||||
TraitType,
|
||||
ITraitModel,
|
||||
IFieldModel,
|
||||
StateKey,
|
||||
} from './IAppModel';
|
||||
import { FieldModel } from './FieldModel';
|
||||
|
||||
export class TraitModel implements ITraitModel {
|
||||
private origin: ComponentTrait;
|
||||
private spec: RuntimeTraitSpec;
|
||||
|
||||
type: TraitType;
|
||||
properties: Record<string, any>;
|
||||
propertiesMedatadata: Record<string, IFieldModel> = {};
|
||||
parent: IComponentModel;
|
||||
|
||||
constructor(trait: ComponentTrait, parent: IComponentModel) {
|
||||
this.origin = trait;
|
||||
this.parent = parent;
|
||||
this.type = trait.type as TraitType;
|
||||
this.spec = registry.getTraitByType(this.type);
|
||||
|
||||
this.properties = trait.properties || {};
|
||||
for (const key in trait.properties) {
|
||||
this.propertiesMedatadata[key] = new FieldModel(trait.properties[key]);
|
||||
}
|
||||
this.propertiesMedatadata;
|
||||
}
|
||||
|
||||
get json(): ComponentTrait {
|
||||
return this.origin;
|
||||
}
|
||||
|
||||
get methods() {
|
||||
return (this.spec ? this.spec.spec.methods.map(m => m.name) : []) as MethodName[];
|
||||
}
|
||||
|
||||
get stateKeys() {
|
||||
return (this.spec ? Object.keys(this.spec.spec.state) : []) as StateKey[];
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import { ApplicationComponent } from '@sunmao-ui/core';
|
||||
import { eventBus } from '../eventBus';
|
||||
import { ApplicationModel } from './AppModel/AppModel';
|
||||
import { IUndoRedoManager, IOperation, OperationList } from './type';
|
||||
|
||||
export class AppModelManager implements IUndoRedoManager {
|
||||
@ -19,6 +20,8 @@ export class AppModelManager implements IUndoRedoManager {
|
||||
updateComponents(components: ApplicationComponent[]) {
|
||||
this.components = components;
|
||||
eventBus.send('componentsChange', this.components);
|
||||
(window as any).app = new ApplicationModel(this.components)
|
||||
console.log((window as any).app)
|
||||
}
|
||||
|
||||
do(operation: IOperation): void {
|
||||
|
Loading…
Reference in New Issue
Block a user