mirror of
https://github.com/smartxworks/sunmao-ui.git
synced 2025-02-17 17:40:31 +08:00
Merge pull request #260 from webzard-io/feat/windlike-patch
feat(editor): auto-complete the parameters of the method
This commit is contained in:
commit
ed913afc94
@ -10,7 +10,7 @@ const ToastPosition = Type.Union([
|
||||
Type.Literal('bottom-right'),
|
||||
Type.Literal('bottom-left'),
|
||||
]);
|
||||
export const ToastOpenParamterSchema = Type.Object({
|
||||
export const ToastOpenParameterSchema = Type.Object({
|
||||
position: Type.Optional(ToastPosition),
|
||||
duration: Type.Optional(Type.Union([Type.Number(), Type.Null()])),
|
||||
title: Type.Optional(Type.String()),
|
||||
@ -40,7 +40,7 @@ export const ToastCloseParameterSchema = Type.Object({
|
||||
positions: Type.Optional(Type.Array(ToastPosition)),
|
||||
});
|
||||
|
||||
export type ToastOpenParameter = Static<typeof ToastOpenParamterSchema>;
|
||||
export type ToastOpenParameter = Static<typeof ToastOpenParameterSchema>;
|
||||
export type ToastCloseParameter = Static<typeof ToastCloseParameterSchema>;
|
||||
|
||||
const pickProperty = <T, U extends Record<string, any>>(
|
||||
@ -58,14 +58,15 @@ export default function ToastUtilMethodFactory() {
|
||||
let toast: ReturnType<typeof createStandaloneToast> | undefined;
|
||||
const toastOpen: UtilMethod = {
|
||||
name: 'toast.open',
|
||||
method(parameters: Static<typeof ToastOpenParamterSchema>) {
|
||||
method(parameters: Static<typeof ToastOpenParameterSchema>) {
|
||||
if (!toast) {
|
||||
toast = createStandaloneToast();
|
||||
}
|
||||
if (parameters) {
|
||||
toast(pickProperty(ToastOpenParamterSchema, parameters));
|
||||
toast(pickProperty(ToastOpenParameterSchema, parameters));
|
||||
}
|
||||
},
|
||||
parameters: ToastOpenParameterSchema,
|
||||
};
|
||||
|
||||
const toastClose: UtilMethod = {
|
||||
@ -85,6 +86,7 @@ export default function ToastUtilMethodFactory() {
|
||||
}
|
||||
}
|
||||
},
|
||||
parameters: ToastCloseParameterSchema,
|
||||
};
|
||||
return [toastOpen, toastClose];
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useCallback, useEffect, useState, useMemo } from 'react';
|
||||
import {
|
||||
Box,
|
||||
FormControl,
|
||||
@ -19,6 +19,7 @@ import { KeyValueEditor } from '../../KeyValueEditor';
|
||||
import { EditorServices } from '../../../types';
|
||||
import { ComponentModel } from '../../../AppModel/ComponentModel';
|
||||
import { AppModel } from '../../../AppModel/AppModel';
|
||||
import { ComponentId } from '../../../AppModel/IAppModel';
|
||||
|
||||
type Props = {
|
||||
eventTypes: readonly string[];
|
||||
@ -31,7 +32,7 @@ type Props = {
|
||||
|
||||
export const EventHandlerForm: React.FC<Props> = observer(props => {
|
||||
const { handler, eventTypes, onChange, onRemove, hideEventType, services } = props;
|
||||
const { registry, editorStore } = services;
|
||||
const { registry, editorStore, appModelManager } = services;
|
||||
const { utilMethods } = registry;
|
||||
const { components } = editorStore;
|
||||
const [methods, setMethods] = useState<string[]>([]);
|
||||
@ -43,6 +44,41 @@ export const EventHandlerForm: React.FC<Props> = observer(props => {
|
||||
},
|
||||
});
|
||||
|
||||
const hasParams = useMemo(
|
||||
() => Object.keys(formik.values.method.parameters ?? {}).length,
|
||||
[formik.values.method.parameters]
|
||||
);
|
||||
const params = useMemo(() => {
|
||||
const params: Record<string, string> = {};
|
||||
const { values } = formik;
|
||||
const methodName = values.method.name;
|
||||
|
||||
if (values.method.name) {
|
||||
let parameters = {};
|
||||
|
||||
if (handler.componentId === GLOBAL_UTILS_ID) {
|
||||
const targetMethod = utilMethods.get(methodName);
|
||||
|
||||
parameters = targetMethod?.parameters?.properties ?? {};
|
||||
} else {
|
||||
const targetComponent = appModelManager.appModel.getComponentById(
|
||||
handler.componentId as ComponentId
|
||||
);
|
||||
const targetMethod = (targetComponent?.methods ?? []).find(
|
||||
({ name }) => name === formik.values.method.name
|
||||
);
|
||||
|
||||
parameters = targetMethod?.parameters?.properties ?? {};
|
||||
}
|
||||
|
||||
for (const key in parameters) {
|
||||
params[key] = values.method.parameters?.[key] ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
return params;
|
||||
}, [formik.values.method.name]);
|
||||
|
||||
const updateMethods = useCallback(
|
||||
(componentId: string) => {
|
||||
if (componentId === GLOBAL_UTILS_ID) {
|
||||
@ -68,6 +104,10 @@ export const EventHandlerForm: React.FC<Props> = observer(props => {
|
||||
formik.setValues(handler);
|
||||
}, [handler]);
|
||||
|
||||
useEffect(() => {
|
||||
formik.setFieldValue('method.parameters', params);
|
||||
}, [params]);
|
||||
|
||||
useEffect(() => {
|
||||
if (handler.componentId) {
|
||||
updateMethods(handler.componentId);
|
||||
@ -76,6 +116,8 @@ export const EventHandlerForm: React.FC<Props> = observer(props => {
|
||||
|
||||
const onTargetComponentChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
updateMethods(e.target.value);
|
||||
formik.handleChange(e);
|
||||
formik.setFieldValue('method', { name: '', parameters: {} });
|
||||
};
|
||||
|
||||
const typeField = (
|
||||
@ -102,10 +144,7 @@ export const EventHandlerForm: React.FC<Props> = observer(props => {
|
||||
<Select
|
||||
name="componentId"
|
||||
onBlur={() => formik.submitForm()}
|
||||
onChange={e => {
|
||||
onTargetComponentChange(e);
|
||||
formik.handleChange(e);
|
||||
}}
|
||||
onChange={onTargetComponentChange}
|
||||
placeholder="Select Target Component"
|
||||
value={formik.values.componentId}
|
||||
>
|
||||
@ -145,6 +184,7 @@ export const EventHandlerForm: React.FC<Props> = observer(props => {
|
||||
formik.setFieldValue('method.parameters', json);
|
||||
formik.submitForm();
|
||||
}}
|
||||
onlySetValue={true}
|
||||
/>
|
||||
</FormControl>
|
||||
);
|
||||
@ -195,7 +235,7 @@ export const EventHandlerForm: React.FC<Props> = observer(props => {
|
||||
{hideEventType ? null : typeField}
|
||||
{targetField}
|
||||
{methodField}
|
||||
{parametersField}
|
||||
{hasParams ? parametersField : null}
|
||||
{waitTypeField}
|
||||
{waitTimeField}
|
||||
{disabledField}
|
||||
|
@ -7,9 +7,11 @@ import React, { useState, useEffect } from 'react';
|
||||
type Props = {
|
||||
onChange: (json: Record<string, string>) => void;
|
||||
value?: Record<string, string>;
|
||||
onlySetValue?: boolean;
|
||||
};
|
||||
|
||||
export const KeyValueEditor: React.FC<Props> = props => {
|
||||
const { onlySetValue } = props;
|
||||
const [rows, setRows] = useState<Array<[string, string]>>(() => {
|
||||
return toPairs(props.value);
|
||||
});
|
||||
@ -54,6 +56,7 @@ export const KeyValueEditor: React.FC<Props> = props => {
|
||||
size="sm"
|
||||
onChange={onInputChange}
|
||||
onBlur={onBlur}
|
||||
isDisabled={onlySetValue}
|
||||
/>
|
||||
<Input
|
||||
name="value"
|
||||
@ -63,13 +66,15 @@ export const KeyValueEditor: React.FC<Props> = props => {
|
||||
onChange={onInputChange}
|
||||
onBlur={onBlur}
|
||||
/>
|
||||
<IconButton
|
||||
aria-label="remove row"
|
||||
icon={<CloseIcon />}
|
||||
size="xs"
|
||||
onClick={() => onRemoveRow(i)}
|
||||
variant="ghost"
|
||||
/>
|
||||
{onlySetValue ? null : (
|
||||
<IconButton
|
||||
aria-label="remove row"
|
||||
icon={<CloseIcon />}
|
||||
size="xs"
|
||||
onClick={() => onRemoveRow(i)}
|
||||
variant="ghost"
|
||||
/>
|
||||
)}
|
||||
</HStack>
|
||||
);
|
||||
});
|
||||
@ -77,9 +82,11 @@ export const KeyValueEditor: React.FC<Props> = props => {
|
||||
return (
|
||||
<VStack spacing="1" alignItems="start">
|
||||
{rowItems}
|
||||
<Button onClick={onAddRow} size="xs">
|
||||
+ Add
|
||||
</Button>
|
||||
{onlySetValue ? null : (
|
||||
<Button onClick={onAddRow} size="xs">
|
||||
+ Add
|
||||
</Button>
|
||||
)}
|
||||
</VStack>
|
||||
);
|
||||
};
|
||||
|
@ -28,6 +28,7 @@ import { ApiService } from './apiService';
|
||||
export type UtilMethod = {
|
||||
name: string;
|
||||
method: (parameters?: any) => void;
|
||||
parameters?: any;
|
||||
};
|
||||
|
||||
export type UtilMethodFactory = () => UtilMethod[];
|
||||
@ -50,7 +51,7 @@ export class Registry {
|
||||
components = new Map<string, Map<string, AnyImplementedRuntimeComponent>>();
|
||||
traits = new Map<string, Map<string, ImplementedRuntimeTrait>>();
|
||||
modules = new Map<string, Map<string, ImplementedRuntimeModule>>();
|
||||
utilMethods = new Map<string, UtilMethod['method']>();
|
||||
utilMethods = new Map<string, UtilMethod>();
|
||||
private apiService: ApiService;
|
||||
|
||||
constructor(apiService: ApiService) {
|
||||
@ -166,7 +167,7 @@ export class Registry {
|
||||
if (this.utilMethods.get(m.name)) {
|
||||
throw new Error(`Already has utilMethod ${m.name} in this registry.`);
|
||||
}
|
||||
this.utilMethods.set(m.name, m.method);
|
||||
this.utilMethods.set(m.name, m);
|
||||
}
|
||||
|
||||
installLib(lib: SunmaoLib) {
|
||||
@ -185,9 +186,19 @@ export class Registry {
|
||||
private mountUtilMethods() {
|
||||
this.apiService.on('uiMethod', ({ componentId, name, parameters }) => {
|
||||
if (componentId === GLOBAL_UTILS_ID) {
|
||||
const utilMethod = this.utilMethods.get(name);
|
||||
const utilMethod = this.utilMethods.get(name)?.method;
|
||||
if (utilMethod) {
|
||||
utilMethod(parameters);
|
||||
const params: Record<string, unknown> = {};
|
||||
|
||||
for (const key in parameters) {
|
||||
const value = parameters[key];
|
||||
|
||||
if (value !== undefined && value !== '') {
|
||||
params[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
utilMethod(params);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user