mirror of
https://github.com/smartxworks/sunmao-ui.git
synced 2025-04-12 21:50:23 +08:00
feat: add the module mock properties
This commit is contained in:
parent
c33a3ffbcb
commit
8e455ce184
@ -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/*"
|
||||
|
@ -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
|
||||
|
@ -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 (
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
});
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -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 };
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user