mirror of
https://github.com/smartxworks/sunmao-ui.git
synced 2025-04-06 21:40:23 +08:00
Merge pull request #669 from smartxworks/feat/event-widget-form
Editor support emit and listen module's event
This commit is contained in:
commit
a09b65955c
@ -14,6 +14,8 @@ import {
|
||||
CoreWidgetName,
|
||||
generateDefaultValueFromSpec,
|
||||
MountEvents,
|
||||
GLOBAL_MODULE_ID,
|
||||
ModuleEventMethodSpec,
|
||||
} from '@sunmao-ui/shared';
|
||||
import { JSONSchema7Object } from 'json-schema';
|
||||
import { PREVENT_POPOVER_WIDGET_CLOSE_CLASS } from '../../constants/widget';
|
||||
@ -32,7 +34,7 @@ declare module '../../types/widget' {
|
||||
export const EventWidget: React.FC<WidgetProps<EventWidgetType>> = observer(props => {
|
||||
const { value, path, level, component, spec, services, onChange } = props;
|
||||
const { registry, editorStore, appModelManager } = services;
|
||||
const { components } = editorStore;
|
||||
const { components, currentEditingTarget } = editorStore;
|
||||
const utilMethods = useMemo(() => registry.getAllUtilMethods(), [registry]);
|
||||
const [methods, setMethods] = useState<string[]>([]);
|
||||
|
||||
@ -62,9 +64,22 @@ export const EventWidget: React.FC<WidgetProps<EventWidgetType>> = observer(prop
|
||||
},
|
||||
[registry]
|
||||
);
|
||||
|
||||
const eventTypes = useMemo(() => {
|
||||
return [...registry.getComponentByType(component.type).spec.events, ...MountEvents];
|
||||
}, [component.type, registry]);
|
||||
let moduleEvents: string[] = [];
|
||||
if (component.type === 'core/v1/moduleContainer') {
|
||||
// if component is moduleContainer, add module events to it
|
||||
const moduleType = component.properties.type as string;
|
||||
const moduleSpec = registry.getModuleByType(moduleType);
|
||||
moduleEvents = moduleSpec.spec.events;
|
||||
}
|
||||
return [
|
||||
...registry.getComponentByType(component.type).spec.events,
|
||||
...moduleEvents,
|
||||
...MountEvents,
|
||||
];
|
||||
}, [component.properties.type, component.type, registry]);
|
||||
|
||||
const hasParams = useMemo(
|
||||
() => Object.keys(formik.values.method.parameters ?? {}).length,
|
||||
[formik.values.method.parameters]
|
||||
@ -79,6 +94,8 @@ export const EventWidget: React.FC<WidgetProps<EventWidgetType>> = observer(prop
|
||||
const targetMethod = registry.getUtilMethodByType(methodType)!;
|
||||
|
||||
spec = targetMethod.spec.parameters;
|
||||
} else if (componentId === GLOBAL_MODULE_ID) {
|
||||
spec = ModuleEventMethodSpec;
|
||||
} else {
|
||||
const targetComponent = appModelManager.appModel.getComponentById(componentId);
|
||||
const targetMethod = (findMethodsByComponent(targetComponent) ?? []).find(
|
||||
@ -140,19 +157,42 @@ export const EventWidget: React.FC<WidgetProps<EventWidgetType>> = observer(prop
|
||||
utilMethod => `${utilMethod.version}/${utilMethod.metadata.name}`
|
||||
)
|
||||
);
|
||||
} else if (
|
||||
componentId === GLOBAL_MODULE_ID &&
|
||||
currentEditingTarget.kind === 'module'
|
||||
) {
|
||||
// if user is editing module, show the events of module spec as method
|
||||
const moduleType = `${currentEditingTarget.version}/${currentEditingTarget.name}`;
|
||||
let methodNames: string[] = [];
|
||||
if (moduleType) {
|
||||
const moduleSpec = services.registry.getModuleByType(moduleType);
|
||||
|
||||
if (moduleSpec) {
|
||||
methodNames = moduleSpec.spec.events;
|
||||
}
|
||||
}
|
||||
setMethods(methodNames);
|
||||
} else {
|
||||
// if user is editing application, show methods of component
|
||||
const component = components.find(c => c.id === componentId);
|
||||
|
||||
if (component) {
|
||||
const methodNames: string[] = findMethodsByComponent(component).map(
|
||||
({ name }) => name
|
||||
);
|
||||
|
||||
setMethods(methodNames);
|
||||
}
|
||||
}
|
||||
},
|
||||
[components, utilMethods, findMethodsByComponent]
|
||||
[
|
||||
currentEditingTarget.kind,
|
||||
currentEditingTarget.version,
|
||||
currentEditingTarget.name,
|
||||
utilMethods,
|
||||
services.registry,
|
||||
components,
|
||||
findMethodsByComponent,
|
||||
]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@ -235,6 +275,11 @@ export const EventWidget: React.FC<WidgetProps<EventWidgetType>> = observer(prop
|
||||
style={{ width: '100%' }}
|
||||
value={formik.values.componentId === '' ? undefined : formik.values.componentId}
|
||||
>
|
||||
{currentEditingTarget.kind === 'module' ? (
|
||||
<ComponentTargetSelect.Option key={GLOBAL_MODULE_ID} value={GLOBAL_MODULE_ID}>
|
||||
{GLOBAL_MODULE_ID}
|
||||
</ComponentTargetSelect.Option>
|
||||
) : undefined}
|
||||
{[{ id: GLOBAL_UTIL_METHOD_ID }].concat(components).map(c => (
|
||||
<ComponentTargetSelect.Option key={c.id} value={c.id}>
|
||||
{c.id}
|
||||
|
@ -7,6 +7,11 @@ export interface EditorServicesInterface extends UIServices {
|
||||
registry: RegistryInterface;
|
||||
editorStore: {
|
||||
components: ComponentSchema[];
|
||||
currentEditingTarget: {
|
||||
kind: 'app' | 'module';
|
||||
version: string;
|
||||
name: string;
|
||||
};
|
||||
};
|
||||
appModelManager: {
|
||||
appModel: any;
|
||||
|
@ -18,7 +18,7 @@ dayjs.locale('zh-cn');
|
||||
type EvalOptions = {
|
||||
scopeObject?: Record<string, any>;
|
||||
overrideScope?: boolean;
|
||||
fallbackWhenError?: (exp: string) => any;
|
||||
fallbackWhenError?: (exp: string, err: Error) => any;
|
||||
// when ignoreEvalError is true, the eval process will continue after error happens in nests expression.
|
||||
ignoreEvalError?: boolean;
|
||||
slotKey?: string;
|
||||
@ -128,7 +128,9 @@ export class StateManager {
|
||||
consoleError(ConsoleType.Expression, raw, expressionError.message);
|
||||
}
|
||||
|
||||
return fallbackWhenError ? fallbackWhenError(raw) : expressionError;
|
||||
return fallbackWhenError
|
||||
? fallbackWhenError(raw, expressionError)
|
||||
: expressionError;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
import { debounce, throttle, delay } from 'lodash';
|
||||
import { EventCallBackHandlerSpec } from '@sunmao-ui/shared';
|
||||
import { EventCallBackHandlerSpec, MODULE_ID_EXP } from '@sunmao-ui/shared';
|
||||
import { type PropsBeforeEvaled } from '@sunmao-ui/core';
|
||||
import { UIServices } from '../types';
|
||||
|
||||
@ -18,6 +18,10 @@ export const runEventHandler = (
|
||||
// Eval before sending event to assure the handler object is evaled from the latest state.
|
||||
const evalOptions = {
|
||||
slotKey,
|
||||
// keep MODULE_ID_EXP when error
|
||||
fallbackWhenError(exp: string, err: Error) {
|
||||
return exp === MODULE_ID_EXP ? exp : err;
|
||||
},
|
||||
};
|
||||
const evaledHandlers = stateManager.deepEval(rawHandlers, evalOptions) as Static<
|
||||
typeof EventCallBackHandlerSpec
|
||||
|
@ -7,6 +7,7 @@ export const LIST_ITEM_INDEX_EXP = '$i';
|
||||
export const SLOT_PROPS_EXP = '$slot';
|
||||
export const GLOBAL_UTIL_METHOD_ID = '$utils';
|
||||
export const GLOBAL_MODULE_ID = '$module';
|
||||
export const MODULE_ID_EXP = '{{$moduleId}}';
|
||||
|
||||
export const ExpressionKeywords = [
|
||||
LIST_ITEM_EXP,
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { EventHandlerSpec } from './event';
|
||||
import { Type } from '@sinclair/typebox';
|
||||
import { CORE_VERSION, CoreWidgetName } from '../constants/core';
|
||||
import { MODULE_ID_EXP } from '../constants';
|
||||
|
||||
export const ModuleRenderSpec = Type.Object(
|
||||
{
|
||||
@ -27,3 +28,7 @@ export const ModuleRenderSpec = Type.Object(
|
||||
widget: 'core/v1/module',
|
||||
}
|
||||
);
|
||||
|
||||
export const ModuleEventMethodSpec = Type.Object({
|
||||
moduleId: Type.Literal(MODULE_ID_EXP),
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user