Skip to content

Commit

Permalink
Merge pull request #513 from bcgov/chore/rsjf-labels-in-fields
Browse files Browse the repository at this point in the history
refactor: form label is displayed by fields, not widgets
  • Loading branch information
matthieu-foucault authored Apr 25, 2022
2 parents d75c266 + f3d9569 commit 2a70014
Show file tree
Hide file tree
Showing 26 changed files with 270 additions and 289 deletions.
44 changes: 19 additions & 25 deletions app/components/Form/ProjectForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ interface Props {
}
// You only need to include the optional arguments when using this function to create the schema for the summary (read-only) page.
export const createProjectUiSchema = (
tradeName,
legalName?,
bcRegistryId?,
rfpStream?,
Expand All @@ -38,12 +37,10 @@ export const createProjectUiSchema = (
"projectStatusId",
],
proposalReference: {
"ui:placeholder": "2020-RFP-1-123-ABCD",
"bcgov:size": "small",
"bcgov:help-text": "(e.g. 2020-RFP-1-ABCD-123)",
"ui:help": <small>(e.g. 2020-RFP-1-ABCD-123)</small>,
},
projectName: {
"ui:placeholder": "Short project name",
"ui:col-md": 12,
"bcgov:size": "small",
},
Expand All @@ -64,16 +61,6 @@ export const createProjectUiSchema = (
"ui:widget": "SearchWidget",
"ui:options": {
text: `${legalName ? `${legalName} (${bcRegistryId})` : ""}`,
title: "Legal Operator Name and BC Registry ID",
},
},
operatorTradeName: {
"ui:col-md": 12,
"ui:widget": "DisplayOnly",
"bcgov:size": "small",
"ui:options": {
text: `${tradeName}`,
title: "Trade Name",
},
},
fundingStreamRfpId: {
Expand All @@ -82,6 +69,7 @@ export const createProjectUiSchema = (
"bcgov:size": "small",
"ui:options": {
text: `${rfpStream}`,
label: rfpStream ? true : false,
},
},
projectStatusId: {
Expand Down Expand Up @@ -198,17 +186,23 @@ const ProjectForm: React.FC<Props> = (props) => {
};

const schema: JSONSchema7 = useMemo(() => {
const initialSchema = projectSchema;
initialSchema.properties.operatorId.anyOf = query.allOperators.edges.map(
({ node }) => {
return {
type: "number",
title: `${node.legalName} (${node.bcRegistryId})`,
enum: [node.rowId],
value: node.rowId,
};
}
);
const initialSchema = {
...projectSchema,
properties: {
...projectSchema.properties,
operatorId: {
...projectSchema.properties.operatorId,
anyOf: query.allOperators.edges.map(({ node }) => {
return {
type: "number",
title: `${node.legalName} (${node.bcRegistryId})`,
enum: [node.rowId],
value: node.rowId,
};
}),
},
},
};
return initialSchema as JSONSchema7;
}, [query]);

Expand Down
2 changes: 0 additions & 2 deletions app/components/Form/ProjectFormSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ const ProjectFormSummary: React.FC<Props> = (props) => {
node {
rowId
legalName
tradeName
bcRegistryId
}
}
Expand Down Expand Up @@ -100,7 +99,6 @@ const ProjectFormSummary: React.FC<Props> = (props) => {
theme={readOnlyTheme}
schema={projectSchema as JSONSchema7}
uiSchema={createProjectUiSchema(
selectedOperator ? selectedOperator.node.tradeName : "",
selectedOperator ? selectedOperator.node.legalName : "",
selectedOperator ? selectedOperator.node.bcRegistryId : "",
rfpStream
Expand Down
5 changes: 2 additions & 3 deletions app/components/Form/ProjectManagerForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ export const createProjectManagerUiSchema = (contact?, role?) => {
"ui:col-md": 12,
"bcgov:size": "small",
"ui:widget": "SearchWidget",
"ui:title": role,
"ui:options": {
label: false,
title: `${role}`,
label: role ? true : false,
text: `${contact}`,
},
},
Expand Down Expand Up @@ -132,7 +132,6 @@ const ProjectManagerForm: React.FC<Props> = (props) => {
label={change.projectManagerLabel.label}
required={false}
htmlFor={`${formIdPrefix}_cifUserId`}
uiSchema={uiSchema}
/>
<div>
<FormBase
Expand Down
13 changes: 2 additions & 11 deletions app/components/Form/SelectProjectStatusWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,8 @@ import { graphql, useFragment } from "react-relay";
import Dropdown from "@button-inc/bcgov-theme/Dropdown";

const SelectProjectStatus: React.FunctionComponent<WidgetProps> = (props) => {
const {
id,
onChange,
placeholder,
label,
required,
uiSchema,
value,
formContext,
} = props;
const { id, onChange, placeholder, required, uiSchema, value, formContext } =
props;

const { allFundingStreamRfpProjectStatuses } = useFragment(
graphql`
Expand Down Expand Up @@ -46,7 +38,6 @@ const SelectProjectStatus: React.FunctionComponent<WidgetProps> = (props) => {

return (
<div>
<label htmlFor={id}>{label}</label>
<Dropdown
id={id}
onChange={(e) => onChange(e.target.value || undefined)}
Expand Down
2 changes: 1 addition & 1 deletion app/cypress/integration/cif/project-revision/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ describe("the new project page", () => {
component: "Project Overview Form",
variant: "with errors",
});
cy.get(".error-detail").should("have.length", 6);
cy.get(".error-detail").should("have.length", 7);
// Renders the default error message for a required field
cy.get(".error-detail").last().should("contain", "Please enter a value");

Expand Down
4 changes: 1 addition & 3 deletions app/data/jsonSchemaForm/projectSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const projectSchema = {
"operatorId",
"fundingStreamRfpId",
"totalFundingRequest",
"projectStatusId",
],
properties: {
proposalReference: {
Expand All @@ -27,9 +28,6 @@ const projectSchema = {
default: undefined,
anyOf: undefined,
},
operatorTradeName: {
type: "string",
},
fundingStreamRfpId: {
type: "number",
title: "Funding Stream RFP ID",
Expand Down
55 changes: 34 additions & 21 deletions app/lib/theme/FieldTemplate.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,60 @@
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faExclamationTriangle } from "@fortawesome/free-solid-svg-icons";
import { FieldTemplateProps } from "@rjsf/core";
import FieldLabel from "./widgets/FieldLabel";

const FieldTemplate = ({ children, errors, help, rawErrors }) => {
const FieldTemplate: React.FC<FieldTemplateProps> = ({
children,
errors,
help,
rawErrors,
label,
displayLabel,
required,
id,
}) => {
return (
<>
<div>
{children}
<div>
{displayLabel && (
<FieldLabel label={label} required={required} htmlFor={id} />
)}
{help}
{children}

<div className="error-div">
{rawErrors && rawErrors.length > 0 ? (
<>
<FontAwesomeIcon
className="error-icon"
icon={faExclamationTriangle}
/>
{errors}
</>
) : null}
</div>
{help}
<div className="error-div">
{rawErrors && rawErrors.length > 0 ? (
<>
<FontAwesomeIcon
className="error-icon"
icon={faExclamationTriangle}
/>
{errors}
</>
) : null}
</div>

<style jsx>{`
div:not(:last-child) {
margin-bottom: 1em;
}
:global(.error-icon) {
div :global(.error-icon) {
color: #cd2026;
}
:global(.error-div) {
div .error-div {
height: 1.5rem;
display: flex;
padding-top: 10px;
}
:global(ul.error-detail) {
div :global(ul.error-detail) {
padding: 0;
list-style: none;
margin-left: 0.5rem;
}
:global(li.text-danger) {
div :global(li.text-danger) {
color: #cd2026 !important;
}
`}</style>
</>
</div>
);
};

Expand Down
67 changes: 67 additions & 0 deletions app/lib/theme/ReadOnlyFieldTemplate.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faExclamationTriangle } from "@fortawesome/free-solid-svg-icons";
import { FieldTemplateProps } from "@rjsf/core";
import FieldLabel from "./widgets/FieldLabel";

const FieldTemplate: React.FC<FieldTemplateProps> = ({
children,
errors,
rawErrors,
label,
displayLabel,
required,
id,
}) => {
return (
<div>
<div className="definition-container">
{displayLabel && (
<FieldLabel
label={label}
required={required}
htmlFor={id}
tagName="dt"
/>
)}
{children}
</div>
{rawErrors && rawErrors.length > 0 ? (
<div className="error-div">
<FontAwesomeIcon
className="error-icon"
icon={faExclamationTriangle}
/>
{errors}
</div>
) : null}

<style jsx>{`
div.definition-container {
display: flex;
}
div:not(:last-child) {
margin-bottom: 0.5em;
}
div :global(.error-icon) {
color: #cd2026;
}
div .error-div {
height: 1.5rem;
display: flex;
padding-top: 10px;
}
div :global(ul.error-detail) {
padding: 0;
list-style: none;
margin-left: 0.5rem;
}
div :global(li.text-danger) {
color: #cd2026 !important;
}
`}</style>
</div>
);
};

export default FieldTemplate;
4 changes: 2 additions & 2 deletions app/lib/theme/ReadOnlyTheme.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ThemeProps } from "@rjsf/core";
import FieldTemplate from "./FieldTemplate";
import ReadOnlyFieldTemplate from "./ReadOnlyFieldTemplate";
import ReadOnlyObjectFieldTemplate from "./ReadOnlyObjectFieldTemplate";
import { utils } from "@rjsf/core";
import ReadOnlyWidget from "./widgets/ReadOnlyWidget";
Expand All @@ -23,7 +23,7 @@ const readOnlyTheme: ThemeProps = {
SelectProjectStatusWidget: ReadOnlyWidget,
},
ObjectFieldTemplate: ReadOnlyObjectFieldTemplate,
FieldTemplate: FieldTemplate,
FieldTemplate: ReadOnlyFieldTemplate,
};

export default readOnlyTheme;
4 changes: 0 additions & 4 deletions app/lib/theme/utils/getRequiredLabel.ts

This file was deleted.

9 changes: 2 additions & 7 deletions app/lib/theme/widgets/DisplayOnlyWidget.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
import { WidgetProps } from "@rjsf/core";

const DisplayOnlyWidget: React.FC<WidgetProps> = ({ options }) => {
return (
<span className="paragraph-text">
<label>{options.title}</label>
<p>{options.text}</p>
</span>
);
const DisplayOnlyWidget: React.FC<WidgetProps> = ({ options, id }) => {
return <span id={id}>{options.text}</span>;
};

export default DisplayOnlyWidget;
Loading

0 comments on commit 2a70014

Please sign in to comment.