-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#9492 Add database to Rich Text Editor form builder field #9495
Changes from all commits
9ba2a0c
e4a290f
4a003d7
3586503
b054633
217d880
f827eca
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/* | ||
* Copyright (C) 2024 PixieBrix, Inc. | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Affero General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Affero General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Affero General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
import React from "react"; | ||
import { partial } from "lodash"; | ||
import { joinName } from "@/utils/formUtils"; | ||
import SchemaField from "@/components/fields/schemaFields/SchemaField"; | ||
|
||
const RichTextFields: React.FunctionComponent<{ uiOptionsPath: string }> = ({ | ||
uiOptionsPath, | ||
}) => { | ||
const configName = partial(joinName, uiOptionsPath); | ||
|
||
return ( | ||
<SchemaField | ||
name={configName("database")} | ||
isRequired | ||
schema={{ | ||
$ref: "https://app.pixiebrix.com/schemas/database#", | ||
title: "Asset Database", | ||
description: | ||
"Asset database to use for image upload. Asset databases are a specific kind of database that" + | ||
" can be created in the Admin Console.", | ||
}} | ||
uiSchema={{ | ||
"ui:widget": "database", | ||
}} | ||
/> | ||
); | ||
}; | ||
|
||
export default RichTextFields; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
/* | ||
* Copyright (C) 2024 PixieBrix, Inc. | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Affero General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Affero General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Affero General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
import React from "react"; | ||
import { partial } from "lodash"; | ||
import { joinName } from "@/utils/formUtils"; | ||
import { useField } from "formik"; | ||
import SchemaField from "@/components/fields/schemaFields/SchemaField"; | ||
import { Collapse } from "react-bootstrap"; | ||
|
||
const TextAreaFields: React.FC<{ uiOptionsPath: string }> = ({ | ||
uiOptionsPath, | ||
}) => { | ||
const configName = partial(joinName, uiOptionsPath); | ||
const [{ value: showSubmitToolbar }] = useField<boolean | null>( | ||
configName("submitToolbar", "show"), | ||
); | ||
|
||
return ( | ||
<> | ||
<SchemaField | ||
name={configName("rows")} | ||
schema={{ | ||
type: "number", | ||
title: "# Rows", | ||
description: | ||
"The number of visible text lines for the control. If it is not specified, the default value is 2.", | ||
}} | ||
/> | ||
<SchemaField | ||
name={configName("submitOnEnter")} | ||
schema={{ | ||
type: "boolean", | ||
title: "Submit Form on Enter?", | ||
description: | ||
"If enabled, pressing Enter will submit the form. Press Shift+Enter for newlines in this mode", | ||
}} | ||
isRequired | ||
/> | ||
<SchemaField | ||
name={configName("submitToolbar", "show")} | ||
schema={{ | ||
type: "boolean", | ||
title: "Include Submit Toolbar?", | ||
description: | ||
"Enable the submit toolbar that has a selectable icon to act as a submit button", | ||
}} | ||
isRequired | ||
/> | ||
<Collapse in={showSubmitToolbar ?? false}> | ||
<SchemaField | ||
name={configName("submitToolbar", "icon")} | ||
schema={{ $ref: "https://app.pixiebrix.com/schemas/icon#" }} | ||
label="Select Icon" | ||
description="Select the icon that appears in the bottom right of the Submit Toolbar" | ||
uiSchema={{ | ||
"ui:widget": "IconWidget", | ||
}} | ||
/> | ||
</Collapse> | ||
</> | ||
); | ||
}; | ||
|
||
export default TextAreaFields; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -177,5 +177,5 @@ describe("RichTextWidget", () => { | |
}, | ||
{ submissionCount: 1 }, | ||
); | ||
}, 15_000); | ||
}, 20_000); | ||
}); |
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -16,7 +16,7 @@ | |||
*/ | ||||
|
||||
import React from "react"; | ||||
import { type WidgetProps } from "@rjsf/utils"; | ||||
import { type ErrorSchema, type WidgetProps } from "@rjsf/utils"; | ||||
import RichTextEditor from "@/components/richTextEditor/RichTextEditor"; | ||||
|
||||
const RichTextWidget: React.FunctionComponent<WidgetProps> = ({ | ||||
|
@@ -26,20 +26,35 @@ const RichTextWidget: React.FunctionComponent<WidgetProps> = ({ | |||
onBlur, | ||||
disabled, | ||||
readonly, | ||||
}) => ( | ||||
<RichTextEditor | ||||
onUpdate={({ editor }) => { | ||||
onChange(editor.getHTML()); | ||||
}} | ||||
onFocus={({ editor }) => { | ||||
editor.commands.focus(); | ||||
onFocus(id, editor.getHTML()); | ||||
}} | ||||
onBlur={({ editor }) => { | ||||
onBlur(id, editor.getHTML()); | ||||
}} | ||||
editable={!(disabled || readonly)} | ||||
/> | ||||
); | ||||
options, | ||||
value, | ||||
}) => { | ||||
const { database } = options; | ||||
|
||||
if (!database) { | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't like using an error in the field preview as a way of showing an error the user has not provided a value. I prefer we stick with showing it as a field error annotation in the Brick Configuration pane. (I think you'd add as a check in the analysis here: Line 28 in 971d00b
Was there a specific reason you chose to show it in the preview/rendered form instead? I won't block this PR on it though to keep the ball rolling There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I wanted to make sure at minimum that the form displayed errors at run-time due to consideration for passing in variables, but I agree that also including the error annotation in the form itself is ideal. However - at this point, I'm more convinced that we should favor the approach of making the field optional in the next slice, as it will 1) be easy to do, 2) be more compatible with putting asset database creation behind a feature flag, and 3) reduce complexity around handling form errors. Let's merge as-is, and I'll remove the |
||||
// TODO: Can't figure out how to satisfy this type without casting, but this is how it's done in the docs | ||||
// https://rjsf-team.github.io/react-jsonschema-form/docs/advanced-customization/custom-widgets-fields/#raising-errors-from-within-a-custom-widget-or-field | ||||
const databaseConfigurationError = { | ||||
__errors: ["Rich text field asset database is required"], | ||||
} as ErrorSchema; | ||||
onChange(value, databaseConfigurationError); | ||||
} | ||||
|
||||
return ( | ||||
<RichTextEditor | ||||
onUpdate={({ editor }) => { | ||||
onChange(editor.getHTML()); | ||||
}} | ||||
onFocus={({ editor }) => { | ||||
editor.commands.focus(); | ||||
onFocus(id, editor.getHTML()); | ||||
}} | ||||
onBlur={({ editor }) => { | ||||
onBlur(id, editor.getHTML()); | ||||
}} | ||||
editable={!(disabled || readonly)} | ||||
/> | ||||
); | ||||
}; | ||||
|
||||
export default RichTextWidget; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️