Skip to content

Commit

Permalink
fix: implement enum
Browse files Browse the repository at this point in the history
  • Loading branch information
amir78729 committed Jun 21, 2024
1 parent b8cc53b commit cb95c4a
Show file tree
Hide file tree
Showing 7 changed files with 165 additions and 13 deletions.
69 changes: 59 additions & 10 deletions src/components/SchemaPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {RJSFSchema} from "@rjsf/utils";
import AddFieldModal from "./AddFieldModal";
import Numbers from '@mui/icons-material/Numbers';
import {
Add,
Add, Checklist,
DataArray,
DataObject,
Delete,
Expand All @@ -20,7 +20,7 @@ import {
IconButton,
ListItem,
ListItemIcon,
ListItemText,
ListItemText, Stack,
Tooltip,
Typography
} from "@mui/material";
Expand All @@ -39,10 +39,12 @@ type Props = {
}

// TODO: refactor
const renderHeader = ({icon, schema, onDelete, name, path}: {
const renderHeader = ({icon, schema, onDelete, name, path, description}: {
icon?: React.ReactNode,
schema: RJSFSchema,
name: string,
description?: React.ReactNode,
path: string,
name?: string,
onDelete?: () => void,
collapse?: boolean;
onCollapse?: () => void
Expand Down Expand Up @@ -107,8 +109,8 @@ const renderHeader = ({icon, schema, onDelete, name, path}: {
label={`${schema?.type}${schema?.format ? `: ${schema?.format}` : ''}`}
/>
</Typography>
{schema?.description && (
<Typography variant="caption">{schema?.description}</Typography>
{description && (
<Typography variant="caption">{description}</Typography>
)}
</>
)}
Expand Down Expand Up @@ -156,7 +158,32 @@ SchemaPreview.String = function String({schema, path, data, name}: DataVisualiza
const {dispatch} = useSchema();
return (
<div>
{renderHeader({name, path, schema, icon: <TextSnippet/>, onDelete: () => handleDelete(dispatch, path)})}
{renderHeader({
description: schema.description,
name,
path,
schema,
icon: <TextSnippet/>,
onDelete: () => handleDelete(dispatch, path)
})}
</div>
);
};

SchemaPreview.Enum = function String({schema, path, data, name}: DataVisualizationType) {
const {dispatch} = useSchema();
const enums = schema.enum
return (
<div>
{renderHeader({
description: <>{schema.description} <Typography variant="caption">Options:</Typography> <Box gap={1} display="flex" flexDirection='row'>{enums.map(e => (
<Chip size="small" label={schema?.enumNames[enums.indexOf(e)] || e}/>))}</Box></>,
name,
path,
schema,
icon: <Checklist/>,
onDelete: () => handleDelete(dispatch, path)
})}
</div>
);
};
Expand All @@ -165,7 +192,14 @@ SchemaPreview.Number = function Number({schema, path, name}: DataVisualizationTy
const {dispatch} = useSchema();
return (
<div>
{renderHeader({name, path, schema, icon: <Numbers/>, onDelete: () => handleDelete(dispatch, path)})}
{renderHeader({
description: schema.description,
name,
path,
schema,
icon: <Numbers/>,
onDelete: () => handleDelete(dispatch, path)
})}
</div>
);
};
Expand All @@ -174,7 +208,14 @@ SchemaPreview.Boolean = function BooleanVisualization({schema, path, name}: Data
const {dispatch} = useSchema();
return (
<div>
{renderHeader({name, path, schema, icon: <ToggleOn/>, onDelete: () => handleDelete(dispatch, path)})}
{renderHeader({
description: schema.description,
name,
path,
schema,
icon: <ToggleOn/>,
onDelete: () => handleDelete(dispatch, path)
})}
</div>
);
};
Expand All @@ -192,6 +233,7 @@ SchemaPreview.Object = function ObjectVisualization({schema, path, data, name}:
return (
<Card sx={{p: 2, m: 2}}>
{renderHeader({
description: schema.description,
name,
path,
schema,
Expand Down Expand Up @@ -234,7 +276,14 @@ SchemaPreview.Array = function ArrayVisualization({schema, path, data, name}: Da
return (
<>
<Card sx={{p: 2, m: 2}}>
{renderHeader({name,path, schema, icon: <DataArray/>, onDelete: () => handleDelete(dispatch, path)})}
{renderHeader({
description: schema.description,
name,
path,
schema,
icon: <DataArray/>,
onDelete: () => handleDelete(dispatch, path)
})}
<SchemaPreview
{...{schema: schema.items, name, path: generatePath(path, 'items')}}
/>
Expand Down
7 changes: 7 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {TimeField} from "./fields/widgets/TimeField";
import {DateTimeField} from "./fields/widgets/DateTimeField";
import {FaqWidget} from "./fields/patterns/FaqWidget";
import {FieldConfig} from "./types";
import {SelectField} from "./fields/widgets/SelectField";

export const PRIMITIVE_PROPERTIES: FieldConfig[] = [
{
Expand Down Expand Up @@ -72,6 +73,12 @@ export const STRING_WIDGETS: FieldConfig[] = [
title: 'Time Field',
description: 'a time field',
Class: TimeField,
},
{
id: 'SELECT',
title: 'Select Field',
description: 'a select field with a list of options',
Class: SelectField,
}
];

Expand Down
1 change: 0 additions & 1 deletion src/fields/primitives/NumberField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,5 +97,4 @@ export class NumberField extends JsonSchemaField {
if (schema.exclusiveMaximum) this.setExclusiveMaximum(schema.exclusiveMaximum)
if (schema.exclusiveMinimum) this.setExclusiveMinimum(schema.exclusiveMinimum)
}

}
83 changes: 83 additions & 0 deletions src/fields/widgets/SelectField.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import {StringField, StringFieldType} from "../primitives/StringField";
import {JsonSchema} from "../../types";
import {produce} from "immer";

export type SelectFieldType = StringFieldType & {
options: {
enum: string;
enumNames: string;
}[]
};

export class SelectField extends StringField {
protected enum?: string[];

protected enumNames?: string[];

constructor(name: string) {
super(name);
}

setEnum(_enum: string[]): this {
this.enum = _enum;
return this;
}

setEnumNames(enumNames: string[]): this {
this.enumNames = enumNames;
return this;
}

getBuilderSchema(): JsonSchema {
const enumSchema: Record<string, JsonSchema> = {
options: {
type: "array",
title: "Options",
minItems: 1,
description: "Here you can add options for the select field",
items: {
type: "object",
properties: {
enum: {
type: "string",
title: "Value of the option",
description: "The value that is going to be in the form",
},
enumNames: {
type: "string",
title: "Title of the option",
description: "The title that is going to be shown to user",
},
},
required: ["enum", "enumNames"],
}
}
}

return produce(super.getBuilderSchema(), (draft: JsonSchema) => {
Object.keys(enumSchema).forEach(key => {
if (draft.properties) draft.properties[key] = enumSchema[key];
})
});
}

public getSchema(): JsonSchema {
return {
...super.getSchema(),
enum: this.enum,
enumNames: this.enumNames,
}
}

public setSchema(schema: SelectFieldType): void {
super.setSchema(schema);

const options = {
enum: schema.options?.map((option) => option.enum) || [],
enumNames: schema.options?.map((option) => option.enumNames) || [],
}

if (options.enum?.length > 0) this.setEnum(options.enum)
if (options.enumNames?.length > 0) this.setEnumNames(options.enumNames)
}
}
14 changes: 14 additions & 0 deletions src/stories/SchemaBuilder.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ const sampleSchema: RJSFSchema = {
"type": "string",
"minLength": 1
},
"type": {
"title": "Type",
"description": "The type of the item.",
"type": "string",
enum: ['grocery', 'cloths'],
enumNames: ['Grocery', 'Cloths'],
},
"price": {
"title": "Price",
"description": "The price of the item.",
Expand Down Expand Up @@ -124,6 +131,13 @@ Themed.args = {
main: '#ff5722'
},
mode: 'dark'
},
components: {
MuiInput: {
defaultProps: {
size: 'small'
}
}
}
}
};
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export interface SchemaAnnotation {
default?: unknown;
readOnly?: boolean;
writeOnly?: boolean;
enum?: unknown[];
enum?: string[]; // TODO: Generalize enum values
enumNames?: string[];
}

Expand Down
2 changes: 1 addition & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const getSchemaFormatFromSchema = (
// if (schema?.type === 'string' && schema?.ui?.widget === 'color') return SchemaFormat.Color;
// if (schema?.format === 'date') return SchemaFormat.Date;
// if (schema?.format === 'date-time') return SchemaFormat.DateTime;
// if (schema?.type === 'string' && schema?.enum?.length > 0) return SchemaFormat.Enum;
if (schema?.type === 'string' && schema?.enum?.length > 0) return SchemaFormat.Enum;
if (schema?.type === 'string') return SchemaFormat.String;
if (schema?.type === 'number' || schema?.type === 'integer') return SchemaFormat.Number;
if (schema?.type === 'object' && schema?.format === 'map') return SchemaFormat.Map;
Expand Down

0 comments on commit cb95c4a

Please sign in to comment.