mirror of
https://github.com/smartxworks/sunmao-ui.git
synced 2025-02-17 17:40:31 +08:00
add fetch trait form
This commit is contained in:
parent
2c7efc149c
commit
4ea4b9f8dc
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import { EmotionJSX } from '@emotion/react/types/jsx-namespace';
|
||||
import { FormControl, FormLabel, Input, VStack } from '@chakra-ui/react';
|
||||
import { EmotionJSX } from '@emotion/react/types/jsx-namespace';
|
||||
import { TSchema } from '@sinclair/typebox';
|
||||
import { Application } from '@meta-ui/core';
|
||||
import { parseType, parseTypeBox } from '@meta-ui/runtime';
|
||||
@ -14,6 +14,7 @@ import {
|
||||
} from '../../operations/Operations';
|
||||
import { EventTraitForm } from './EventTraitForm';
|
||||
import { GeneralTraitFormList } from './GeneralTraitFormList';
|
||||
import { FetchTraitForm } from './FetchTraitForm';
|
||||
|
||||
type Props = { selectedId: string; app: Application };
|
||||
|
||||
@ -69,6 +70,7 @@ export const ComponentForm: React.FC<Props> = props => {
|
||||
parseTypeBox(cImpl.spec.properties as TSchema),
|
||||
selectedComponent.properties
|
||||
);
|
||||
|
||||
const propertyFields = Object.keys(properties || []).map(key => {
|
||||
const value = properties![key];
|
||||
return renderField({ key, value, fullKey: key, selectedId });
|
||||
@ -109,6 +111,7 @@ export const ComponentForm: React.FC<Props> = props => {
|
||||
</FormControl>
|
||||
{propertyFields.length > 0 ? propertyForm : null}
|
||||
<EventTraitForm component={selectedComponent} />
|
||||
<FetchTraitForm component={selectedComponent} />
|
||||
<GeneralTraitFormList component={selectedComponent} />
|
||||
</VStack>
|
||||
);
|
||||
|
@ -16,7 +16,6 @@ import { EventHandlerSchema } from '@meta-ui/runtime';
|
||||
import { registry } from '../../../metaUI';
|
||||
import { useAppModel } from '../../../operations/useAppModel';
|
||||
import { formWrapperCSS } from '../style';
|
||||
import produce from 'immer';
|
||||
import { KeyValueEditor } from '../../KeyValueEditor';
|
||||
|
||||
type Props = {
|
||||
@ -24,10 +23,11 @@ type Props = {
|
||||
handler: Static<typeof EventHandlerSchema>;
|
||||
onChange: (hanlder: Static<typeof EventHandlerSchema>) => void;
|
||||
onRemove: () => void;
|
||||
hideEventType?: boolean;
|
||||
};
|
||||
|
||||
export const EventHandlerForm: React.FC<Props> = props => {
|
||||
const { handler, eventTypes, onChange, onRemove } = props;
|
||||
const { handler, eventTypes, onChange, onRemove, hideEventType } = props;
|
||||
const { app } = useAppModel();
|
||||
const [methods, setMethods] = useState<string[]>([]);
|
||||
|
||||
@ -117,7 +117,7 @@ export const EventHandlerForm: React.FC<Props> = props => {
|
||||
<FormControl>
|
||||
<FormLabel>Parameters</FormLabel>
|
||||
<KeyValueEditor
|
||||
initValue={handler.method.parameters}
|
||||
initValue={formik.values.method.parameters}
|
||||
onChange={json => {
|
||||
formik.setFieldValue('method.parameters', json);
|
||||
formik.submitForm();
|
||||
@ -169,7 +169,7 @@ export const EventHandlerForm: React.FC<Props> = props => {
|
||||
return (
|
||||
<Box position="relative">
|
||||
<VStack css={formWrapperCSS}>
|
||||
{typeField}
|
||||
{hideEventType ? null : typeField}
|
||||
{targetField}
|
||||
{methodField}
|
||||
{parametersField}
|
||||
|
@ -0,0 +1,199 @@
|
||||
import {
|
||||
Box,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
HStack,
|
||||
IconButton,
|
||||
Input,
|
||||
Select,
|
||||
VStack,
|
||||
} from '@chakra-ui/react';
|
||||
import { Static } from '@sinclair/typebox';
|
||||
import { AddIcon, CloseIcon } from '@chakra-ui/icons';
|
||||
import { useFormik } from 'formik';
|
||||
import produce from 'immer';
|
||||
import { ApplicationComponent } from '@meta-ui/core';
|
||||
import { EventHandlerSchema, FetchTraitPropertiesSchema } from '@meta-ui/runtime';
|
||||
import { formWrapperCSS } from '../style';
|
||||
import { KeyValueEditor } from '../../KeyValueEditor';
|
||||
import { EventHandlerForm } from '../EventTraitForm/EventHandlerForm';
|
||||
import {
|
||||
ModifyTraitPropertiesOperation,
|
||||
RemoveTraitOperation,
|
||||
} from '../../../operations/Operations';
|
||||
import { eventBus } from '../../../eventBus';
|
||||
|
||||
type EventHandler = Static<typeof EventHandlerSchema>;
|
||||
|
||||
type Props = {
|
||||
component: ApplicationComponent;
|
||||
};
|
||||
|
||||
const httpMethods = ['get', 'post', 'put', 'delete', 'patch'];
|
||||
|
||||
export const FetchTraitForm: React.FC<Props> = props => {
|
||||
const { component } = props;
|
||||
|
||||
const fetchTrait = component.traits.find(t => t.type === 'core/v1/fetch')
|
||||
?.properties as Static<typeof FetchTraitPropertiesSchema>;
|
||||
|
||||
if (!fetchTrait) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: fetchTrait,
|
||||
onSubmit: values => {
|
||||
eventBus.send(
|
||||
'operation',
|
||||
new ModifyTraitPropertiesOperation(component.id, 'core/v1/fetch', values)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const urlField = (
|
||||
<FormControl>
|
||||
<FormLabel>URL</FormLabel>
|
||||
<Input
|
||||
name="url"
|
||||
onChange={formik.handleChange}
|
||||
onBlur={() => formik.submitForm()}
|
||||
value={formik.values.url}
|
||||
/>
|
||||
</FormControl>
|
||||
);
|
||||
|
||||
const methodField = (
|
||||
<FormControl>
|
||||
<FormLabel>Method</FormLabel>
|
||||
<Select
|
||||
name="method"
|
||||
placeholder="Select Method"
|
||||
onChange={formik.handleChange}
|
||||
onBlur={() => formik.submitForm()}
|
||||
value={formik.values.method}
|
||||
>
|
||||
{httpMethods.map(v => (
|
||||
<option key={v} value={v}>
|
||||
{v}
|
||||
</option>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
);
|
||||
const bodyField = (
|
||||
<FormControl>
|
||||
<FormLabel>Body</FormLabel>
|
||||
<KeyValueEditor
|
||||
initValue={formik.values.body}
|
||||
onChange={json => {
|
||||
formik.setFieldValue('body', json);
|
||||
formik.submitForm();
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
);
|
||||
|
||||
const headersField = (
|
||||
<FormControl>
|
||||
<FormLabel>Headers</FormLabel>
|
||||
<KeyValueEditor
|
||||
initValue={formik.values.headers}
|
||||
onChange={json => {
|
||||
formik.setFieldValue('headers', json);
|
||||
formik.submitForm();
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
);
|
||||
|
||||
const onAddHandler = () => {
|
||||
const newHandler: EventHandler = {
|
||||
type: '',
|
||||
componentId: '',
|
||||
method: {
|
||||
name: '',
|
||||
parameters: {},
|
||||
},
|
||||
disabled: false,
|
||||
wait: {
|
||||
type: 'delay',
|
||||
time: 0,
|
||||
},
|
||||
};
|
||||
|
||||
formik.setFieldValue('onComplete', [...formik.values.onComplete, newHandler]);
|
||||
};
|
||||
|
||||
const onCompleteField = (
|
||||
<FormControl>
|
||||
<HStack width="full" justify="space-between">
|
||||
<FormLabel>onComplete</FormLabel>
|
||||
|
||||
<IconButton
|
||||
aria-label="add event"
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
colorScheme="blue"
|
||||
icon={<AddIcon />}
|
||||
onClick={onAddHandler}
|
||||
/>
|
||||
</HStack>
|
||||
{formik.values.onComplete.map((handler, i) => {
|
||||
const onChange = (handler: EventHandler) => {
|
||||
const newOnComplete = produce(formik.values.onComplete, draft => {
|
||||
draft[i] = handler;
|
||||
});
|
||||
formik.setFieldValue('onComplete', newOnComplete);
|
||||
formik.submitForm();
|
||||
};
|
||||
const onRemove = () => {
|
||||
const newOnComplete = produce(formik.values.onComplete, draft => {
|
||||
draft.splice(i, 1);
|
||||
});
|
||||
formik.setFieldValue('onComplete', newOnComplete);
|
||||
formik.submitForm();
|
||||
};
|
||||
return (
|
||||
<EventHandlerForm
|
||||
key={i}
|
||||
eventTypes={[]}
|
||||
handler={handler}
|
||||
hideEventType={true}
|
||||
onChange={onChange}
|
||||
onRemove={onRemove}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</FormControl>
|
||||
);
|
||||
|
||||
return (
|
||||
<Box width="full" position="relative">
|
||||
<strong>Fetch</strong>
|
||||
<HStack width="full" justify="space-between">
|
||||
<VStack css={formWrapperCSS}>
|
||||
{urlField}
|
||||
{methodField}
|
||||
{bodyField}
|
||||
{headersField}
|
||||
{onCompleteField}
|
||||
</VStack>
|
||||
</HStack>
|
||||
<IconButton
|
||||
position="absolute"
|
||||
right="0"
|
||||
top="0"
|
||||
aria-label="remove event handler"
|
||||
variant="ghost"
|
||||
colorScheme="red"
|
||||
size="xs"
|
||||
icon={<CloseIcon />}
|
||||
onClick={() => {
|
||||
const i = component.traits.findIndex(t => t.type === 'core/v1/fetch');
|
||||
eventBus.send('operation', new RemoveTraitOperation(component.id, i));
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
@ -0,0 +1 @@
|
||||
export * from './FetchTraitForm';
|
@ -1,7 +1,6 @@
|
||||
import { AddIcon, ChevronDownIcon } from '@chakra-ui/icons';
|
||||
import { IconButton, Menu, MenuButton, MenuItem, MenuList } from '@chakra-ui/react';
|
||||
import { useMemo } from 'react';
|
||||
import { ignoreTraitsList } from '../../../constants';
|
||||
import { registry } from '../../../metaUI';
|
||||
|
||||
type Props = {
|
||||
@ -12,7 +11,7 @@ export const AddTraitButton: React.FC<Props> = props => {
|
||||
const { onAddTrait } = props;
|
||||
|
||||
const traitTypes = useMemo(() => {
|
||||
return registry.getAllTraitTypes().filter(type => !ignoreTraitsList.includes(type));
|
||||
return registry.getAllTraitTypes();
|
||||
}, []);
|
||||
|
||||
const menuItems = traitTypes.map(type => {
|
||||
|
@ -1,8 +1,11 @@
|
||||
import { ApplicationComponent, ComponentTrait } from '@meta-ui/core';
|
||||
import { HStack, IconButton, VStack } from '@chakra-ui/react';
|
||||
import { parseTypeBox } from '@meta-ui/runtime';
|
||||
import { CloseIcon } from '@chakra-ui/icons';
|
||||
import { TSchema } from '@sinclair/typebox';
|
||||
import { renderField } from '../ComponentForm';
|
||||
import { formWrapperCSS } from '../style';
|
||||
import { registry } from '../../../metaUI';
|
||||
|
||||
type Props = {
|
||||
component: ApplicationComponent;
|
||||
@ -13,7 +16,13 @@ type Props = {
|
||||
export const GeneralTraitForm: React.FC<Props> = props => {
|
||||
const { trait, component, onRemove } = props;
|
||||
|
||||
const fields = Object.keys(trait.properties || []).map(key => {
|
||||
const tImpl = registry.getTraitByType(trait.type);
|
||||
const properties = Object.assign(
|
||||
parseTypeBox(tImpl.spec.properties as TSchema),
|
||||
trait.properties
|
||||
);
|
||||
|
||||
const fields = Object.keys(properties || []).map((key: string) => {
|
||||
const value = trait.properties[key];
|
||||
return renderField({
|
||||
key,
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { CloseIcon } from '@chakra-ui/icons';
|
||||
import { Button, Flex, HStack, IconButton, Input, VStack } from '@chakra-ui/react';
|
||||
import { Button, HStack, IconButton, Input, VStack } from '@chakra-ui/react';
|
||||
import produce from 'immer';
|
||||
import { fromPairs, toPairs } from 'lodash';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
type Props = {
|
||||
@ -10,21 +11,11 @@ type Props = {
|
||||
|
||||
export const KeyValueEditor: React.FC<Props> = props => {
|
||||
const [rows, setRows] = useState<Array<[string, string]>>(() => {
|
||||
if (!props.initValue) return [];
|
||||
const res: Array<[string, string]> = [];
|
||||
for (const key in props.initValue) {
|
||||
res.push([key, props.initValue[key]]);
|
||||
}
|
||||
return res;
|
||||
return toPairs(props.initValue);
|
||||
});
|
||||
|
||||
const emitDataChange = (newRows: Array<[string, string]>) => {
|
||||
const json = newRows.reduce<Record<string, string>>((res, curr) => {
|
||||
if (curr[0]) {
|
||||
res[curr[0]] = curr[1];
|
||||
}
|
||||
return res;
|
||||
}, {});
|
||||
const json = fromPairs(newRows);
|
||||
props.onChange(json);
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Application } from '@meta-ui/core';
|
||||
|
||||
export const ignoreTraitsList = ['core/v1/slot', 'core/v1/event'];
|
||||
export const ignoreTraitsList = ['core/v1/slot', 'core/v1/event', 'core/v1/fetch'];
|
||||
|
||||
export const DefaultAppSchema: Application = {
|
||||
kind: 'Application',
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
ModifyComponentIdOperation,
|
||||
AddTraitOperation,
|
||||
RemoveTraitOperation,
|
||||
ModifyTraitPropertiesOperation,
|
||||
} from './Operations';
|
||||
import { produce } from 'immer';
|
||||
import { registry } from '../metaUI';
|
||||
@ -175,6 +176,30 @@ export class AppModelManager {
|
||||
this.undoStack.push(undoOperation);
|
||||
}
|
||||
break;
|
||||
case 'modifyTraitProperties':
|
||||
const mtpo = o as ModifyTraitPropertiesOperation;
|
||||
let oldProperties;
|
||||
newApp = produce(this.app, draft => {
|
||||
draft.spec.components.forEach(c => {
|
||||
if (c.id === mtpo.componentId) {
|
||||
c.traits.forEach(t => {
|
||||
if (t.type === mtpo.traitType) {
|
||||
oldProperties = t.properties;
|
||||
t.properties = mtpo.properties;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
if (!noEffect) {
|
||||
const undoOperation = new ModifyTraitPropertiesOperation(
|
||||
mtpo.componentId,
|
||||
mtpo.traitType,
|
||||
oldProperties || {}
|
||||
);
|
||||
this.undoStack.push(undoOperation);
|
||||
}
|
||||
break;
|
||||
case 'addTraitOperation':
|
||||
const ato = o as AddTraitOperation;
|
||||
let i = 0;
|
||||
@ -203,10 +228,6 @@ export class AppModelManager {
|
||||
}
|
||||
});
|
||||
});
|
||||
if (!noEffect) {
|
||||
// const removeTraitOperation = new AddTraitOperation(rto.componentId, trait.type);
|
||||
// this.undoStack.push(removeTraitOperation);
|
||||
}
|
||||
break;
|
||||
}
|
||||
this.updateApp(newApp);
|
||||
|
@ -55,3 +55,12 @@ export class ModifyTraitPropertyOperation {
|
||||
public propertyValue: any
|
||||
) {}
|
||||
}
|
||||
|
||||
export class ModifyTraitPropertiesOperation {
|
||||
kind = 'modifyTraitProperties';
|
||||
constructor(
|
||||
public componentId: string,
|
||||
public traitType: string,
|
||||
public properties: Record<string, any>
|
||||
) {}
|
||||
}
|
||||
|
@ -77,13 +77,11 @@
|
||||
name: 'query',
|
||||
url: `{{ "https://skyscanner-skyscanner-flight-search-v1.p.rapidapi.com/apiservices/browseroutes/v1.0/"+fetch_list.country+"/CNY/zh-CN/CSHA/SZX/anytime/anytime"}}`,
|
||||
method: 'get',
|
||||
headers: [
|
||||
{ key: 'x-rapidapi-key', value: `{{fetch_list.token}}` },
|
||||
{
|
||||
key: 'x-rapidapi-host',
|
||||
value: 'skyscanner-skyscanner-flight-search-v1.p.rapidapi.com',
|
||||
},
|
||||
],
|
||||
headers: {
|
||||
'x-rapidapi-key': `{{fetch_list.token}}`,
|
||||
'x-rapidapi-host':
|
||||
'skyscanner-skyscanner-flight-search-v1.p.rapidapi.com',
|
||||
},
|
||||
lazy: true,
|
||||
},
|
||||
},
|
||||
|
@ -80,13 +80,11 @@
|
||||
name: 'query',
|
||||
url: `{{ "https://skyscanner-skyscanner-flight-search-v1.p.rapidapi.com/apiservices/browseroutes/v1.0/"+fetch_list.country+"/CNY/zh-CN/CSHA/SZX/anytime/anytime"}}`,
|
||||
method: 'get',
|
||||
headers: [
|
||||
{ key: 'x-rapidapi-key', value: `{{fetch_btn.token}}` },
|
||||
{
|
||||
key: 'x-rapidapi-host',
|
||||
value: 'skyscanner-skyscanner-flight-search-v1.p.rapidapi.com',
|
||||
},
|
||||
],
|
||||
headers: {
|
||||
'x-rapidapi-key': `{{fetch_btn.token}}`,
|
||||
'x-rapidapi-host':
|
||||
'skyscanner-skyscanner-flight-search-v1.p.rapidapi.com',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
|
@ -45,7 +45,9 @@
|
||||
url: 'https://61373521eac1410017c18209.mockapi.io/Volume',
|
||||
method: 'post',
|
||||
lazy: true,
|
||||
headers: [{ key: 'Content-Type', value: 'application/json' }],
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: '{{ form.data }}',
|
||||
onComplete: [
|
||||
{
|
||||
|
@ -45,7 +45,9 @@
|
||||
url: 'https://61373521eac1410017c18209.mockapi.io/Volume',
|
||||
method: 'post',
|
||||
lazy: true,
|
||||
headers: [{ key: 'Content-Type', value: 'application/json' }],
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: '{{ form.data }}',
|
||||
onComplete: [
|
||||
{
|
||||
|
@ -72,7 +72,9 @@
|
||||
name: 'query',
|
||||
url: 'https://61373521eac1410017c18209.mockapi.io/users/{{ table.selectedItem ? table.selectedItem.id : "" }}',
|
||||
method: 'put',
|
||||
headers: [{ key: 'Content-Type', value: 'application/json' }],
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: '{{ {...table.selectedItem, name: nameInput.value } }}',
|
||||
lazy: true,
|
||||
onComplete: [
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Type } from '@sinclair/typebox';
|
||||
import { EventHandlerSchema } from '../../../types/EventHandlerSchema';
|
||||
import { EventHandlerSchema } from '../../../types/TraitPropertiesSchema';
|
||||
|
||||
export const MajorKeyPropertySchema = Type.String();
|
||||
export const RowsPerPagePropertySchema = Type.Number();
|
||||
|
@ -25,5 +25,5 @@ export * from './utils/parseType';
|
||||
export * from './utils/parseTypeBox';
|
||||
export * from './utils/encodeDragDataTransfer';
|
||||
export * from './types/RuntimeSchema';
|
||||
export * from './types/EventHandlerSchema';
|
||||
export * from './types/TraitPropertiesSchema';
|
||||
export * from './constants';
|
||||
|
@ -2,7 +2,7 @@ import { createTrait } from '@meta-ui/core';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
import { debounce, throttle, delay } from 'lodash';
|
||||
import { CallbackMap, TraitImplementation } from 'src/types/RuntimeSchema';
|
||||
import { EventHandlerSchema } from '../../types/EventHandlerSchema';
|
||||
import { EventHandlerSchema } from '../../types/TraitPropertiesSchema';
|
||||
|
||||
const useEventTrait: TraitImplementation<Static<typeof PropsSchema>> = ({
|
||||
handlers,
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { createTrait } from '@meta-ui/core';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
import { TraitImplementation } from 'src/types/RuntimeSchema';
|
||||
import { EventHandlerSchema } from '../../types/EventHandlerSchema';
|
||||
import { FetchTraitPropertiesSchema } from '../../types/TraitPropertiesSchema';
|
||||
|
||||
const hasFetchedMap = new Map<string, boolean>();
|
||||
|
||||
const useFetchTrait: TraitImplementation<Static<typeof PropsSchema>> = ({
|
||||
const useFetchTrait: TraitImplementation<Static<typeof FetchTraitPropertiesSchema>> = ({
|
||||
url,
|
||||
method,
|
||||
lazy: _lazy,
|
||||
@ -27,9 +27,8 @@ const useFetchTrait: TraitImplementation<Static<typeof PropsSchema>> = ({
|
||||
// FIXME: listen to the header change
|
||||
const headers = new Headers();
|
||||
if (_headers) {
|
||||
for (let i = 0; i < _headers.length; i++) {
|
||||
const header = _headers[i];
|
||||
headers.append(header.key, _headers[i].value);
|
||||
for (const key in _headers) {
|
||||
headers.append(key, _headers[key]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,7 +36,7 @@ const useFetchTrait: TraitImplementation<Static<typeof PropsSchema>> = ({
|
||||
fetch(url, {
|
||||
method,
|
||||
headers,
|
||||
body: JSON.stringify(body),
|
||||
body: method === 'get' ? undefined : JSON.stringify(body),
|
||||
}).then(
|
||||
async response => {
|
||||
if (response.ok) {
|
||||
@ -105,15 +104,6 @@ const useFetchTrait: TraitImplementation<Static<typeof PropsSchema>> = ({
|
||||
};
|
||||
};
|
||||
|
||||
const PropsSchema = Type.Object({
|
||||
url: Type.String(), // {format:uri}?;
|
||||
method: Type.String(), // {pattern: /^(get|post|put|delete)$/i}
|
||||
lazy: Type.Boolean(),
|
||||
headers: Type.Array(Type.Object({ key: Type.String(), value: Type.String() })),
|
||||
body: Type.Any(),
|
||||
onComplete: Type.Array(EventHandlerSchema),
|
||||
});
|
||||
|
||||
export default {
|
||||
...createTrait({
|
||||
version: 'core/v1',
|
||||
@ -122,7 +112,7 @@ export default {
|
||||
description: 'fetch data to store',
|
||||
},
|
||||
spec: {
|
||||
properties: PropsSchema,
|
||||
properties: FetchTraitPropertiesSchema,
|
||||
state: Type.Object({
|
||||
fetch: Type.Object({
|
||||
loading: Type.Boolean(),
|
||||
|
@ -1,23 +0,0 @@
|
||||
import { Type } from '@sinclair/typebox';
|
||||
|
||||
export const EventHandlerSchema = Type.Object({
|
||||
type: Type.String(),
|
||||
componentId: Type.String(),
|
||||
method: Type.Object({
|
||||
name: Type.String(),
|
||||
parameters: Type.Any(),
|
||||
}),
|
||||
wait: Type.Optional(
|
||||
Type.Object({
|
||||
type: Type.KeyOf(
|
||||
Type.Object({
|
||||
debounce: Type.String(),
|
||||
throttle: Type.String(),
|
||||
delay: Type.String(),
|
||||
})
|
||||
),
|
||||
time: Type.Number(),
|
||||
})
|
||||
),
|
||||
disabled: Type.Optional(Type.Boolean()),
|
||||
});
|
35
packages/runtime/src/types/TraitPropertiesSchema.ts
Normal file
35
packages/runtime/src/types/TraitPropertiesSchema.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { Type } from '@sinclair/typebox';
|
||||
|
||||
export const EventHandlerSchema = Type.Object(
|
||||
{
|
||||
type: Type.String(),
|
||||
componentId: Type.String(),
|
||||
method: Type.Object({
|
||||
name: Type.String(),
|
||||
parameters: Type.Record(Type.String(), Type.String()),
|
||||
}),
|
||||
wait: Type.Optional(
|
||||
Type.Object({
|
||||
type: Type.KeyOf(
|
||||
Type.Object({
|
||||
debounce: Type.String(),
|
||||
throttle: Type.String(),
|
||||
delay: Type.String(),
|
||||
})
|
||||
),
|
||||
time: Type.Number(),
|
||||
})
|
||||
),
|
||||
disabled: Type.Optional(Type.Boolean()),
|
||||
},
|
||||
{ $id: 'eventHanlder' }
|
||||
);
|
||||
|
||||
export const FetchTraitPropertiesSchema = Type.Object({
|
||||
url: Type.String(), // {format:uri}?;
|
||||
method: Type.String(), // {pattern: /^(get|post|put|delete)$/i}
|
||||
lazy: Type.Boolean(),
|
||||
headers: Type.Record(Type.String(), Type.String()),
|
||||
body: Type.Record(Type.String(), Type.String()),
|
||||
onComplete: Type.Array(EventHandlerSchema),
|
||||
});
|
Loading…
Reference in New Issue
Block a user