mirror of
https://github.com/smartxworks/sunmao-ui.git
synced 2025-03-31 21:30:22 +08:00
Merge pull request #167 from webzard-io/editor-ex
introduce widgets and impl module widget
This commit is contained in:
commit
5b7b21655b
@ -134,6 +134,7 @@ export const ComponentForm: React.FC<Props> = observer(props => {
|
||||
})
|
||||
);
|
||||
}}
|
||||
registry={registry}
|
||||
/>
|
||||
</VStack>
|
||||
</VStack>
|
||||
|
@ -16,7 +16,7 @@ function swap<T>(arr: Array<T>, i1: number, i2: number): Array<T> {
|
||||
}
|
||||
|
||||
const ArrayField: React.FC<Props> = props => {
|
||||
const { schema, formData, onChange } = props;
|
||||
const { schema, formData, onChange, registry } = props;
|
||||
const subSchema = Array.isArray(schema.items) ? schema.items[0] : schema.items;
|
||||
if (typeof subSchema === 'boolean' || !subSchema) {
|
||||
return null;
|
||||
@ -81,6 +81,7 @@ const ArrayField: React.FC<Props> = props => {
|
||||
newFormData[idx] = value;
|
||||
onChange(newFormData);
|
||||
}}
|
||||
registry={registry}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
|
@ -8,7 +8,7 @@ type Props = FieldProps;
|
||||
const _Field: React.FC<
|
||||
Omit<Props, 'schema'> & { schemas: NonNullable<FieldProps['schema']['anyOf']> }
|
||||
> = props => {
|
||||
const { schemas, formData, onChange } = props;
|
||||
const { schemas, formData, onChange, registry } = props;
|
||||
const [schemaIdx, setSchemaIdx] = useState(0);
|
||||
|
||||
const subSchema = schemas[schemaIdx];
|
||||
@ -37,20 +37,35 @@ const _Field: React.FC<
|
||||
label={subSchema.title || ''}
|
||||
formData={formData}
|
||||
onChange={value => onChange(value)}
|
||||
registry={registry}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
const MultiSchemaField: React.FC<Props> = props => {
|
||||
const { schema, formData, onChange } = props;
|
||||
const { schema, formData, onChange, registry } = props;
|
||||
|
||||
if (schema.anyOf) {
|
||||
return <_Field formData={formData} onChange={onChange} schemas={schema.anyOf} />;
|
||||
return (
|
||||
<_Field
|
||||
formData={formData}
|
||||
onChange={onChange}
|
||||
schemas={schema.anyOf}
|
||||
registry={registry}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (schema.oneOf) {
|
||||
return <_Field formData={formData} onChange={onChange} schemas={schema.oneOf} />;
|
||||
return (
|
||||
<_Field
|
||||
formData={formData}
|
||||
onChange={onChange}
|
||||
schemas={schema.oneOf}
|
||||
registry={registry}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -5,7 +5,7 @@ import { FieldProps } from './fields';
|
||||
type Props = FieldProps;
|
||||
|
||||
const ObjectField: React.FC<Props> = props => {
|
||||
const { schema, formData, onChange } = props;
|
||||
const { schema, formData, onChange, registry } = props;
|
||||
|
||||
const properties = Object.keys(schema.properties || {});
|
||||
return (
|
||||
@ -27,6 +27,7 @@ const ObjectField: React.FC<Props> = props => {
|
||||
[name]: value,
|
||||
})
|
||||
}
|
||||
registry={registry}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
@ -8,6 +8,7 @@ import {
|
||||
} from '@chakra-ui/react';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import { FieldProps, getDisplayLabel } from './fields';
|
||||
import { widgets } from './widgets/widgets';
|
||||
import StringField from './StringField';
|
||||
import ObjectField from './ObjectField';
|
||||
import ArrayField from './ArrayField';
|
||||
@ -64,7 +65,7 @@ type Props = FieldProps & {
|
||||
};
|
||||
|
||||
const SchemaField: React.FC<Props> = props => {
|
||||
const { schema, label, formData, onChange } = props;
|
||||
const { schema, label, formData, onChange, registry } = props;
|
||||
|
||||
if (isEmpty(schema)) {
|
||||
return null;
|
||||
@ -72,7 +73,12 @@ const SchemaField: React.FC<Props> = props => {
|
||||
|
||||
let Component = UnsupportedField;
|
||||
|
||||
if (schema.type === 'object') {
|
||||
// customize widgets
|
||||
if (schema.widget && widgets[schema.widget]) {
|
||||
Component = widgets[schema.widget];
|
||||
}
|
||||
// type fields
|
||||
else if (schema.type === 'object') {
|
||||
Component = ObjectField;
|
||||
} else if (schema.type === 'string') {
|
||||
Component = StringField;
|
||||
@ -94,7 +100,12 @@ const SchemaField: React.FC<Props> = props => {
|
||||
|
||||
return (
|
||||
<DefaultTemplate label={label} displayLabel={displayLabel}>
|
||||
<Component schema={schema} formData={formData} onChange={onChange} />
|
||||
<Component
|
||||
schema={schema}
|
||||
formData={formData}
|
||||
onChange={onChange}
|
||||
registry={registry}
|
||||
/>
|
||||
</DefaultTemplate>
|
||||
);
|
||||
};
|
||||
|
@ -1,9 +1,14 @@
|
||||
import { Component } from '@sunmao-ui/core';
|
||||
import { Registry } from '@sunmao-ui/runtime';
|
||||
|
||||
type Schema = Component['spec']['properties'];
|
||||
type EditorSchema = {
|
||||
widget?: string;
|
||||
};
|
||||
|
||||
export type FieldProps = {
|
||||
schema: Schema;
|
||||
schema: Schema & EditorSchema;
|
||||
registry: Registry;
|
||||
formData: any;
|
||||
onChange: (v: any) => void;
|
||||
};
|
||||
|
@ -0,0 +1,78 @@
|
||||
import { Box, FormControl, FormLabel, Select } from '@chakra-ui/react';
|
||||
import React, { useMemo } from 'react';
|
||||
import { FieldProps } from '../fields';
|
||||
import SchemaField from '../SchemaField';
|
||||
|
||||
type Props = FieldProps;
|
||||
|
||||
const ModuleWidget: React.FC<Props> = props => {
|
||||
const { formData, onChange, schema, registry } = props;
|
||||
const moduleTypes = useMemo(() => {
|
||||
const res: string[] = [];
|
||||
for (const version of registry.modules.keys()) {
|
||||
for (const name of registry.modules.get(version)!.keys()) {
|
||||
res.push(`${version}/${name}`);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}, [registry]);
|
||||
const module = useMemo(() => {
|
||||
if (!formData?.type) {
|
||||
return null;
|
||||
}
|
||||
return registry.getModuleByType(formData.type);
|
||||
}, [formData]);
|
||||
|
||||
return (
|
||||
<Box p="2" border="1px solid" borderColor="gray.200" borderRadius="4">
|
||||
<SchemaField
|
||||
schema={schema.properties!.id! as FieldProps['schema']}
|
||||
registry={registry}
|
||||
label="Module ID"
|
||||
formData={formData?.id}
|
||||
onChange={v =>
|
||||
onChange({
|
||||
...formData,
|
||||
id: v,
|
||||
})
|
||||
}
|
||||
/>
|
||||
<FormControl id="type">
|
||||
<FormLabel>Module Type</FormLabel>
|
||||
<Select
|
||||
placeholder="select module"
|
||||
value={formData?.type}
|
||||
onChange={evt =>
|
||||
onChange({
|
||||
...formData,
|
||||
type: evt.currentTarget.value,
|
||||
})
|
||||
}
|
||||
>
|
||||
{moduleTypes.map(type => (
|
||||
<option key={type}>{type}</option>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
{module !== null && (
|
||||
<SchemaField
|
||||
schema={{
|
||||
...module.spec.properties,
|
||||
title: 'Module Properties',
|
||||
}}
|
||||
registry={registry}
|
||||
label="Module Properties"
|
||||
formData={formData?.properties}
|
||||
onChange={v =>
|
||||
onChange({
|
||||
...formData,
|
||||
properties: v,
|
||||
})
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default ModuleWidget;
|
@ -0,0 +1,6 @@
|
||||
import { FieldProps } from '../fields';
|
||||
import ModuleWidget from './ModuleWidget';
|
||||
|
||||
export const widgets: Record<string, React.FC<FieldProps>> = {
|
||||
module: ModuleWidget,
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user