Skip to content

Commit

Permalink
Merge pull request #78 from Exabyte-io/fix/SOF-7428
Browse files Browse the repository at this point in the history
SOF-7428: ObjectFieldTemplate RJSF
  • Loading branch information
k0stik authored Aug 8, 2024
2 parents bebbfa1 + b9f8c4b commit 63e7723
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 71 deletions.
12 changes: 1 addition & 11 deletions dist/mui/components/accordion/Accordion.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,6 @@ import { withStyles } from "@mui/styles";
import React, { useEffect, useState } from "react";
import IconByName from "../icon/IconByName";
// deletes header animation in accordion
const StyledAccordion = withStyles({
root: {
margin: "0",
"&$expanded": {
margin: "0",
},
},
expanded: {},
})(MuiAccordion);
// deletes header animation in accordion
const AccordionSummary = withStyles({
root: {
minHeight: "48px",
Expand Down Expand Up @@ -50,7 +40,7 @@ export default function Accordion({ hideExpandIcon, children, isExpanded, header
setIsExpanded((prev) => !prev);
}
};
return (React.createElement(StyledAccordion, { defaultExpanded: isExpanded, expanded: isExpanded_, ...restProps },
return (React.createElement(MuiAccordion, { defaultExpanded: isExpanded, expanded: isExpanded_, ...restProps },
React.createElement(AccordionSummary, { onClick: handleToggleExpanded, "aria-controls": "panel2a-content", expandIcon: !hideExpandIcon && React.createElement(IconByName, { name: "actions.expand" }) }, renderSummary || React.createElement(Typography, { variant: "overline" }, header)),
React.createElement(Divider, null),
React.createElement(AccordionDetails, null, children)));
Expand Down
3 changes: 2 additions & 1 deletion dist/mui/components/dialog/Dialog.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export interface DialogModalProps extends DialogProps {
id?: string;
titleComponent?: string | React.ReactNode;
open: boolean;
scrollable?: boolean;
onSubmit?: (() => void) | undefined;
onClose?: (() => void) | undefined;
onCancel?: (() => void) | undefined;
Expand All @@ -23,5 +24,5 @@ export interface DialogModalProps extends DialogProps {
cancelButtonProps?: ButtonProps;
draggableId?: string;
}
declare function DialogModal({ id, title, titleComponent, open, scroll, onSubmit, onCancel, onClose, children, maxWidth, dividers, fullWidth, isSubmitButtonDisabled, isSubmitButtonProcessing, isSubmitOnEnter, renderHeaderCustom, renderBodyCustom, renderFooterCustom, submitButtonText, cancelButtonText, submitButtonProps, cancelButtonProps, PaperComponent, draggableId, ...originalProps }: DialogModalProps): React.JSX.Element;
declare function DialogModal({ id, title, titleComponent, open, scrollable, scroll, onSubmit, onCancel, onClose, children, maxWidth, dividers, fullWidth, isSubmitButtonDisabled, isSubmitButtonProcessing, isSubmitOnEnter, renderHeaderCustom, renderBodyCustom, renderFooterCustom, submitButtonText, cancelButtonText, submitButtonProps, cancelButtonProps, PaperComponent, draggableId, ...originalProps }: DialogModalProps): React.JSX.Element;
export default DialogModal;
4 changes: 2 additions & 2 deletions dist/mui/components/dialog/Dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import IconButton from "@mui/material/IconButton";
import Typography from "@mui/material/Typography";
import React, { useCallback } from "react";
import IconByName from "../icon/IconByName";
function DialogModal({ id = "modal-dialog", title, titleComponent, open, scroll = "paper", onSubmit = undefined, onCancel, onClose, children, maxWidth = "sm", dividers = true, fullWidth = true, isSubmitButtonDisabled = false, isSubmitButtonProcessing = false, isSubmitOnEnter = false, renderHeaderCustom, renderBodyCustom, renderFooterCustom, submitButtonText = "Submit", cancelButtonText = "Cancel", submitButtonProps, cancelButtonProps, PaperComponent, draggableId, ...originalProps }) {
function DialogModal({ id = "modal-dialog", title, titleComponent, open, scrollable, scroll = "paper", onSubmit = undefined, onCancel, onClose, children, maxWidth = "sm", dividers = true, fullWidth = true, isSubmitButtonDisabled = false, isSubmitButtonProcessing = false, isSubmitOnEnter = false, renderHeaderCustom, renderBodyCustom, renderFooterCustom, submitButtonText = "Submit", cancelButtonText = "Cancel", submitButtonProps, cancelButtonProps, PaperComponent, draggableId, ...originalProps }) {
const handleSubmit = () => {
if (onSubmit)
onSubmit();
Expand Down Expand Up @@ -38,7 +38,7 @@ function DialogModal({ id = "modal-dialog", title, titleComponent, open, scroll
return (React.createElement(DialogContent, { sx: {
display: "flex",
flexDirection: "column",
overflow: "hidden",
overflow: scrollable ? "auto" : "hidden",
}, dividers: dividers }, children));
};
const renderFooterDefault = () => {
Expand Down
39 changes: 25 additions & 14 deletions dist/other/rjsf/templates/ObjectFieldTemplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,41 @@
/* eslint-disable react/no-array-index-key */
import Box from "@mui/material/Box";
import Grid from "@mui/material/Grid";
import { canExpand, descriptionId, getTemplate, getUiOptions, titleId, } from "@rjsf/utils";
import { canExpand, descriptionId, getTemplate, getUiOptions, } from "@rjsf/utils";
import React from "react";
function isNumeric(str) {
return (!Number.isNaN(str) && // use type coercion to parse the _entirety_ of the string (`parseFloat` alone does not do this)...
!Number.isNaN(parseFloat(str)) // ...and ensure strings of whitespace fail
);
function schemaHasInnerObjects(schema) {
return Object.values(schema.properties || {}).some((innerSchema) => {
if (typeof innerSchema === "object" && typeof innerSchema.items === "boolean") {
return false;
}
if (typeof innerSchema === "object" && Array.isArray(innerSchema.items)) {
return innerSchema.items.some((item) => typeof item === "object" && Boolean(item.properties));
}
if (typeof innerSchema === "object" &&
typeof innerSchema.items === "object" &&
!Array.isArray(innerSchema.items)) {
return Boolean(innerSchema.items.properties);
}
return typeof innerSchema === "object" && Boolean(innerSchema.properties);
});
}
export default function ObjectFieldTemplate(props) {
const { description, title, properties, required, disabled, readonly, uiSchema, idSchema, schema, formData, onAddClick, registry, } = props;
const { description, properties, disabled, readonly, uiSchema, idSchema, schema, formData, onAddClick, registry, } = props;
const uiOptions = getUiOptions(uiSchema);
const TitleFieldTemplate = getTemplate("TitleFieldTemplate", registry, uiOptions);
const DescriptionFieldTemplate = getTemplate("DescriptionFieldTemplate", registry, uiOptions);
// Button templates are not overridden in the uiSchema
const { ButtonTemplates: { AddButton }, } = registry.templates;
const hasInnerObjects = schemaHasInnerObjects(schema);
return (React.createElement(Box, { className: "ObjectFieldTemplate" },
title && !isNumeric(title) && (React.createElement(TitleFieldTemplate, { id: titleId(idSchema), title: title, required: required, schema: schema, uiSchema: uiSchema, registry: registry })),
description && (React.createElement(DescriptionFieldTemplate, { id: descriptionId(idSchema), description: description, schema: schema, uiSchema: uiSchema, registry: registry })),
React.createElement(Grid, { container: true, spacing: 2 },
properties.map((element, index) =>
// Remove the <Grid> if the inner element is hidden as the <Grid>
// itself would otherwise still take up space.
element.hidden ? (element.content) : (React.createElement(Grid, { item: true, xs: 12, sm: 4,
// md={4}
key: index, style: { marginBottom: "10px" } }, element.content))),
properties.map((element, index) => {
// Remove the <Grid> if the inner element is hidden as the <Grid>
// itself would otherwise still take up space.
return element.hidden ? (element.content) : (React.createElement(Grid, { item: true, xs: 12, sm: hasInnerObjects ? 12 : 4,
// md={4}
key: index, style: { marginBottom: "10px" } }, element.content));
}),
canExpand(schema, uiSchema, formData) && (React.createElement(Grid, { container: true, justifyContent: "flex-end" },
React.createElement(Grid, { item: true },
React.createElement(AddButton, { className: "object-property-expand", onClick: onAddClick(schema), disabled: disabled || readonly, uiSchema: uiSchema, registry: registry })))))));
Expand Down
15 changes: 2 additions & 13 deletions src/mui/components/accordion/Accordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,6 @@ import React, { SyntheticEvent, useEffect, useState } from "react";

import IconByName from "../icon/IconByName";

// deletes header animation in accordion
const StyledAccordion = withStyles({
root: {
margin: "0",
"&$expanded": {
margin: "0",
},
},
expanded: {},
})(MuiAccordion);

// deletes header animation in accordion
const AccordionSummary = withStyles({
root: {
Expand Down Expand Up @@ -73,7 +62,7 @@ export default function Accordion({
};

return (
<StyledAccordion defaultExpanded={isExpanded} expanded={isExpanded_} {...restProps}>
<MuiAccordion defaultExpanded={isExpanded} expanded={isExpanded_} {...restProps}>
<AccordionSummary
onClick={handleToggleExpanded}
aria-controls="panel2a-content"
Expand All @@ -82,6 +71,6 @@ export default function Accordion({
</AccordionSummary>
<Divider />
<AccordionDetails>{children}</AccordionDetails>
</StyledAccordion>
</MuiAccordion>
);
}
4 changes: 3 additions & 1 deletion src/mui/components/dialog/Dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface DialogModalProps extends DialogProps {
id?: string;
titleComponent?: string | React.ReactNode;
open: boolean;
scrollable?: boolean;
onSubmit?: (() => void) | undefined;
onClose?: (() => void) | undefined;
onCancel?: (() => void) | undefined;
Expand All @@ -40,6 +41,7 @@ function DialogModal({
title,
titleComponent,
open,
scrollable,
scroll = "paper",
onSubmit = undefined,
onCancel,
Expand Down Expand Up @@ -105,7 +107,7 @@ function DialogModal({
sx={{
display: "flex",
flexDirection: "column",
overflow: "hidden",
overflow: scrollable ? "auto" : "hidden",
}}
dividers={dividers}>
{children}
Expand Down
58 changes: 29 additions & 29 deletions src/other/rjsf/templates/ObjectFieldTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,31 @@ import {
ObjectFieldTemplateProps,
RJSFSchema,
StrictRJSFSchema,
titleId,
} from "@rjsf/utils";
import React from "react";

function isNumeric(str: string) {
return (
!Number.isNaN(str) && // use type coercion to parse the _entirety_ of the string (`parseFloat` alone does not do this)...
!Number.isNaN(parseFloat(str)) // ...and ensure strings of whitespace fail
);
function schemaHasInnerObjects(schema: StrictRJSFSchema): boolean {
return Object.values(schema.properties || {}).some((innerSchema) => {
if (typeof innerSchema === "object" && typeof innerSchema.items === "boolean") {
return false;
}

if (typeof innerSchema === "object" && Array.isArray(innerSchema.items)) {
return innerSchema.items.some(
(item) => typeof item === "object" && Boolean(item.properties),
);
}

if (
typeof innerSchema === "object" &&
typeof innerSchema.items === "object" &&
!Array.isArray(innerSchema.items)
) {
return Boolean(innerSchema.items.properties);
}

return typeof innerSchema === "object" && Boolean(innerSchema.properties);
});
}

export default function ObjectFieldTemplate<
Expand All @@ -29,9 +45,7 @@ export default function ObjectFieldTemplate<
>(props: ObjectFieldTemplateProps<T, S, F>) {
const {
description,
title,
properties,
required,
disabled,
readonly,
uiSchema,
Expand All @@ -44,12 +58,6 @@ export default function ObjectFieldTemplate<

const uiOptions = getUiOptions<T, S, F>(uiSchema);

const TitleFieldTemplate = getTemplate<"TitleFieldTemplate", T, S, F>(
"TitleFieldTemplate",
registry,
uiOptions,
);

const DescriptionFieldTemplate = getTemplate<"DescriptionFieldTemplate", T, S, F>(
"DescriptionFieldTemplate",
registry,
Expand All @@ -61,18 +69,10 @@ export default function ObjectFieldTemplate<
ButtonTemplates: { AddButton },
} = registry.templates;

const hasInnerObjects = schemaHasInnerObjects(schema);

return (
<Box className="ObjectFieldTemplate">
{title && !isNumeric(title) && (
<TitleFieldTemplate
id={titleId<T>(idSchema)}
title={title}
required={required}
schema={schema}
uiSchema={uiSchema}
registry={registry}
/>
)}
{description && (
<DescriptionFieldTemplate
id={descriptionId<T>(idSchema)}
Expand All @@ -83,23 +83,23 @@ export default function ObjectFieldTemplate<
/>
)}
<Grid container spacing={2}>
{properties.map((element, index) =>
{properties.map((element, index) => {
// Remove the <Grid> if the inner element is hidden as the <Grid>
// itself would otherwise still take up space.
element.hidden ? (
return element.hidden ? (
element.content
) : (
<Grid
item
xs={12}
sm={4}
sm={hasInnerObjects ? 12 : 4}
// md={4}
key={index}
style={{ marginBottom: "10px" }}>
{element.content}
</Grid>
),
)}
);
})}
{canExpand<T, S, F>(schema, uiSchema, formData) && (
<Grid container justifyContent="flex-end">
<Grid item>
Expand Down

0 comments on commit 63e7723

Please sign in to comment.