mirror of
https://github.com/smartxworks/sunmao-ui.git
synced 2025-04-12 21:50:23 +08:00
feat(DataSource): support create component datasource
This commit is contained in:
parent
9418334d9e
commit
84b11f115a
@ -39,7 +39,7 @@ export function createTrait(options: CreateTraitOptions): RuntimeTrait {
|
||||
kind: 'Trait' as any,
|
||||
parsedVersion: parseVersion(options.version),
|
||||
metadata: {
|
||||
name: options.metadata.name,
|
||||
...options.metadata,
|
||||
description: options.metadata.description || '',
|
||||
annotations: options.metadata.annotations || {},
|
||||
},
|
||||
|
@ -22,7 +22,7 @@ declare module '../../types/widget' {
|
||||
|
||||
export const FetchWidget: React.FC<WidgetProps<FetchWidgetType>> = props => {
|
||||
const { value, onChange, component, services } = props;
|
||||
const [isOpen, setIsOpen] = useState(true);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
return (
|
||||
<Box>
|
||||
<Button onClick={() => setIsOpen(true)}>Edit In Modal</Button>
|
||||
|
@ -1,25 +1,22 @@
|
||||
import React, { useState, useMemo, useEffect } from 'react';
|
||||
import React from 'react';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import {
|
||||
Box,
|
||||
Text,
|
||||
Input,
|
||||
AccordionItem,
|
||||
AccordionButton,
|
||||
AccordionIcon,
|
||||
AccordionPanel,
|
||||
Tag,
|
||||
HStack,
|
||||
} from '@chakra-ui/react';
|
||||
import { EditorServices } from '../../types';
|
||||
import { ComponentSchema } from '@sunmao-ui/core';
|
||||
import { watch } from '@sunmao-ui/runtime';
|
||||
import { ComponentNode } from '../StructureTree/ComponentNode';
|
||||
|
||||
interface Props {
|
||||
datas: ComponentSchema[];
|
||||
dataSources: ComponentSchema[];
|
||||
title: string;
|
||||
filterPlaceholder: string;
|
||||
emptyPlaceholder: string;
|
||||
services: EditorServices;
|
||||
type: string;
|
||||
}
|
||||
|
||||
const COLOR_MAP = {
|
||||
@ -37,51 +34,37 @@ const STATE_MAP: Record<string, string> = {
|
||||
object: 'Object',
|
||||
};
|
||||
|
||||
export const DataSourceNode: React.FC<Props> = props => {
|
||||
const { datas = [], filterPlaceholder, emptyPlaceholder, title, services } = props;
|
||||
export const DataSourceGroup: React.FC<Props> = props => {
|
||||
const { dataSources = [], title, services, type } = props;
|
||||
const { stateManager, editorStore } = services;
|
||||
const { store } = stateManager;
|
||||
const [search, setSearch] = useState('');
|
||||
const [reactiveStore, setReactiveStore] = useState<Record<string, any>>({ ...store });
|
||||
const list = useMemo(
|
||||
() => datas.filter(({ id }) => id.includes(search)),
|
||||
[search, datas]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const stop = watch(store, newValue => {
|
||||
setReactiveStore({ ...newValue });
|
||||
});
|
||||
|
||||
return stop;
|
||||
}, [store]);
|
||||
|
||||
const StateItems = () => (
|
||||
<>
|
||||
{list.map(state => {
|
||||
{dataSources.map(dataSource => {
|
||||
let tag = '';
|
||||
|
||||
const trait = state.traits.find(({ type }) => type === `core/v1/fetch`);
|
||||
const trait = dataSource.traits.find(({ type }) => type === `core/v1/fetch`);
|
||||
if (trait?.properties) {
|
||||
tag = (trait.properties.method as string).toUpperCase();
|
||||
tag = ((trait.properties.config as any).method as string).toUpperCase();
|
||||
} else {
|
||||
tag = Array.isArray(reactiveStore[state.id]?.value)
|
||||
tag = Array.isArray(store[dataSource.id]?.value)
|
||||
? 'Array'
|
||||
: STATE_MAP[typeof reactiveStore[state.id]?.value] ?? 'Any';
|
||||
: STATE_MAP[typeof store[dataSource.id]?.value] ?? 'Any';
|
||||
}
|
||||
|
||||
return (
|
||||
<ComponentNode
|
||||
id={state.id}
|
||||
key={state.id}
|
||||
component={state}
|
||||
id={dataSource.id}
|
||||
key={dataSource.id}
|
||||
component={dataSource}
|
||||
parentId={null}
|
||||
slot={null}
|
||||
onSelectComponent={editorStore.setSelectedComponentId}
|
||||
services={services}
|
||||
droppable={false}
|
||||
depth={0}
|
||||
isSelected={editorStore.selectedComponent?.id === state.id}
|
||||
isSelected={editorStore.selectedComponent?.id === dataSource.id}
|
||||
isExpanded={false}
|
||||
onToggleExpand={() => undefined}
|
||||
shouldShowSelfSlotName={false}
|
||||
@ -108,23 +91,15 @@ export const DataSourceNode: React.FC<Props> = props => {
|
||||
|
||||
return (
|
||||
<AccordionItem>
|
||||
<h2>
|
||||
<AccordionButton borderBottom="solid" borderColor="inherit">
|
||||
<Box flex="1" textAlign="left">
|
||||
{title}
|
||||
</Box>
|
||||
<AccordionIcon />
|
||||
</AccordionButton>
|
||||
</h2>
|
||||
<AccordionPanel pb="4" padding="0">
|
||||
<Input
|
||||
placeholder={filterPlaceholder}
|
||||
value={search}
|
||||
onChange={e => {
|
||||
setSearch(e.target.value);
|
||||
}}
|
||||
/>
|
||||
{list.length ? <StateItems /> : <Text padding="2">{emptyPlaceholder}</Text>}
|
||||
<AccordionButton justifyContent="space-between">
|
||||
<HStack>
|
||||
{type === 'component' ? <Tag colorScheme="blue">C</Tag> : undefined}
|
||||
<Text fontWeight="bold">{title}</Text>
|
||||
</HStack>
|
||||
<AccordionIcon />
|
||||
</AccordionButton>
|
||||
<AccordionPanel padding="0">
|
||||
{dataSources.length ? <StateItems /> : <Text padding="2">Empty</Text>}
|
||||
</AccordionPanel>
|
||||
</AccordionItem>
|
||||
);
|
@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import {
|
||||
VStack,
|
||||
Flex,
|
||||
@ -10,65 +10,114 @@ import {
|
||||
MenuList,
|
||||
IconButton,
|
||||
Accordion,
|
||||
MenuGroup,
|
||||
} from '@chakra-ui/react';
|
||||
import { AddIcon, ChevronDownIcon } from '@chakra-ui/icons';
|
||||
import { DataSourceNode } from './DataSourceNode';
|
||||
import { DataSourceGroup } from './DataSourceGroup';
|
||||
import { EditorServices } from '../../types';
|
||||
import { DataSourceType } from '../../constants/dataSource';
|
||||
import { groupBy } from 'lodash';
|
||||
import { genOperation } from '../../operations';
|
||||
import { generateDefaultValueFromSpec } from '@sunmao-ui/shared';
|
||||
import { JSONSchema7 } from 'json-schema';
|
||||
import { ToolMenuTabs } from '../../constants/enum';
|
||||
|
||||
interface Props {
|
||||
active: string;
|
||||
services: EditorServices;
|
||||
}
|
||||
|
||||
const DATASOURCE_TYPES = Object.values(DataSourceType);
|
||||
|
||||
export const DataSourceList: React.FC<Props> = props => {
|
||||
const { services } = props;
|
||||
const { editorStore } = services;
|
||||
const group = groupBy(editorStore.dataSources, c => c.traits[0]?.type);
|
||||
// const NORMAL_DATASOURCES = DATA_DATASOURCES.map(item => ({
|
||||
// ...item,
|
||||
// title: item.type,
|
||||
// datas: editorStore.dataSources[item.type],
|
||||
// }));
|
||||
const NORMAL_DATASOURCES = Object.keys(group).map(type => {
|
||||
const { editorStore, eventBus, registry } = services;
|
||||
const { dataSources, setSelectedComponentId, setToolMenuTab } = editorStore;
|
||||
const tDataSources = dataSources.filter(ds => ds.type === 'core/v1/dummy');
|
||||
const cDataSources = dataSources.filter(ds => ds.type !== 'core/v1/dummy');
|
||||
const cdsMap = groupBy(cDataSources, c => c.type);
|
||||
const tdsMap = groupBy(tDataSources, c => c.traits[0]?.type);
|
||||
const cdsGroups = Object.keys(cdsMap).map(type => {
|
||||
return {
|
||||
title: type,
|
||||
datas: group[type],
|
||||
dataSources: cdsMap[type],
|
||||
type: 'component',
|
||||
};
|
||||
});
|
||||
const onMenuItemClick = (type: DataSourceType) => {
|
||||
editorStore.createDataSource(
|
||||
type,
|
||||
type === DataSourceType.API ? {} : { key: 'value' }
|
||||
);
|
||||
editorStore.setSelectedComponentId('');
|
||||
};
|
||||
// const onApiItemClick = (api: ComponentSchema) => {
|
||||
// editorStore.setActiveDataSourceId(api.id);
|
||||
// editorStore.setSelectedComponentId(api.id);
|
||||
// };
|
||||
// const onDataSourceItemClick = (dataSource: ComponentSchema) => {
|
||||
// editorStore.setActiveDataSourceId(dataSource.id);
|
||||
// editorStore.setToolMenuTab(ToolMenuTabs.INSPECT);
|
||||
// editorStore.setSelectedComponentId(dataSource.id);
|
||||
// };
|
||||
// const onApiItemRemove = (api: ComponentSchema) => {
|
||||
// editorStore.removeDataSource(api);
|
||||
// };
|
||||
// const onStateItemRemove = (state: ComponentSchema) => {
|
||||
// editorStore.removeDataSource(state);
|
||||
// };
|
||||
const MenuItems = () => (
|
||||
<>
|
||||
{DATASOURCE_TYPES.map(type => (
|
||||
<MenuItem key={type} onClick={() => onMenuItemClick(type)}>
|
||||
{type}
|
||||
</MenuItem>
|
||||
))}
|
||||
</>
|
||||
const tdsGroups = Object.keys(tdsMap).map(type => {
|
||||
return {
|
||||
title: type,
|
||||
dataSources: tdsMap[type],
|
||||
type: 'trait',
|
||||
};
|
||||
});
|
||||
|
||||
const dsGroups = cdsGroups.concat(tdsGroups);
|
||||
|
||||
// cdsTypes: component data source types
|
||||
// tdsTypes: trait data source types
|
||||
const { cdsTypes, tdsTypes } = useMemo(() => {
|
||||
const cdsTypes = registry
|
||||
.getAllComponents()
|
||||
.filter(c => c.metadata.isDataSource && c.metadata.name !== 'dummy')
|
||||
.map(c => `${c.version}/${c.metadata.name}`);
|
||||
const tdsTypes = registry
|
||||
.getAllTraits()
|
||||
.filter(t => t.metadata.isDataSource)
|
||||
.map(t => `${t.version}/${t.metadata.name}`);
|
||||
return { cdsTypes, tdsTypes };
|
||||
}, [registry]);
|
||||
|
||||
const getNewId = useCallback(
|
||||
(name: string): string => {
|
||||
let count = dataSources.length;
|
||||
let id = `${name}${count}`;
|
||||
const ids = dataSources.map(({ id }) => id);
|
||||
|
||||
while (ids.includes(id)) {
|
||||
id = `${name}${++count}`;
|
||||
}
|
||||
|
||||
return `${name}${count}`;
|
||||
},
|
||||
[dataSources]
|
||||
);
|
||||
const onCreateDSFromComponent = useCallback(
|
||||
(type: string) => {
|
||||
const name = type.split('/')[2];
|
||||
const id = getNewId(name);
|
||||
|
||||
eventBus.send(
|
||||
'operation',
|
||||
genOperation(registry, 'createComponent', {
|
||||
componentType: type,
|
||||
componentId: id,
|
||||
})
|
||||
);
|
||||
|
||||
setSelectedComponentId(id);
|
||||
setToolMenuTab(ToolMenuTabs.INSPECT);
|
||||
},
|
||||
[eventBus, getNewId, registry, setSelectedComponentId, setToolMenuTab]
|
||||
);
|
||||
const onCreateDSFromTrait = useCallback(
|
||||
(type: string) => {
|
||||
const propertiesSpec = registry.getTraitByType(type).spec.properties;
|
||||
const defaultProperties = generateDefaultValueFromSpec(propertiesSpec, {
|
||||
genArrayItemDefaults: true,
|
||||
});
|
||||
const name = type.split('/')[2];
|
||||
const id = getNewId(name);
|
||||
|
||||
eventBus.send(
|
||||
'operation',
|
||||
genOperation(registry, 'createDataSource', {
|
||||
id,
|
||||
type,
|
||||
defaultProperties: defaultProperties as JSONSchema7,
|
||||
})
|
||||
);
|
||||
|
||||
setSelectedComponentId(id);
|
||||
setToolMenuTab(ToolMenuTabs.INSPECT);
|
||||
},
|
||||
[eventBus, getNewId, registry, setSelectedComponentId, setToolMenuTab]
|
||||
);
|
||||
|
||||
return (
|
||||
@ -89,22 +138,36 @@ export const DataSourceList: React.FC<Props> = props => {
|
||||
rightIcon={<ChevronDownIcon />}
|
||||
/>
|
||||
<MenuList>
|
||||
<MenuItems />
|
||||
{cdsTypes.length ? (
|
||||
<MenuGroup title="From Component">
|
||||
{cdsTypes.map(type => (
|
||||
<MenuItem key={type} onClick={() => onCreateDSFromComponent(type)}>
|
||||
{type}
|
||||
</MenuItem>
|
||||
))}
|
||||
</MenuGroup>
|
||||
) : undefined}
|
||||
<MenuGroup title="From Trait">
|
||||
{tdsTypes.map(type => (
|
||||
<MenuItem key={type} onClick={() => onCreateDSFromTrait(type)}>
|
||||
{type}
|
||||
</MenuItem>
|
||||
))}
|
||||
</MenuGroup>
|
||||
</MenuList>
|
||||
</Menu>
|
||||
</Flex>
|
||||
<Accordion
|
||||
reduceMotion
|
||||
defaultIndex={[0].concat(NORMAL_DATASOURCES.map((_, i) => i + 1))}
|
||||
defaultIndex={[0].concat(dsGroups.map((_, i) => i + 1))}
|
||||
allowMultiple
|
||||
>
|
||||
{NORMAL_DATASOURCES.map(dataSourceItem => (
|
||||
<DataSourceNode
|
||||
key={dataSourceItem.title}
|
||||
title={dataSourceItem.title}
|
||||
filterPlaceholder={'filter'}
|
||||
emptyPlaceholder={'Empty'}
|
||||
datas={dataSourceItem.datas}
|
||||
{dsGroups.map(group => (
|
||||
<DataSourceGroup
|
||||
key={group.title}
|
||||
title={group.title}
|
||||
type={group.type}
|
||||
dataSources={group.dataSources}
|
||||
services={services}
|
||||
/>
|
||||
))}
|
||||
|
@ -39,7 +39,6 @@ export const Editor: React.FC<Props> = observer(
|
||||
components,
|
||||
selectedComponentId,
|
||||
modules,
|
||||
activeDataSource,
|
||||
toolMenuTab,
|
||||
explorerMenuTab,
|
||||
setToolMenuTab,
|
||||
@ -158,10 +157,7 @@ export const Editor: React.FC<Props> = observer(
|
||||
<StructureTree services={services} />
|
||||
</TabPanel>
|
||||
<TabPanel height="full" overflow="auto" p={0}>
|
||||
<DataSourceList
|
||||
active={activeDataSource?.id ?? ''}
|
||||
services={services}
|
||||
/>
|
||||
<DataSourceList services={services} />
|
||||
</TabPanel>
|
||||
<TabPanel overflow="auto" p={0} height="100%">
|
||||
<StateViewer store={stateStore} />
|
||||
@ -212,15 +208,6 @@ export const Editor: React.FC<Props> = observer(
|
||||
</Tabs>
|
||||
</Box>
|
||||
</Resizable>
|
||||
{/* {selectedComponent && activeDataSourceType === 'core/v1/fetch' ? (
|
||||
<ApiForm
|
||||
key={selectedComponentId}
|
||||
api={selectedComponent}
|
||||
services={services}
|
||||
store={stateStore}
|
||||
className={ApiFormStyle}
|
||||
/>
|
||||
) : null} */}
|
||||
</Flex>
|
||||
</>
|
||||
);
|
||||
|
@ -1,44 +0,0 @@
|
||||
import { CORE_VERSION, CoreTraitName } from '@sunmao-ui/shared';
|
||||
|
||||
|
||||
export enum DataSourceType {
|
||||
API = 'API',
|
||||
STATE = 'State',
|
||||
LOCALSTORAGE = 'LocalStorage',
|
||||
TRANSFORMER = 'Transformer',
|
||||
}
|
||||
|
||||
export const DATASOURCE_NAME_MAP = {
|
||||
[DataSourceType.API]: 'api',
|
||||
[DataSourceType.STATE]: 'state',
|
||||
[DataSourceType.LOCALSTORAGE]: 'localStorage',
|
||||
[DataSourceType.TRANSFORMER]: 'transformer',
|
||||
};
|
||||
|
||||
export const DATASOURCE_TRAIT_TYPE_MAP = {
|
||||
[DataSourceType.API]: `${CORE_VERSION}/${CoreTraitName.Fetch}`,
|
||||
[DataSourceType.STATE]: `${CORE_VERSION}/${CoreTraitName.State}`,
|
||||
[DataSourceType.LOCALSTORAGE]: `${CORE_VERSION}/${CoreTraitName.LocalStorage}`,
|
||||
[DataSourceType.TRANSFORMER]: `${CORE_VERSION}/${CoreTraitName.Transformer}`,
|
||||
};
|
||||
|
||||
export const DATA_DATASOURCES = [
|
||||
{
|
||||
type: DataSourceType.STATE,
|
||||
traitType: DATASOURCE_TRAIT_TYPE_MAP[DataSourceType.STATE],
|
||||
filterPlaceholder: 'filter the states',
|
||||
emptyPlaceholder: 'No States.',
|
||||
},
|
||||
{
|
||||
type: DataSourceType.LOCALSTORAGE,
|
||||
traitType: DATASOURCE_TRAIT_TYPE_MAP[DataSourceType.LOCALSTORAGE],
|
||||
filterPlaceholder: 'filter the localStorages',
|
||||
emptyPlaceholder: 'No LocalStorages.',
|
||||
},
|
||||
{
|
||||
type: DataSourceType.TRANSFORMER,
|
||||
traitType: DATASOURCE_TRAIT_TYPE_MAP[DataSourceType.TRANSFORMER],
|
||||
filterPlaceholder: 'filter the transformers',
|
||||
emptyPlaceholder: 'No Transformers.',
|
||||
},
|
||||
];
|
@ -7,14 +7,12 @@ export const unremovableTraits = [`${CORE_VERSION}/${CoreTraitName.Slot}`];
|
||||
export const hideCreateTraitsList = [
|
||||
`${CORE_VERSION}/${CoreTraitName.Event}`,
|
||||
`${CORE_VERSION}/${CoreTraitName.Style}`,
|
||||
// `${CORE_VERSION}/${CoreTraitName.Fetch}`,
|
||||
`${CORE_VERSION}/${CoreTraitName.Slot}`,
|
||||
];
|
||||
|
||||
export const hasSpecialFormTraitList = [
|
||||
`${CORE_VERSION}/${CoreTraitName.Event}`,
|
||||
`${CORE_VERSION}/${CoreTraitName.Style}`,
|
||||
// `${CORE_VERSION}/${CoreTraitName.Fetch}`,
|
||||
];
|
||||
|
||||
export const RootId = '__root__';
|
||||
|
@ -2,7 +2,6 @@ import { AppModel } from '../../../AppModel/AppModel';
|
||||
import { BaseBranchOperation } from '../../type';
|
||||
import { CreateComponentBranchOperation } from '../index';
|
||||
import { CreateTraitLeafOperation } from '../../leaf';
|
||||
import { DataSourceType, DATASOURCE_TRAIT_TYPE_MAP } from '../../../constants/dataSource';
|
||||
import {
|
||||
generateDefaultValueFromSpec,
|
||||
CORE_VERSION,
|
||||
@ -12,18 +11,17 @@ import { JSONSchema7Object } from 'json-schema';
|
||||
|
||||
export type CreateDataSourceBranchOperationContext = {
|
||||
id: string;
|
||||
type: DataSourceType;
|
||||
defaultProperties: Record<string, any>;
|
||||
type: string;
|
||||
defaultProperties?: Record<string, any>;
|
||||
};
|
||||
|
||||
export class CreateDataSourceBranchOperation extends BaseBranchOperation<CreateDataSourceBranchOperationContext> {
|
||||
do(prev: AppModel): AppModel {
|
||||
const { id, type, defaultProperties = {} } = this.context;
|
||||
const traitType = DATASOURCE_TRAIT_TYPE_MAP[type];
|
||||
const traitSpec = this.registry.getTraitByType(traitType).spec;
|
||||
const initProperties = generateDefaultValueFromSpec(
|
||||
traitSpec.properties
|
||||
) as JSONSchema7Object;
|
||||
const { id, type, defaultProperties } = this.context;
|
||||
const traitSpec = this.registry.getTraitByType(type).spec;
|
||||
const initProperties = generateDefaultValueFromSpec(traitSpec.properties, {
|
||||
genArrayItemDefaults: true,
|
||||
}) as JSONSchema7Object;
|
||||
|
||||
this.operationStack.insert(
|
||||
new CreateComponentBranchOperation(this.registry, {
|
||||
@ -34,14 +32,8 @@ export class CreateDataSourceBranchOperation extends BaseBranchOperation<CreateD
|
||||
this.operationStack.insert(
|
||||
new CreateTraitLeafOperation(this.registry, {
|
||||
componentId: id,
|
||||
traitType,
|
||||
properties:
|
||||
type === DataSourceType.API
|
||||
? {
|
||||
...initProperties,
|
||||
method: 'get',
|
||||
}
|
||||
: { ...initProperties, ...defaultProperties },
|
||||
traitType: type,
|
||||
properties: defaultProperties || initProperties,
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import { AppModel } from '../../../AppModel/AppModel';
|
||||
import { ComponentId, TraitId, TraitType } from '../../../AppModel/IAppModel';
|
||||
import { BaseLeafOperation } from '../../type';
|
||||
@ -15,11 +14,14 @@ export class CreateTraitLeafOperation extends BaseLeafOperation<CreateTraitLeafO
|
||||
do(prev: AppModel): AppModel {
|
||||
const component = prev.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
return prev
|
||||
return prev;
|
||||
}
|
||||
const trait = component.addTrait(this.context.traitType as TraitType, this.context.properties);
|
||||
const trait = component.addTrait(
|
||||
this.context.traitType as TraitType,
|
||||
this.context.properties
|
||||
);
|
||||
this.traitId = trait.id;
|
||||
return prev
|
||||
return prev;
|
||||
}
|
||||
|
||||
redo(prev: AppModel): AppModel {
|
||||
@ -29,9 +31,9 @@ export class CreateTraitLeafOperation extends BaseLeafOperation<CreateTraitLeafO
|
||||
undo(prev: AppModel): AppModel {
|
||||
const component = prev.getComponentById(this.context.componentId as ComponentId);
|
||||
if (!component) {
|
||||
return prev
|
||||
return prev;
|
||||
}
|
||||
component.removeTrait(this.traitId);
|
||||
return prev
|
||||
return prev;
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,6 @@ import { RegistryInterface, StateManagerInterface } from '@sunmao-ui/runtime';
|
||||
import { EventBusType } from './eventBus';
|
||||
import { AppStorage } from './AppStorage';
|
||||
import type { SchemaValidator, ValidateErrorResult } from '../validator';
|
||||
import { DataSourceType, DATASOURCE_NAME_MAP } from '../constants/dataSource';
|
||||
import { genOperation } from '../operations';
|
||||
import { ExplorerMenuTabs, ToolMenuTabs } from '../constants/enum';
|
||||
|
||||
import { isEqual } from 'lodash';
|
||||
@ -47,9 +45,6 @@ export class EditorStore {
|
||||
lastSavedComponentsVersion = 0;
|
||||
schemaValidator?: SchemaValidator;
|
||||
|
||||
// data source
|
||||
activeDataSourceId: string | null = null;
|
||||
|
||||
private isDataSourceTypeCache: Record<string, boolean> = {};
|
||||
|
||||
constructor(
|
||||
@ -115,7 +110,6 @@ export class EditorStore {
|
||||
() => {
|
||||
if (this.selectedComponentId) {
|
||||
this.setToolMenuTab(ToolMenuTabs.INSPECT);
|
||||
this.setActiveDataSourceId(null);
|
||||
}
|
||||
}
|
||||
);
|
||||
@ -208,18 +202,6 @@ export class EditorStore {
|
||||
});
|
||||
}
|
||||
|
||||
get activeDataSource(): ComponentSchema | null {
|
||||
return (
|
||||
this.components.find(component => component.id === this.activeDataSourceId) || null
|
||||
);
|
||||
}
|
||||
|
||||
get activeDataSourceType(): string | null {
|
||||
if (!this.selectedComponent) return null;
|
||||
const isDataSource = this.isDataSourceTypeCache[this.selectedComponent.type];
|
||||
return isDataSource ? this.selectedComponent.traits[0].type : null;
|
||||
}
|
||||
|
||||
clearSunmaoGlobalState() {
|
||||
this.stateManager.clear();
|
||||
this.setSelectedComponentId('');
|
||||
@ -282,68 +264,10 @@ export class EditorStore {
|
||||
this.lastSavedComponentsVersion = val;
|
||||
};
|
||||
|
||||
setActiveDataSourceId = (dataSourceId: string | null) => {
|
||||
this.activeDataSourceId = dataSourceId;
|
||||
};
|
||||
|
||||
setValidateResult = (validateResult: ValidateErrorResult[]) => {
|
||||
this.validateResult = validateResult;
|
||||
};
|
||||
|
||||
createDataSource = (
|
||||
type: DataSourceType,
|
||||
defaultProperties: Record<string, any> = {}
|
||||
) => {
|
||||
const getCount = (
|
||||
dataSources: ComponentSchema[] = [],
|
||||
dataSourceName = ''
|
||||
): number => {
|
||||
let count = dataSources.length;
|
||||
let id = `${dataSourceName}${count}`;
|
||||
const ids = dataSources.map(({ id }) => id);
|
||||
|
||||
while (ids.includes(id)) {
|
||||
id = `${dataSourceName}${++count}`;
|
||||
}
|
||||
|
||||
return count;
|
||||
};
|
||||
|
||||
const id = `${DATASOURCE_NAME_MAP[type]}${getCount(
|
||||
this.dataSources,
|
||||
DATASOURCE_NAME_MAP[type]
|
||||
)}`;
|
||||
|
||||
this.eventBus.send(
|
||||
'operation',
|
||||
genOperation(this.registry, 'createDataSource', {
|
||||
id,
|
||||
type,
|
||||
defaultProperties,
|
||||
})
|
||||
);
|
||||
|
||||
const component = this.components.find(({ id: componentId }) => id === componentId);
|
||||
|
||||
this.setActiveDataSourceId(component!.id);
|
||||
|
||||
if (type === DataSourceType.STATE || type === DataSourceType.LOCALSTORAGE) {
|
||||
this.setToolMenuTab(ToolMenuTabs.INSPECT);
|
||||
}
|
||||
};
|
||||
|
||||
removeDataSource = (dataSource: ComponentSchema) => {
|
||||
this.eventBus.send(
|
||||
'operation',
|
||||
genOperation(this.registry, 'removeComponent', {
|
||||
componentId: dataSource.id,
|
||||
})
|
||||
);
|
||||
if (this.activeDataSource?.id === dataSource.id) {
|
||||
this.setActiveDataSourceId(null);
|
||||
}
|
||||
};
|
||||
|
||||
setExplorerMenuTab = (val: ExplorerMenuTabs) => {
|
||||
this.explorerMenuTab = val;
|
||||
};
|
||||
|
@ -60,6 +60,7 @@ export default implementRuntimeTrait({
|
||||
metadata: {
|
||||
name: CoreTraitName.Fetch,
|
||||
description: 'fetch data to store',
|
||||
isDataSource: true,
|
||||
},
|
||||
spec: {
|
||||
properties: Type.Object({
|
||||
|
@ -28,6 +28,7 @@ export default implementRuntimeTrait({
|
||||
metadata: {
|
||||
name: CoreTraitName.LocalStorage,
|
||||
description: 'localStorage trait',
|
||||
isDataSource: true,
|
||||
},
|
||||
spec: {
|
||||
properties: LocalStorageTraitPropertiesSpec,
|
||||
|
@ -18,6 +18,7 @@ export default implementRuntimeTrait({
|
||||
metadata: {
|
||||
name: CoreTraitName.State,
|
||||
description: 'add state to component',
|
||||
isDataSource: true,
|
||||
},
|
||||
spec: {
|
||||
properties: StateTraitPropertiesSpec,
|
||||
|
@ -16,6 +16,7 @@ export default implementRuntimeTrait({
|
||||
metadata: {
|
||||
name: CoreTraitName.Transformer,
|
||||
description: 'transform the value',
|
||||
isDataSource: true,
|
||||
},
|
||||
spec: {
|
||||
properties: TransformerTraitPropertiesSpec,
|
||||
|
Loading…
x
Reference in New Issue
Block a user