feat: add the module mock properties

This commit is contained in:
MrWindlike 2022-05-23 21:32:02 +08:00
parent c33a3ffbcb
commit 8e455ce184
9 changed files with 96 additions and 35 deletions

View File

@ -23,7 +23,7 @@
"husky": "^6.0.0",
"lerna": "^4.0.0",
"lint-staged": "^11.0.0",
"prettier": "^2.3.2"
"prettier": "^2.5.0"
},
"workspaces": [
"packages/*"

View File

@ -1,21 +1,19 @@
import { CloseIcon } from '@chakra-ui/icons';
import { Button, Text, HStack, IconButton, Input, VStack } from '@chakra-ui/react';
import { Box, Button, Text, HStack, IconButton, Input, VStack } from '@chakra-ui/react';
import produce from 'immer';
import { fromPairs, toPairs } from 'lodash-es';
import React, { useState, useMemo, useEffect, useCallback } from 'react';
import { Type } from '@sinclair/typebox';
import { SpecWidget } from '../Widgets/SpecWidget';
import { ExpressionWidget } from '../Widgets/ExpressionWidget';
import { ExpressionEditor } from '../Form/ExpressionEditor';
import { WidgetProps } from '../../types/widget';
import { mergeWidgetOptionsIntoSpec } from '../../utils/widget';
import { ExpressionEditorProps } from './ExpressionEditor';
const IGNORE_SPEC_TYPES = ['array', 'object'];
type RecordEditorProps = Omit<
WidgetProps,
'component' | 'spec' | 'level' | 'path'
> & {
type RecordEditorProps = Omit<WidgetProps, 'component' | 'spec' | 'level' | 'path'> & {
component?: WidgetProps['component'];
spec?: WidgetProps['spec'];
path?: WidgetProps['path'];
@ -45,10 +43,8 @@ const RowItem = (props: RowItemProps) => {
onRemoveRow,
emitDataChange,
} = props;
const { minNum = 0, onlySetValue } = useMemo(
() => spec?.widgetOptions || {},
[spec]
);
const { stateManager } = services;
const { minNum = 0, onlySetValue } = useMemo(() => spec?.widgetOptions || {}, [spec]);
const expressionOptions = useMemo<{
compactOptions: ExpressionEditorProps['compactOptions'];
}>(
@ -152,16 +148,24 @@ const RowItem = (props: RowItemProps) => {
)}
</HStack>
) : (
<Input
flex={2}
minWidth={0}
name="value"
value={value}
title={value}
placeholder="value"
onChange={onInputChange}
onBlur={onBlur}
/>
(() => {
const evaledResult = stateManager.maskedEval(value);
return (
<Box flex="2 2 66.66%" minWidth={0}>
<ExpressionEditor
compactOptions={{
height: '32px',
}}
defaultCode={value}
evaledValue={evaledResult}
error={evaledResult instanceof Error ? evaledResult.message : undefined}
onChange={onValueChange}
onBlur={onBlur}
/>
</Box>
);
})()
)}
{onlySetValue ? null : (
<IconButton

View File

@ -30,7 +30,9 @@ export const ExplorerForm: React.FC<Props> = observer(
name,
version,
};
form = <AppMetaDataForm data={appMetaData} services={services} onSubmit={onSubmit} />;
form = (
<AppMetaDataForm data={appMetaData} services={services} onSubmit={onSubmit} />
);
break;
case 'module':
const moduleSpec = editorStore.appStorage.modules.find(
@ -40,8 +42,15 @@ export const ExplorerForm: React.FC<Props> = observer(
name,
version,
stateMap: moduleSpec?.spec.stateMap || {},
properties: moduleSpec?.spec.properties || {},
};
form = <ModuleMetaDataForm services={services} initData={moduleMetaData} onSubmit={onSubmit} />;
form = (
<ModuleMetaDataForm
services={services}
initData={moduleMetaData}
onSubmit={onSubmit}
/>
);
break;
}
return (

View File

@ -9,6 +9,7 @@ export type ModuleMetaDataFormData = {
name: string;
version: string;
stateMap: Record<string, string>;
properties: Record<string, any>;
};
type ModuleMetaDataFormProps = {
@ -62,6 +63,17 @@ export const ModuleMetaDataForm: React.FC<ModuleMetaDataFormProps> = observer(
}}
/>
</FormControl>
<FormControl>
<FormLabel>Module Mock Properties</FormLabel>
<RecordEditor
services={services}
value={formik.values.properties}
onChange={json => {
formik.setFieldValue('properties', json);
formik.submitForm();
}}
/>
</FormControl>
</VStack>
);
}

View File

@ -55,7 +55,12 @@ export const ExplorerTree: React.FC<ExplorerTreeProps> = observer(
const moduleItemId = genItemId('module', module.version, module.metadata.name);
const onClickModule = () => {
setSelectedItem(moduleItemId);
updateCurrentEditingTarget('module', module.version, module.metadata.name);
updateCurrentEditingTarget(
'module',
module.version,
module.metadata.name,
module.spec
);
};
const onEditModule = () => {
onEdit('module', module.version, module.metadata.name);

View File

@ -113,10 +113,12 @@ export class AppStorage {
version,
name,
stateMap,
properties,
}: {
version: string;
name: string;
stateMap: Record<string, string>;
properties: Record<string, string>;
}
) {
const i = this.modules.findIndex(
@ -125,6 +127,7 @@ export class AppStorage {
const newModules = produce(toJS(this.modules), draft => {
draft[i].metadata.name = name;
draft[i].spec.stateMap = stateMap;
draft[i].spec.properties = properties;
draft[i].version = version;
});

View File

@ -13,19 +13,20 @@ import {
import { genOperation } from '../operations';
import { ExplorerMenuTabs, ToolMenuTabs } from '../constants/enum';
import {
CORE_VERSION,
CoreComponentName,
} from '@sunmao-ui/shared';
import { CORE_VERSION, CoreComponentName } from '@sunmao-ui/shared';
import { isEqual } from 'lodash-es';
type EditingTarget = {
kind: 'app' | 'module';
version: string;
name: string;
spec?: {
properties?: Record<string, any>;
};
};
export class EditorStore {
globalDependencies: Record<string, unknown> = {};
components: ComponentSchema[] = [];
// currentEditingComponents, it could be app's or module's components
_selectedComponentId = '';
@ -57,6 +58,7 @@ export class EditorStore {
private stateManager: StateManagerInterface,
public appStorage: AppStorage
) {
this.globalDependencies = this.stateManager.dependencies;
this.schemaValidator = new SchemaValidator(this.registry);
makeAutoObservable(this, {
eleMap: false,
@ -79,7 +81,6 @@ export class EditorStore {
reaction(
() => this.currentEditingTarget,
(target, prevTarget) => {
if (isEqual(prevTarget, target)) {
return;
}
@ -92,6 +93,14 @@ export class EditorStore {
this.setComponents(this.originComponents);
this.setSelectedComponentId(this.originComponents[0]?.id || '');
const evaledDependencies = stateManager.deepEval(
target.spec?.properties || {},
{ fallbackWhenError: () => undefined }
);
this.stateManager.setDependencies({
...this.globalDependencies,
...evaledDependencies,
});
}
}
);
@ -181,7 +190,9 @@ export class EditorStore {
}
get activeDataSource(): ComponentSchema | null {
return this.components.find((component) => component.id === this.activeDataSourceId) || null;
return (
this.components.find(component => component.id === this.activeDataSourceId) || null
);
}
get activeDataSourceType(): DataSourceType | null {
@ -224,12 +235,14 @@ export class EditorStore {
updateCurrentEditingTarget = (
kind: 'app' | 'module',
version: string,
name: string
name: string,
spec?: EditingTarget['spec']
) => {
this.currentEditingTarget = {
kind,
name,
version,
spec,
};
};

View File

@ -7,7 +7,13 @@ import relativeTime from 'dayjs/plugin/relativeTime';
import LocalizedFormat from 'dayjs/plugin/localizedFormat';
import { isProxy, reactive, toRaw } from '@vue/reactivity';
import { watch } from '../utils/watchReactivity';
import { isNumeric, parseExpression, consoleError, ConsoleType, type ExpChunk } from '@sunmao-ui/shared';
import {
isNumeric,
parseExpression,
consoleError,
ConsoleType,
type ExpChunk,
} from '@sunmao-ui/shared';
dayjs.extend(relativeTime);
dayjs.extend(isLeapYear);
@ -19,7 +25,7 @@ type EvalOptions = {
scopeObject?: Record<string, any>;
overrideScope?: boolean;
fallbackWhenError?: (exp: string) => any;
noConsoleError?: boolean
noConsoleError?: boolean;
};
// TODO: use web worker
@ -35,7 +41,7 @@ export class ExpressionError extends Error {
}
}
export type StateManagerInterface = InstanceType<typeof StateManager>
export type StateManagerInterface = InstanceType<typeof StateManager>;
export class StateManager {
store = reactive<Record<string, any>>({});
@ -105,9 +111,9 @@ export class StateManager {
} catch (error) {
if (error instanceof Error) {
const expressionError = new ExpressionError(error.message);
if (!noConsoleError) {
consoleError(ConsoleType.Expression, '', expressionError.message);
consoleError(ConsoleType.Expression, '', expressionError.message);
}
return fallbackWhenError ? fallbackWhenError(raw) : expressionError;
@ -194,4 +200,8 @@ export class StateManager {
stop: () => stops.forEach(s => s()),
};
}
setDependencies(dependencies: Record<string, unknown> = {}) {
this.dependencies = { ...DefaultDependencies, ...dependencies };
}
}

View File

@ -9057,6 +9057,11 @@ prettier@^2.3.2:
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.4.1.tgz#671e11c89c14a4cfc876ce564106c4a6726c9f5c"
integrity sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==
prettier@^2.5.0:
version "2.6.2"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032"
integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==
pretty-format@^26.0.0, pretty-format@^26.6.2:
version "26.6.2"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93"