use function to generate component to avoid misunderstand

This commit is contained in:
Sczlog 2021-12-01 11:41:16 +08:00
parent 6fba9b81a0
commit 61c96bc77a
9 changed files with 214 additions and 131 deletions

View File

@ -11,11 +11,7 @@ import { GeneralTraitFormList } from './GeneralTraitFormList';
import { FetchTraitForm } from './FetchTraitForm';
import { Registry } from '@sunmao-ui/runtime/lib/services/registry';
import SchemaField from './JsonSchemaForm/SchemaField';
import {
ModifyComponentPropertiesLeafOperation,
ModifyTraitPropertiesLeafOperation,
} from '../../operations/leaf';
import { ModifyComponentIdBranchOperation } from '../../operations/branch';
import { genOperation } from 'src/operations';
type Props = {
registry: Registry;
@ -36,14 +32,14 @@ export const renderField = (properties: {
const ref = React.createRef<HTMLTextAreaElement>();
const onBlur = () => {
const operation = type
? new ModifyTraitPropertiesLeafOperation({
? genOperation('modifyTraitProperty', {
componentId: selectedId,
traitIndex: index,
properties: {
[fullKey]: ref.current?.value,
},
})
: new ModifyComponentPropertiesLeafOperation({
: genOperation('modifyComponentProperty', {
componentId: selectedId,
properties: {
[fullKey]: ref.current?.value,
@ -96,7 +92,10 @@ export const ComponentForm: React.FC<Props> = props => {
const changeComponentId = (selectedId: string, value: string) => {
eventBus.send(
'operation',
new ModifyComponentIdBranchOperation({ componentId: selectedId, newId: value })
genOperation('modifyComponentId', {
componentId: selectedId,
newId: value,
})
);
};
@ -132,7 +131,7 @@ export const ComponentForm: React.FC<Props> = props => {
onChange={newFormData => {
eventBus.send(
'operation',
new ModifyComponentPropertiesLeafOperation({
genOperation('modifyComponentProperty', {
componentId: selectedId,
properties: newFormData,
})

View File

@ -8,10 +8,7 @@ import { EventHandlerSchema } from '@sunmao-ui/runtime';
import { eventBus } from '../../../eventBus';
import { EventHandlerForm } from './EventHandlerForm';
import { Registry } from '@sunmao-ui/runtime/lib/services/registry';
import {
CreateTraitLeafOperation,
ModifyTraitPropertiesLeafOperation,
} from '../../../operations/leaf';
import { genOperation } from 'src/operations';
type EventHandler = Static<typeof EventHandlerSchema>;
@ -51,7 +48,7 @@ export const EventTraitForm: React.FC<Props> = props => {
if (!handlers) {
eventBus.send(
'operation',
new CreateTraitLeafOperation({
genOperation('createTrait', {
componentId: component.id,
traitType: 'core/v1/event',
properties: { handlers: [newHandler] },
@ -62,7 +59,7 @@ export const EventTraitForm: React.FC<Props> = props => {
const index = component.traits.findIndex(t => t.type === 'core/v1/event');
eventBus.send(
'operation',
new ModifyTraitPropertiesLeafOperation({
genOperation('modifyTraitProperty', {
componentId: component.id,
traitIndex: index,
properties: [...handlers, newHandler],
@ -80,7 +77,7 @@ export const EventTraitForm: React.FC<Props> = props => {
});
eventBus.send(
'operation',
new ModifyTraitPropertiesLeafOperation({
genOperation('modifyTraitProperty', {
componentId: component.id,
traitIndex: index,
properties: {
@ -97,7 +94,7 @@ export const EventTraitForm: React.FC<Props> = props => {
});
eventBus.send(
'operation',
new ModifyTraitPropertiesLeafOperation({
genOperation('modifyTraitProperty', {
componentId: component.id,
traitIndex: index,
properties: {

View File

@ -19,10 +19,7 @@ import { KeyValueEditor } from '../../KeyValueEditor';
import { EventHandlerForm } from '../EventTraitForm/EventHandlerForm';
import { eventBus } from '../../../eventBus';
import { Registry } from '@sunmao-ui/runtime/lib/services/registry';
import {
ModifyTraitPropertiesLeafOperation,
RemoveTraitLeafOperation,
} from '../../../operations/leaf';
import { genOperation } from 'src/operations';
type EventHandler = Static<typeof EventHandlerSchema>;
@ -49,7 +46,7 @@ export const FetchTraitForm: React.FC<Props> = props => {
const index = component.traits.findIndex(t => t.type === 'core/v1/fetch');
eventBus.send(
'operation',
new ModifyTraitPropertiesLeafOperation({
genOperation('modifyTraitProperty', {
componentId: component.id,
traitIndex: index,
properties: values,
@ -201,7 +198,10 @@ export const FetchTraitForm: React.FC<Props> = props => {
const index = component.traits.findIndex(t => t.type === 'core/v1/fetch');
eventBus.send(
'operation',
new RemoveTraitLeafOperation({ componentId: component.id, index })
genOperation('removeTrait', {
componentId: component.id,
index,
})
);
}}
/>

View File

@ -7,10 +7,7 @@ import { GeneralTraitForm } from './GeneralTraitForm';
import { eventBus } from '../../../eventBus';
import { ignoreTraitsList } from '../../../constants';
import { Registry } from '@sunmao-ui/runtime/lib/services/registry';
import {
CreateTraitLeafOperation,
RemoveTraitLeafOperation,
} from '../../../operations/leaf';
import { genOperation } from 'src/operations';
type Props = {
registry: Registry;
@ -25,7 +22,7 @@ export const GeneralTraitFormList: React.FC<Props> = props => {
const initProperties = parseTypeBox(traitSpec.properties as TSchema);
eventBus.send(
'operation',
new CreateTraitLeafOperation({
genOperation('createTrait', {
componentId: component.id,
traitType: type,
properties: initProperties,
@ -34,21 +31,24 @@ export const GeneralTraitFormList: React.FC<Props> = props => {
};
const traitFields = component.traits
.filter(t => {
return !ignoreTraitsList.includes(t.type);
.filter(trait => {
return !ignoreTraitsList.includes(trait.type);
})
.map((t, i) => {
.map((trait, index) => {
const onRemoveTrait = () => {
eventBus.send(
'operation',
new RemoveTraitLeafOperation({ componentId: component.id, index: i })
genOperation('removeTrait', {
componentId: component.id,
index,
})
);
};
return (
<GeneralTraitForm
key={i}
key={index}
component={component}
trait={t}
trait={trait}
onRemove={onRemoveTrait}
registry={registry}
/>

View File

@ -13,12 +13,8 @@ import { KeyboardEventWrapper } from './KeyboardEventWrapper';
import { ComponentWrapper } from './ComponentWrapper';
import { StateEditor, SchemaEditor } from './CodeEditor';
import { Explorer } from './Explorer';
import {
ModifyComponentPropertiesLeafOperation,
ReplaceAppLeafOperation,
} from '../operations/leaf';
import { CreateComponentBranchOperation } from '../operations/branch';
import { editorStore } from '../EditorStore';
import { genOperation } from 'src/operations';
type ReturnOfInit = ReturnType<typeof initSunmaoUI>;
@ -26,7 +22,6 @@ type Props = {
App: ReturnOfInit['App'];
registry: ReturnOfInit['registry'];
stateStore: ReturnOfInit['stateManager']['store'];
apiService: ReturnOfInit['apiService'];
};
export const Editor: React.FC<Props> = observer(
@ -38,46 +33,46 @@ export const Editor: React.FC<Props> = observer(
const [codeMode, setCodeMode] = useState(false);
const [code, setCode] = useState('');
const gridCallbacks: GridCallbacks = useMemo(() => {
return {
// drag an existing component
onDragStop(id, layout) {
eventBus.send(
'operation',
new ModifyComponentPropertiesLeafOperation({
componentId: id,
properties: { layout },
})
);
},
// drag a new component from tool box
onDrop(id, layout, _, e) {
const component = e.dataTransfer?.getData('component') || '';
eventBus.send(
'operation',
new CreateComponentBranchOperation({
componentType: component,
parentId: id,
slot: 'content',
layout,
})
);
},
};
}, []);
const gridCallbacks: GridCallbacks = useMemo(() => {
return {
// drag an existing component
onDragStop(id, layout) {
eventBus.send(
'operation',
genOperation('modifyComponentProperty', {
componentId: id,
properties: { layout },
})
);
},
// drag a new component from tool box
onDrop(id, layout, _, e) {
const component = e.dataTransfer?.getData('component') || '';
eventBus.send(
'operation',
genOperation('createComponent', {
componentType: component,
parentId: id,
slot: 'content',
layout,
})
);
},
};
}, []);
const app = useMemo<Application>(() => {
return {
version: 'sunmao/v1',
kind: 'Application',
metadata: {
name: 'some App',
},
spec: {
components,
},
};
}, [components]);
const app = useMemo<Application>(() => {
return {
version: 'sunmao/v1',
kind: 'Application',
metadata: {
name: 'some App',
},
spec: {
components,
},
};
}, [components]);
const appComponent = useMemo(() => {
return (
@ -189,37 +184,41 @@ export const Editor: React.FC<Props> = observer(
);
};
return (
<KeyboardEventWrapper selectedComponentId={selectedComponentId}>
<Box display="flex" height="100%" width="100%" flexDirection="column">
<EditorHeader
scale={scale}
setScale={setScale}
onPreview={() => setPreview(true)}
codeMode={codeMode}
onCodeMode={v => {
setCodeMode(v);
if (!v && code) {
eventBus.send('operation', new ReplaceAppLeafOperation(JSON.parse(code)));
}
}}
/>
<Box display="flex" flex="1" overflow="auto">
{renderMain()}
</Box>
return (
<KeyboardEventWrapper selectedComponentId={selectedComponentId}>
<Box display="flex" height="100%" width="100%" flexDirection="column">
<EditorHeader
scale={scale}
setScale={setScale}
onPreview={() => setPreview(true)}
codeMode={codeMode}
onCodeMode={v => {
setCodeMode(v);
if (!v && code) {
eventBus.send(
'operation',
genOperation('replaceApp', {
app: JSON.parse(code),
})
);
}
}}
/>
<Box display="flex" flex="1" overflow="auto">
{renderMain()}
</Box>
{preview && (
<PreviewModal onClose={() => setPreview(false)}>
<Box width="100%" height="100%">
<App
options={JSON.parse(JSON.stringify(app))}
debugEvent={false}
debugStore={false}
/>
</Box>
</PreviewModal>
)}
</KeyboardEventWrapper>
);
}
);
</Box>
{preview && (
<PreviewModal onClose={() => setPreview(false)}>
<Box width="100%" height="100%">
<App
options={JSON.parse(JSON.stringify(app))}
debugEvent={false}
debugStore={false}
/>
</Box>
</PreviewModal>
)}
</KeyboardEventWrapper>
);
});

View File

@ -1,7 +1,7 @@
import { css } from '@emotion/react';
import React from 'react';
import { RemoveComponentBranchOperation } from '../operations/branch';
import { eventBus } from '../eventBus';
import { genOperation } from 'src/operations';
type Props = {
selectedComponentId: string;
@ -25,7 +25,9 @@ export const KeyboardEventWrapper: React.FC<Props> = props => {
case 'Backspace':
eventBus.send(
'operation',
new RemoveComponentBranchOperation({ componentId: props.selectedComponentId })
genOperation('removeComponent', {
componentId: props.selectedComponentId,
})
);
break;
case 'z':

View File

@ -2,15 +2,11 @@ import { Box, Text, VStack } from '@chakra-ui/react';
import { ApplicationComponent } from '@sunmao-ui/core';
import { Registry } from '@sunmao-ui/runtime/lib/services/registry';
import React, { useMemo, useState } from 'react';
import {
RemoveComponentBranchOperation,
CreateComponentBranchOperation,
} from '../../operations/branch';
import { AdjustComponentOrderLeafOperation } from '../../operations/leaf';
import { eventBus } from '../../eventBus';
import { ComponentItemView } from './ComponentItemView';
import { DropComponentWrapper } from './DropComponentWrapper';
import { ChildrenMap } from './StructureTree';
import { genOperation } from 'src/operations';
type Props = {
registry: Registry;
@ -57,7 +53,7 @@ export const ComponentTree: React.FC<Props> = props => {
const onDrop = (creatingComponent: string) => {
eventBus.send(
'operation',
new CreateComponentBranchOperation({
genOperation('createComponent', {
componentType: creatingComponent,
parentId: component.id,
slot,
@ -88,7 +84,9 @@ export const ComponentTree: React.FC<Props> = props => {
const onClickRemove = () => {
eventBus.send(
'operation',
new RemoveComponentBranchOperation({ componentId: component.id })
genOperation('removeComponent', {
componentId: component.id,
})
);
};
@ -96,10 +94,10 @@ export const ComponentTree: React.FC<Props> = props => {
if (slots.length === 0) return;
eventBus.send(
'operation',
new CreateComponentBranchOperation({
genOperation('createComponent', {
componentType: creatingComponent,
parentId: component.id,
slot: 'content',
slot: slots[0],
})
);
};
@ -107,7 +105,7 @@ export const ComponentTree: React.FC<Props> = props => {
const onMoveUp = () => {
eventBus.send(
'operation',
new AdjustComponentOrderLeafOperation({
genOperation('adjustComponentOrder', {
componentId: component.id,
orientation: 'up',
})
@ -117,7 +115,7 @@ export const ComponentTree: React.FC<Props> = props => {
const onMoveDown = () => {
eventBus.send(
'operation',
new AdjustComponentOrderLeafOperation({
genOperation('adjustComponentOrder', {
componentId: component.id,
orientation: 'down',
})

View File

@ -6,10 +6,7 @@ import { ComponentItemView } from './ComponentItemView';
import { ComponentTree } from './ComponentTree';
import { DropComponentWrapper } from './DropComponentWrapper';
import { Registry } from '@sunmao-ui/runtime/lib/services/registry';
import {
RemoveComponentBranchOperation,
CreateComponentBranchOperation,
} from '../../operations/branch';
import { genOperation as genOperation } from 'src/operations';
export type ChildrenMap = Map<string, SlotsMap>;
type SlotsMap = Map<string, ApplicationComponent[]>;
@ -62,7 +59,7 @@ export const StructureTree: React.FC<Props> = props => {
const onClickRemove = () => {
eventBus.send(
'operation',
new RemoveComponentBranchOperation({
genOperation('removeComponent', {
componentId: dummy.id,
})
);
@ -101,7 +98,7 @@ function RootItem() {
const onDrop = (creatingComponent: string) => {
eventBus.send(
'operation',
new CreateComponentBranchOperation({
genOperation('createComponent', {
componentType: creatingComponent,
})
);

View File

@ -0,0 +1,91 @@
import {
CreateComponentBranchOperation,
CreateComponentBranchOperationContext,
ModifyComponentIdBranchOperation,
ModifyComponentIdBranchOperationContext,
RemoveComponentBranchOperation,
RemoveComponentBranchOperationContext,
} from './branch';
import {
AdjustComponentOrderLeafOperation,
AdjustComponentOrderLeafOperationContext,
CreateTraitLeafOperation,
CreateTraitLeafOperationContext,
ModifyComponentPropertiesLeafOperation,
ModifyComponentPropertiesLeafOperationContext,
ModifyTraitPropertiesLeafOperation,
ModifyTraitPropertiesLeafOperationContext,
RemoveTraitLeafOperation,
RemoveTraitLeafOperationContext,
ReplaceAppLeafOperation,
ReplaceAppLeafOperationContext,
} from './leaf';
import { IOperation } from './type';
const OperationConstructors: Record<
OperationTypes,
OperationConfigMaps[OperationTypes]['constructor']
> = {
createComponent: CreateComponentBranchOperation,
removeComponent: RemoveComponentBranchOperation,
modifyComponentProperty: ModifyComponentPropertiesLeafOperation,
modifyComponentId: ModifyComponentIdBranchOperation,
adjustComponentOrder: AdjustComponentOrderLeafOperation,
createTrait: CreateTraitLeafOperation,
removeTrait: RemoveTraitLeafOperation,
modifyTraitProperty: ModifyTraitPropertiesLeafOperation,
replaceApp: ReplaceAppLeafOperation,
};
type OperationTypes = keyof OperationConfigMaps;
type OperationConfigMap<TOperation, TContext> = {
constructor: new (context: TContext) => TOperation;
context: TContext;
};
type OperationConfigMaps = {
createComponent: OperationConfigMap<
CreateComponentBranchOperation,
CreateComponentBranchOperationContext
>;
removeComponent: OperationConfigMap<
RemoveComponentBranchOperation,
RemoveComponentBranchOperationContext
>;
modifyComponentProperty: OperationConfigMap<
ModifyComponentPropertiesLeafOperation,
ModifyComponentPropertiesLeafOperationContext
>;
modifyComponentId: OperationConfigMap<
ModifyComponentIdBranchOperation,
ModifyComponentIdBranchOperationContext
>;
adjustComponentOrder: OperationConfigMap<
AdjustComponentOrderLeafOperation,
AdjustComponentOrderLeafOperationContext
>;
createTrait: OperationConfigMap<
CreateTraitLeafOperation,
CreateTraitLeafOperationContext
>;
removeTrait: OperationConfigMap<
RemoveTraitLeafOperation,
RemoveTraitLeafOperationContext
>;
modifyTraitProperty: OperationConfigMap<
ModifyTraitPropertiesLeafOperation,
ModifyTraitPropertiesLeafOperationContext
>;
replaceApp: OperationConfigMap<ReplaceAppLeafOperation, ReplaceAppLeafOperationContext>;
};
export const genOperation = <T extends OperationTypes>(
type: T,
context: OperationConfigMaps[T]['context']
): IOperation => {
const OperationConstructor = OperationConstructors[
type
] as OperationConfigMaps[T]['constructor'];
return new OperationConstructor(context as any);
};