From fcd179d95aae45b2fd9f48437805d10981ab7393 Mon Sep 17 00:00:00 2001 From: Oleksii Husakov Date: Mon, 4 Sep 2023 17:09:48 +0300 Subject: [PATCH 1/5] chore: add more rjsf widgets --- package-lock.json | 5 ++ package.json | 1 + src/other/rjsf/CustomObjectFieldTemplate.tsx | 1 - src/other/rjsf/InputWithInfoPopover.tsx | 43 +++++++++++++++ src/other/rjsf/SelectWithInfoPopover.tsx | 42 +++++++++++++++ src/other/rjsf/TimePicker.tsx | 55 ++++++++++++++++++++ 6 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 src/other/rjsf/InputWithInfoPopover.tsx create mode 100644 src/other/rjsf/SelectWithInfoPopover.tsx create mode 100644 src/other/rjsf/TimePicker.tsx diff --git a/package-lock.json b/package-lock.json index 676880c2..0826dacd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1198,6 +1198,11 @@ "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", "dev": true }, + "@rjsf/mui": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/@rjsf/mui/-/mui-5.12.1.tgz", + "integrity": "sha512-d7cNFIdt6N24m5NPrNSqfCe2SUyUjX48Goo7z4J9vOHWxo5kdDfBEa3UwNA/DR9lo+9cYY7QTvKbgrTkxWU58A==" + }, "@rjsf/utils": { "version": "5.12.1", "resolved": "https://registry.npmjs.org/@rjsf/utils/-/utils-5.12.1.tgz", diff --git a/package.json b/package.json index 4cf2f8ad..8f1a1c12 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "@codemirror/legacy-modes": "^6.3.1", "@codemirror/lint": "^6.2.0", "@mui/x-date-pickers": "6.11.1", + "@rjsf/mui": "^5.12.1", "@rjsf/utils": "^5.1.0", "@toast-ui/editor": "^3.2.2", "@toast-ui/editor-plugin-code-syntax-highlight": "^3.1.0", diff --git a/src/other/rjsf/CustomObjectFieldTemplate.tsx b/src/other/rjsf/CustomObjectFieldTemplate.tsx index 186582ad..74e3a7fc 100644 --- a/src/other/rjsf/CustomObjectFieldTemplate.tsx +++ b/src/other/rjsf/CustomObjectFieldTemplate.tsx @@ -89,7 +89,6 @@ function ObjectFieldTemplate< sm={6} md={4} lg={3} - xl={2} key={index} rowSpacing={theme.spacing(1.25)}> {element.content} diff --git a/src/other/rjsf/InputWithInfoPopover.tsx b/src/other/rjsf/InputWithInfoPopover.tsx new file mode 100644 index 00000000..e4761ec2 --- /dev/null +++ b/src/other/rjsf/InputWithInfoPopover.tsx @@ -0,0 +1,43 @@ +/* eslint-disable react/jsx-props-no-spreading */ +import Box from "@mui/material/Box"; +import Typography from "@mui/material/Typography"; +import { Templates } from "@rjsf/mui"; +import { WidgetProps } from "@rjsf/utils"; +import React from "react"; + +import InfoPopover, { + InfoPopoverProps, +} from "../../mui/components/popover/info-popover/InfoPopover"; + +const { BaseInputTemplate } = Templates; + +type InfoPopoverOptions = InfoPopoverProps & { content: string }; + +export default function InputWithInfoPopover(props: WidgetProps) { + const { uiSchema } = props; + const infoPopover = (uiSchema ? uiSchema["ui:options"]?.infoPopover : {}) as InfoPopoverOptions; + + if (!BaseInputTemplate) return null; + + return ( + <> + + + + + + + + ); +} diff --git a/src/other/rjsf/SelectWithInfoPopover.tsx b/src/other/rjsf/SelectWithInfoPopover.tsx new file mode 100644 index 00000000..2b7fba36 --- /dev/null +++ b/src/other/rjsf/SelectWithInfoPopover.tsx @@ -0,0 +1,42 @@ +/* eslint-disable react/jsx-props-no-spreading */ +import Box from "@mui/material/Box"; +import Typography from "@mui/material/Typography"; +import { Widgets } from "@rjsf/mui"; +import { WidgetProps } from "@rjsf/utils"; +import React from "react"; + +import InfoPopover, { + InfoPopoverProps, +} from "../../mui/components/popover/info-popover/InfoPopover"; + +const { SelectWidget } = Widgets; + +type InfoPopoverOptions = InfoPopoverProps & { content: string }; + +export default function SelectWithInfoPopover(props: WidgetProps) { + const { uiSchema } = props; + + const infoPopover = (uiSchema ? uiSchema["ui:options"]?.infoPopover : {}) as InfoPopoverOptions; + + return ( + <> + + + + + + + + ); +} diff --git a/src/other/rjsf/TimePicker.tsx b/src/other/rjsf/TimePicker.tsx new file mode 100644 index 00000000..c6bd128e --- /dev/null +++ b/src/other/rjsf/TimePicker.tsx @@ -0,0 +1,55 @@ +import Box from "@mui/material/Box"; +import Typography from "@mui/material/Typography"; +import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment"; +import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; +import { TimePicker as MuiTimePicker } from "@mui/x-date-pickers/TimePicker"; +import { WidgetProps } from "@rjsf/utils"; +import moment from "moment"; +import React from "react"; + +import InfoPopover, { + InfoPopoverProps, +} from "../../mui/components/popover/info-popover/InfoPopover"; + +type InfoPopoverOptions = InfoPopoverProps & { content: string }; + +export default function TimePicker(props: WidgetProps) { + const { onChange, value, label } = props; + const { uiSchema, options } = props; + const infoPopover = (uiSchema ? uiSchema["ui:options"]?.infoPopover : {}) as InfoPopoverOptions; + + return ( + + onChange(timeObj?.format("hh:mm:ss"))} + views={["hours", "minutes", "seconds"]} + format="hh:mm:ss" + ampm={false} + value={moment("1970-01-01 " + value)} + label={label} + disabled={options.disabled} + slotProps={{ + textField: { + size: "small", + }, + }} + /> + + + + + + + ); +} From 81d962a48dee398c6891855f8e7e1e7bb31bc211 Mon Sep 17 00:00:00 2001 From: Oleksii Husakov Date: Mon, 4 Sep 2023 17:23:23 +0300 Subject: [PATCH 2/5] chore: add PositionInfoPopover.styled --- src/other/rjsf/InputWithInfoPopover.tsx | 13 +++---------- src/other/rjsf/PositionInfoPopover.styled.ts | 10 ++++++++++ src/other/rjsf/SelectWithInfoPopover.tsx | 13 +++---------- src/other/rjsf/TimePicker.tsx | 13 +++---------- 4 files changed, 19 insertions(+), 30 deletions(-) create mode 100644 src/other/rjsf/PositionInfoPopover.styled.ts diff --git a/src/other/rjsf/InputWithInfoPopover.tsx b/src/other/rjsf/InputWithInfoPopover.tsx index e4761ec2..95678650 100644 --- a/src/other/rjsf/InputWithInfoPopover.tsx +++ b/src/other/rjsf/InputWithInfoPopover.tsx @@ -1,5 +1,4 @@ /* eslint-disable react/jsx-props-no-spreading */ -import Box from "@mui/material/Box"; import Typography from "@mui/material/Typography"; import { Templates } from "@rjsf/mui"; import { WidgetProps } from "@rjsf/utils"; @@ -8,6 +7,7 @@ import React from "react"; import InfoPopover, { InfoPopoverProps, } from "../../mui/components/popover/info-popover/InfoPopover"; +import { PositionInfoPopover } from "./PositionInfoPopover.styled"; const { BaseInputTemplate } = Templates; @@ -22,14 +22,7 @@ export default function InputWithInfoPopover(props: WidgetProps) { return ( <> - + - + ); } diff --git a/src/other/rjsf/PositionInfoPopover.styled.ts b/src/other/rjsf/PositionInfoPopover.styled.ts new file mode 100644 index 00000000..14ed2a53 --- /dev/null +++ b/src/other/rjsf/PositionInfoPopover.styled.ts @@ -0,0 +1,10 @@ +import Box from "@mui/material/Box"; +import { styled } from "@mui/material/styles"; + +export const PositionInfoPopover = styled(Box)({ + backgroundColor: "background.paper", + position: "absolute", + borderRadius: "50%", + right: -14, + top: -14, +}); diff --git a/src/other/rjsf/SelectWithInfoPopover.tsx b/src/other/rjsf/SelectWithInfoPopover.tsx index 2b7fba36..ac3ca3ab 100644 --- a/src/other/rjsf/SelectWithInfoPopover.tsx +++ b/src/other/rjsf/SelectWithInfoPopover.tsx @@ -1,5 +1,4 @@ /* eslint-disable react/jsx-props-no-spreading */ -import Box from "@mui/material/Box"; import Typography from "@mui/material/Typography"; import { Widgets } from "@rjsf/mui"; import { WidgetProps } from "@rjsf/utils"; @@ -8,6 +7,7 @@ import React from "react"; import InfoPopover, { InfoPopoverProps, } from "../../mui/components/popover/info-popover/InfoPopover"; +import { PositionInfoPopover } from "./PositionInfoPopover.styled"; const { SelectWidget } = Widgets; @@ -21,14 +21,7 @@ export default function SelectWithInfoPopover(props: WidgetProps) { return ( <> - + - + ); } diff --git a/src/other/rjsf/TimePicker.tsx b/src/other/rjsf/TimePicker.tsx index c6bd128e..22f59868 100644 --- a/src/other/rjsf/TimePicker.tsx +++ b/src/other/rjsf/TimePicker.tsx @@ -1,4 +1,3 @@ -import Box from "@mui/material/Box"; import Typography from "@mui/material/Typography"; import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment"; import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; @@ -10,6 +9,7 @@ import React from "react"; import InfoPopover, { InfoPopoverProps, } from "../../mui/components/popover/info-popover/InfoPopover"; +import { PositionInfoPopover } from "./PositionInfoPopover.styled"; type InfoPopoverOptions = InfoPopoverProps & { content: string }; @@ -34,14 +34,7 @@ export default function TimePicker(props: WidgetProps) { }, }} /> - + ) { dangerouslySetInnerHTML={{ __html: infoPopover?.content }} /> - + ); } From aa3795d1748edb5030f74e66ab2b648236a07531 Mon Sep 17 00:00:00 2001 From: Oleksii Husakov Date: Tue, 5 Sep 2023 18:26:22 +0300 Subject: [PATCH 3/5] chore: fix time picker format, minor ui changes --- src/other/rjsf/PositionInfoPopover.styled.ts | 6 +++--- src/other/rjsf/TimePicker.tsx | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/other/rjsf/PositionInfoPopover.styled.ts b/src/other/rjsf/PositionInfoPopover.styled.ts index 14ed2a53..c634ca9e 100644 --- a/src/other/rjsf/PositionInfoPopover.styled.ts +++ b/src/other/rjsf/PositionInfoPopover.styled.ts @@ -1,10 +1,10 @@ import Box from "@mui/material/Box"; import { styled } from "@mui/material/styles"; -export const PositionInfoPopover = styled(Box)({ - backgroundColor: "background.paper", +export const PositionInfoPopover = styled(Box)(({ theme }) => ({ + backgroundColor: theme.palette.background.paper, position: "absolute", borderRadius: "50%", right: -14, top: -14, -}); +})); diff --git a/src/other/rjsf/TimePicker.tsx b/src/other/rjsf/TimePicker.tsx index 22f59868..fa6db620 100644 --- a/src/other/rjsf/TimePicker.tsx +++ b/src/other/rjsf/TimePicker.tsx @@ -21,9 +21,9 @@ export default function TimePicker(props: WidgetProps) { return ( onChange(timeObj?.format("hh:mm:ss"))} + onChange={(timeObj) => onChange(timeObj?.format("HH:mm:ss"))} views={["hours", "minutes", "seconds"]} - format="hh:mm:ss" + format="HH:mm:ss" ampm={false} value={moment("1970-01-01 " + value)} label={label} @@ -31,6 +31,7 @@ export default function TimePicker(props: WidgetProps) { slotProps={{ textField: { size: "small", + className: "timePickerInput", }, }} /> From d8a45c0077d060b8b46d73806d56f75c9d86a94f Mon Sep 17 00:00:00 2001 From: Oleksii Husakov Date: Wed, 6 Sep 2023 17:26:19 +0300 Subject: [PATCH 4/5] chire: adjust grid in CustomObjectFieldTemplate --- src/other/rjsf/CustomObjectFieldTemplate.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/other/rjsf/CustomObjectFieldTemplate.tsx b/src/other/rjsf/CustomObjectFieldTemplate.tsx index 74e3a7fc..186582ad 100644 --- a/src/other/rjsf/CustomObjectFieldTemplate.tsx +++ b/src/other/rjsf/CustomObjectFieldTemplate.tsx @@ -89,6 +89,7 @@ function ObjectFieldTemplate< sm={6} md={4} lg={3} + xl={2} key={index} rowSpacing={theme.spacing(1.25)}> {element.content} From eb3e14ab08a6ec190a7d9191933af71af410e8fb Mon Sep 17 00:00:00 2001 From: Oleksii Husakov Date: Thu, 7 Sep 2023 15:33:26 +0300 Subject: [PATCH 5/5] chore: split rjsf files in folders, update widget types --- .../CustomObjectFieldTemplate.tsx | 0 .../rjsf/{ => widgets}/InputWithInfoPopover.tsx | 16 ++++++---------- .../{ => widgets}/PositionInfoPopover.styled.ts | 0 .../{ => widgets}/SelectWithInfoPopover.tsx | 17 ++++++----------- src/other/rjsf/{ => widgets}/TimePicker.tsx | 16 ++++++---------- src/other/rjsf/widgets/types.ts | 13 +++++++++++++ 6 files changed, 31 insertions(+), 31 deletions(-) rename src/other/rjsf/{ => templates}/CustomObjectFieldTemplate.tsx (100%) rename src/other/rjsf/{ => widgets}/InputWithInfoPopover.tsx (64%) rename src/other/rjsf/{ => widgets}/PositionInfoPopover.styled.ts (100%) rename src/other/rjsf/{ => widgets}/SelectWithInfoPopover.tsx (62%) rename src/other/rjsf/{ => widgets}/TimePicker.tsx (76%) create mode 100644 src/other/rjsf/widgets/types.ts diff --git a/src/other/rjsf/CustomObjectFieldTemplate.tsx b/src/other/rjsf/templates/CustomObjectFieldTemplate.tsx similarity index 100% rename from src/other/rjsf/CustomObjectFieldTemplate.tsx rename to src/other/rjsf/templates/CustomObjectFieldTemplate.tsx diff --git a/src/other/rjsf/InputWithInfoPopover.tsx b/src/other/rjsf/widgets/InputWithInfoPopover.tsx similarity index 64% rename from src/other/rjsf/InputWithInfoPopover.tsx rename to src/other/rjsf/widgets/InputWithInfoPopover.tsx index 95678650..9ec046be 100644 --- a/src/other/rjsf/InputWithInfoPopover.tsx +++ b/src/other/rjsf/widgets/InputWithInfoPopover.tsx @@ -1,21 +1,17 @@ /* eslint-disable react/jsx-props-no-spreading */ import Typography from "@mui/material/Typography"; import { Templates } from "@rjsf/mui"; -import { WidgetProps } from "@rjsf/utils"; import React from "react"; -import InfoPopover, { - InfoPopoverProps, -} from "../../mui/components/popover/info-popover/InfoPopover"; +import InfoPopover from "../../../mui/components/popover/info-popover/InfoPopover"; import { PositionInfoPopover } from "./PositionInfoPopover.styled"; +import { WidgetWithInfoPopoverProps } from "./types"; const { BaseInputTemplate } = Templates; -type InfoPopoverOptions = InfoPopoverProps & { content: string }; - -export default function InputWithInfoPopover(props: WidgetProps) { - const { uiSchema } = props; - const infoPopover = (uiSchema ? uiSchema["ui:options"]?.infoPopover : {}) as InfoPopoverOptions; +export default function InputWithInfoPopover(props: WidgetWithInfoPopoverProps) { + const { uiSchema = {} } = props; + const infoPopover = uiSchema["ui:options"] && uiSchema["ui:options"].infoPopover; if (!BaseInputTemplate) return null; @@ -27,7 +23,7 @@ export default function InputWithInfoPopover(props: WidgetProps) { diff --git a/src/other/rjsf/PositionInfoPopover.styled.ts b/src/other/rjsf/widgets/PositionInfoPopover.styled.ts similarity index 100% rename from src/other/rjsf/PositionInfoPopover.styled.ts rename to src/other/rjsf/widgets/PositionInfoPopover.styled.ts diff --git a/src/other/rjsf/SelectWithInfoPopover.tsx b/src/other/rjsf/widgets/SelectWithInfoPopover.tsx similarity index 62% rename from src/other/rjsf/SelectWithInfoPopover.tsx rename to src/other/rjsf/widgets/SelectWithInfoPopover.tsx index ac3ca3ab..3a615d70 100644 --- a/src/other/rjsf/SelectWithInfoPopover.tsx +++ b/src/other/rjsf/widgets/SelectWithInfoPopover.tsx @@ -1,22 +1,17 @@ /* eslint-disable react/jsx-props-no-spreading */ import Typography from "@mui/material/Typography"; import { Widgets } from "@rjsf/mui"; -import { WidgetProps } from "@rjsf/utils"; import React from "react"; -import InfoPopover, { - InfoPopoverProps, -} from "../../mui/components/popover/info-popover/InfoPopover"; +import InfoPopover from "../../../mui/components/popover/info-popover/InfoPopover"; import { PositionInfoPopover } from "./PositionInfoPopover.styled"; +import { WidgetWithInfoPopoverProps } from "./types"; const { SelectWidget } = Widgets; -type InfoPopoverOptions = InfoPopoverProps & { content: string }; - -export default function SelectWithInfoPopover(props: WidgetProps) { - const { uiSchema } = props; - - const infoPopover = (uiSchema ? uiSchema["ui:options"]?.infoPopover : {}) as InfoPopoverOptions; +export default function SelectWithInfoPopover(props: WidgetWithInfoPopoverProps) { + const { uiSchema = {} } = props; + const infoPopover = uiSchema["ui:options"] && uiSchema["ui:options"].infoPopover; return ( <> @@ -26,7 +21,7 @@ export default function SelectWithInfoPopover(props: WidgetProps) { diff --git a/src/other/rjsf/TimePicker.tsx b/src/other/rjsf/widgets/TimePicker.tsx similarity index 76% rename from src/other/rjsf/TimePicker.tsx rename to src/other/rjsf/widgets/TimePicker.tsx index fa6db620..0c0fa1e2 100644 --- a/src/other/rjsf/TimePicker.tsx +++ b/src/other/rjsf/widgets/TimePicker.tsx @@ -2,21 +2,17 @@ import Typography from "@mui/material/Typography"; import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment"; import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; import { TimePicker as MuiTimePicker } from "@mui/x-date-pickers/TimePicker"; -import { WidgetProps } from "@rjsf/utils"; import moment from "moment"; import React from "react"; -import InfoPopover, { - InfoPopoverProps, -} from "../../mui/components/popover/info-popover/InfoPopover"; +import InfoPopover from "../../../mui/components/popover/info-popover/InfoPopover"; import { PositionInfoPopover } from "./PositionInfoPopover.styled"; +import { WidgetWithInfoPopoverProps } from "./types"; -type InfoPopoverOptions = InfoPopoverProps & { content: string }; - -export default function TimePicker(props: WidgetProps) { +export default function TimePicker(props: WidgetWithInfoPopoverProps) { const { onChange, value, label } = props; - const { uiSchema, options } = props; - const infoPopover = (uiSchema ? uiSchema["ui:options"]?.infoPopover : {}) as InfoPopoverOptions; + const { uiSchema = {}, options } = props; + const infoPopover = uiSchema["ui:options"] && uiSchema["ui:options"].infoPopover; return ( @@ -40,7 +36,7 @@ export default function TimePicker(props: WidgetProps) { diff --git a/src/other/rjsf/widgets/types.ts b/src/other/rjsf/widgets/types.ts new file mode 100644 index 00000000..a676a706 --- /dev/null +++ b/src/other/rjsf/widgets/types.ts @@ -0,0 +1,13 @@ +import { WidgetProps } from "@rjsf/utils"; + +export type InfoPopoverOptions = { title: string; content: string }; + +type InfoPopoverUISchema = { + "ui:options"?: { + infoPopover?: InfoPopoverOptions; + }; +}; + +export type WidgetWithInfoPopoverProps = WidgetProps & { + uiSchema?: InfoPopoverUISchema; +};