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 cb95c4a commit 1706d07
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 39 deletions.
15 changes: 13 additions & 2 deletions src/components/AddFieldModal.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
import {Box, Button, Dialog, FormControl, IconButton, InputLabel, MenuItem, Stack, TextField,} from "@mui/material";
import {
Box,
Button,
Dialog,
FormControl,
IconButton,
InputLabel,
MenuItem,
Stack,
TextField,
Tooltip,
} from "@mui/material";
import Form from "@rjsf/mui";

import validator from "@rjsf/validator-ajv8";
Expand Down Expand Up @@ -61,7 +72,7 @@ const AddFieldModal = ({ parentPath }) => {

return (
<>
<IconButton onClick={() => setOpen(true)}><Add /></IconButton>
<Tooltip title="Add Property" arrow placement="left"><IconButton onClick={() => setOpen(true)}><Add /></IconButton></Tooltip>
<Dialog fullWidth open={open} onClose={() => setOpen(false)}>
<Box p={3} key={JSON.stringify(fields)}>
<h1>{step !== 0 && <Button onClick={() => setStep(0)}>back</Button>}Adding Field</h1>
Expand Down
9 changes: 9 additions & 0 deletions src/components/FieldPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,15 @@ FieldPreview.String = function String({schema, data, name}: DataVisualizationTyp
);
};

FieldPreview.Enum = function Enum({schema, data, name}: DataVisualizationType) {
return (
<TableRow>
<TableCell>{schema?.title}</TableCell>
<TableCell>{data || '-'}</TableCell>
</TableRow>
);
};

FieldPreview.Number = function Number({schema, name, data}: DataVisualizationType) {
return (
<TableRow>
Expand Down
71 changes: 37 additions & 34 deletions src/components/SchemaPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ import {
IconButton,
ListItem,
ListItemIcon,
ListItemText, Stack,
ListItemText, Paper, Stack,
Tooltip,
Typography
Typography, useTheme
} from "@mui/material";
import {generatePath, getFieldId, getSchemaFormatFromSchema} from "../utils";
import {DataVisualizationType} from "../types";
Expand Down Expand Up @@ -148,16 +148,14 @@ const handleEdit = (dispatch: React.Dispatch<SchemaAction>, name: string, schema
const SchemaPreview = ({schema, data, name, path}: Props) => {
const FormPreview = getSchemaFormatFromSchema(schema, SchemaPreview)
return (
<div>
<FormPreview {...{schema, data, name, path}} />
</div>
)
};

SchemaPreview.String = function String({schema, path, data, name}: DataVisualizationType) {
const {dispatch} = useSchema();
return (
<div>
<Paper>
{renderHeader({
description: schema.description,
name,
Expand All @@ -166,15 +164,15 @@ SchemaPreview.String = function String({schema, path, data, name}: DataVisualiza
icon: <TextSnippet/>,
onDelete: () => handleDelete(dispatch, path)
})}
</div>
</Paper>
);
};

SchemaPreview.Enum = function String({schema, path, data, name}: DataVisualizationType) {
SchemaPreview.Enum = function Enum({schema, path, data, name}: DataVisualizationType) {
const {dispatch} = useSchema();
const enums = schema.enum
return (
<div>
<Paper>
{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></>,
Expand All @@ -184,14 +182,14 @@ SchemaPreview.Enum = function String({schema, path, data, name}: DataVisualizati
icon: <Checklist/>,
onDelete: () => handleDelete(dispatch, path)
})}
</div>
</Paper>
);
};

SchemaPreview.Number = function Number({schema, path, name}: DataVisualizationType) {
const {dispatch} = useSchema();
return (
<div>
<Paper>
{renderHeader({
description: schema.description,
name,
Expand All @@ -200,14 +198,14 @@ SchemaPreview.Number = function Number({schema, path, name}: DataVisualizationTy
icon: <Numbers/>,
onDelete: () => handleDelete(dispatch, path)
})}
</div>
</Paper>
);
};

SchemaPreview.Boolean = function BooleanVisualization({schema, path, name}: DataVisualizationType) {
const {dispatch} = useSchema();
return (
<div>
<Paper>
{renderHeader({
description: schema.description,
name,
Expand All @@ -216,7 +214,7 @@ SchemaPreview.Boolean = function BooleanVisualization({schema, path, name}: Data
icon: <ToggleOn/>,
onDelete: () => handleDelete(dispatch, path)
})}
</div>
</Paper>
);
};

Expand All @@ -230,8 +228,10 @@ SchemaPreview.Object = function ObjectVisualization({schema, path, data, name}:
setOpen(!open);
};

const theme = useTheme();

return (
<Card sx={{p: 2, m: 2}}>
<Paper>
{renderHeader({
description: schema.description,
name,
Expand All @@ -242,7 +242,7 @@ SchemaPreview.Object = function ObjectVisualization({schema, path, data, name}:
onCollapse: handleCollapse,
onDelete: () => handleDelete(dispatch, path)
})}
<Card sx={{p: 2, m: 2}}>
<Paper sx={{ p: 1 }}>
<Box
px={2} display="flex" justifyContent="space-between">
<Typography flex={1}>Properties</Typography>
Expand All @@ -252,30 +252,32 @@ SchemaPreview.Object = function ObjectVisualization({schema, path, data, name}:
<ExpandLess fontSize="small"/>}</IconButton>}
</Box>
<Collapse in={open} timeout="auto" unmountOnExit>
{properties?.length > 0 ? properties?.map((property) => (
<>
<SchemaPreview
name={property}
schema={schema.properties[property]}
path={generatePath(path, generatePath('properties', property))}
/>
</>
)) : (
<Typography alignItems="center" textAlign="center" p={3}>
Click on <Add fontSize="small"/> button to add properties
</Typography>
)}
<Stack gap={2}>
{properties?.length > 0 ? properties?.map((property) => (
<>
<SchemaPreview
name={property}
schema={schema.properties[property]}
path={generatePath(path, generatePath('properties', property))}
/>
</>
)) : (
<Typography alignItems="center" textAlign="center" p={3}>
Click on <Add fontSize="small"/> button to add properties
</Typography>
)}
</Stack>
</Collapse>
</Card>
</Card>
</Paper>
</Paper>
);
};

SchemaPreview.Array = function ArrayVisualization({schema, path, data, name}: DataVisualizationType) {
const {dispatch} = useSchema();
const theme = useTheme();
return (
<>
<Card sx={{p: 2, m: 2}}>
<Paper sx={{ p: 1 }}>
{renderHeader({
description: schema.description,
name,
Expand All @@ -284,11 +286,12 @@ SchemaPreview.Array = function ArrayVisualization({schema, path, data, name}: Da
icon: <DataArray/>,
onDelete: () => handleDelete(dispatch, path)
})}
<Box>
<SchemaPreview
{...{schema: schema.items, name, path: generatePath(path, 'items')}}
/>
</Card>
</>
</Box>
</Paper>
);
};

Expand Down
55 changes: 53 additions & 2 deletions src/fields/JsonSchemaField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ export class JsonSchemaField {

protected writeOnly?: boolean;

protected enum?: string[];

protected enumNames?: string[];


constructor(name: string) {
this.name = name;
this.type = 'object';
Expand Down Expand Up @@ -46,6 +51,16 @@ export class JsonSchemaField {
return this;
}

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

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

private setDefault(value: unknown): JsonSchemaField {
this.default = value;
return this;
Expand All @@ -66,14 +81,27 @@ export class JsonSchemaField {
return this;
}

public setSchema(schema: SchemaAnnotation & { isRequired?: boolean }): void {
public setSchema(schema: SchemaAnnotation & {
isRequired?: boolean, options: {
enum: string;
enumNames: string;
}[]
}): void {
if (schema.type) this.setType(schema.type)
if (schema.title) this.setTitle(schema.title)
if (schema.description) this.setDescription(schema.description)
if (schema.default) this.setDefault(schema.default)
if (schema.readOnly) this.setReadOnly(schema.readOnly)
if (schema.writeOnly) this.setWriteOnly(schema.writeOnly)
if (schema.isRequired) this.setIsRequired(schema.isRequired)

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)
}


Expand All @@ -84,7 +112,9 @@ export class JsonSchemaField {
description: this.description,
default: this.default,
readOnly: this.readOnly,
writeOnly: this.writeOnly
writeOnly: this.writeOnly,
enum: this.enum,
enumNames: this.enumNames
};

}
Expand Down Expand Up @@ -121,6 +151,27 @@ export class JsonSchemaField {
isRequired: {
type: 'boolean',
title: 'Field is required'
},
options: {
type: "array",
title: "Options",
description: "Here you can add options for the select field",
items: {
type: "object",
properties: {
enum: {
type: this.getSchema()?.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"],
}
}
},
required: ['title', 'type'],
Expand Down
15 changes: 15 additions & 0 deletions src/stories/SchemaBuilder.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,21 @@ const sampleSchema: RJSFSchema = {
"type": "number",
"minimum": 0
},
"location": {
"title": "Location",
"description": "The coordination.",
"type": "object",
properties: {
lat: {
type: 'number',
title: "latitude"
},
long: {
type: 'number',
title: "longitude"
},
}
},
"tags": {
"title": "Tags",
"description": "Tags associated with the item.",
Expand Down
2 changes: 1 addition & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const getSchemaFormatFromSchema = (
Unknown({schema, data}: DataVisualizationType): JSX.Element;
},
) => {
if (schema?.enum?.length > 0) return SchemaFormat.Enum;
if (schema?.type === 'boolean') return SchemaFormat.Boolean;
// if (schema?.type === 'string' && schema?.format === 'image-url') return SchemaFormat.Image;
// if (schema?.type === 'string' && schema?.format === 'video-url') return SchemaFormat.Video;
Expand All @@ -30,7 +31,6 @@ 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') 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 1706d07

Please sign in to comment.