Skip to content

Commit

Permalink
feat: project funding stream dropdown
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexZorkin committed Dec 15, 2021
1 parent 2c2d6ee commit aaac8fd
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 4 deletions.
4 changes: 2 additions & 2 deletions app/components/Form/FormBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import FormComponentProps from "./FormComponentProps";

interface Props extends FormComponentProps {
schema: JSONSchema7;
uiSchema: object;
uiSchema: {};
}

const FormBase: React.FC<Props> = ({
Expand Down Expand Up @@ -42,7 +42,7 @@ const FormBase: React.FC<Props> = ({
}, []);

return (
<FormBorder title="Background">
<FormBorder title={schema.title}>
<Form
// @ts-ignore
ref={formRef}
Expand Down
55 changes: 54 additions & 1 deletion app/components/Project/ProjectForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ const ProjectForm: React.FC<Props> = (props) => {
}
}
}
allFundingStreams {
edges {
node {
rowId
name
description
}
}
}
}
}
`,
Expand All @@ -37,9 +46,22 @@ const ProjectForm: React.FC<Props> = (props) => {
);
}

// If there is a funding stream selected, retrieve it to populate the description field below in the UI Schema.
let selectedFundingStream;
if (props.formData.fundingStreamId) {
selectedFundingStream = query.allFundingStreams.edges.find(
({ node }) => node.rowId === props.formData.fundingStreamId
);
}

const schema: JSONSchema7 = {
type: "object",
required: ["rfpNumber", "description", "operatorId"],
required: [
"rfpNumber",
"description",
"operatorId",
"fundingStreamId"
],
properties: {
rfpNumber: {
type: "string",
Expand All @@ -63,6 +85,22 @@ const ProjectForm: React.FC<Props> = (props) => {
operatorTradeName: {
type: "string",
},
fundingStreamId: {
type: "number",
title: "Funding Stream ID",
default: undefined,
anyOf: query.allFundingStreams.edges.map(({ node }) => {
return {
type: "number",
title: node.name,
enum: [node.rowId],
value: node.rowId,
};
}),
},
fundingStreamDescription: {
type: "string",
},
},
};

Expand Down Expand Up @@ -92,6 +130,21 @@ const ProjectForm: React.FC<Props> = (props) => {
title: "Trade Name",
},
},
fundingStreamId: {
"ui:placeholder": "Select a Funding Stream",
"ui:widget": "select",
"ui:col-md": 12,
"bcgov:size": "small",
},
fundingStreamDescription: {
"ui:col-md": 12,
"ui:widget": "DisplayOnly",
"bcgov:size": "large",
"ui:options": {
text: `${selectedFundingStream ? selectedFundingStream.node.description : ""}`,
title: "Description",
},
},
};
return <FormBase {...props} schema={schema} uiSchema={uiSchema} />;
};
Expand Down
2 changes: 2 additions & 0 deletions app/lib/theme/service-development-toolkit-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import TextWidget from "./widgets/TextWidget";
import { utils } from "@rjsf/core";
import SearchDropdownWidget from "lib/theme/widgets/SearchDropdownWidget";
import DisplayOnlyWidget from "lib/theme/widgets/DisplayOnlyWidget";
import SelectWidget from "lib/theme/widgets/SelectWidget";

const { fields, widgets } = utils.getDefaultRegistry();

Expand All @@ -16,6 +17,7 @@ const Theme: ThemeProps = {
TextWidget: TextWidget,
SearchWidget: SearchDropdownWidget,
DisplayOnly: DisplayOnlyWidget,
SelectWidget: SelectWidget,
},
ObjectFieldTemplate: ObjectFieldTemplate,
FieldTemplate: FieldTemplate,
Expand Down
39 changes: 39 additions & 0 deletions app/lib/theme/widgets/SelectWidget.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { WidgetProps } from "@rjsf/core";
import Dropdown from "@button-inc/bcgov-theme/Dropdown";
import getRequiredLabel from "../utils/getRequiredLabel";

const SelectWidget: React.FunctionComponent<WidgetProps> = (props) => {
const { id, onChange, options, placeholder, label, required, uiSchema } = props;
console.log(props)
return (
<>
<label htmlFor={`funding-stream-dropdown-${props.id}`}>
{getRequiredLabel(label, required)}
</label>
<Dropdown
id={id}
onChange={(e) => onChange(e.target.value || undefined)}
placeholder={placeholder}
size={(uiSchema && uiSchema["bcgov:size"]) || "large"}
required={required}
>
{options.enumOptions.map((opt) => {
return (
<option key={opt.value} value={opt.value}>
{opt.label}
</option>
);
})}
</Dropdown>
<style jsx>
{`
:global(input) {
width: 100%;
}
`}
</style>
</>
);
};

export default SelectWidget;
1 change: 0 additions & 1 deletion app/pages/cif/create-project.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ export function CreateProject({
/>
</Grid.Col>
</Grid.Row>

<Button
size="medium"
variant="primary"
Expand Down
64 changes: 64 additions & 0 deletions app/tests/unit/components/Project/ProjectForm.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ describe("The Project Form", () => {
rfpNumber: "12345678",
description: "d",
operatorId: 1,
fundingStreamId: 1,
};
environment.mock.queueOperationResolver((operation) =>
MockPayloadGenerator.generate(operation, {
Expand All @@ -102,6 +103,17 @@ describe("The Project Form", () => {
},
],
},
allFundingStreams: {
edges: [
{
node: {
rowId: 1,
name: "EP",
description: "Emissions Performance",
},
},
],
},
};
},
})
Expand All @@ -116,6 +128,9 @@ describe("The Project Form", () => {
expect(screen.getByPlaceholderText("Select an Operator").value).toBe(
"test operator (1234abcd)"
);
expect(screen.getByPlaceholderText("Select a Funding Stream").value).toBe(
"EP"
);
});
it("calls onformerrors on first render if there are errors", () => {
const onFormErrorsSpy = jest.fn();
Expand All @@ -124,6 +139,7 @@ describe("The Project Form", () => {
rfpNumber: "",
description: "",
operatorId: 1,
fundingStreamId: 1,
};
props.onFormErrors = onFormErrorsSpy;

Expand All @@ -142,6 +158,17 @@ describe("The Project Form", () => {
},
],
},
allFundingStreams: {
edges: [
{
node: {
rowId: 1,
name: "EP",
description: "Emissions Performance",
},
},
],
},
};
},
})
Expand All @@ -166,6 +193,7 @@ describe("The Project Form", () => {
rfpNumber: "1999-RFP-1-123-ABCD",
description: "d",
operatorId: 1,
fundingStreamId: 1,
};
props.onFormErrors = onFormErrorsSpy;
environment.mock.queueOperationResolver((operation) =>
Expand All @@ -183,6 +211,17 @@ describe("The Project Form", () => {
},
],
},
allFundingStreams: {
edges: [
{
node: {
rowId: 1,
name: "EP",
description: "Emissions Performance",
},
},
],
},
};
},
})
Expand All @@ -197,6 +236,7 @@ describe("The Project Form", () => {
rfpNumber: null,
description: null,
operatorId: null,
fundingStreamId: null,
})
);
});
Expand Down Expand Up @@ -225,6 +265,17 @@ describe("The Project Form", () => {
},
],
},
allFundingStreams: {
edges: [
{
node: {
rowId: 1,
name: "EP",
description: "Emissions Performance",
},
},
],
},
};
},
})
Expand Down Expand Up @@ -253,6 +304,7 @@ describe("The Project Form", () => {
rfpNumber: "1999123-RFP-1-123-ABCD",
description: "desc",
operatorId: 1,
fundingStreamId: 1,
};
props.onFormErrors = onFormErrorsSpy;

Expand All @@ -271,6 +323,17 @@ describe("The Project Form", () => {
},
],
},
allFundingStreams: {
edges: [
{
node: {
rowId: 1,
name: "EP",
description: "Emissions Performance",
},
},
],
},
};
},
})
Expand All @@ -285,6 +348,7 @@ describe("The Project Form", () => {
rfpNumber: expect.anything(),
description: null,
operatorId: null,
fundingStreamId: null,
})
);
});
Expand Down
48 changes: 48 additions & 0 deletions app/tests/unit/lib/theme/widgets/SelectWidget.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from "react";
import SelectWidget from "lib/theme/widgets/SelectWidget";

import { render } from "@testing-library/react";

describe("The SelectWidget Widget", () => {
it("Matches the snapshot with no default value set", () => {
const props: any = {
id: "1",
placeholder: "test placeholder",
onChange: jest.fn(),
label: "Search",
value: undefined,
required: false,
schema: {
anyOf: [
{ value: 1, enum: [1], type: "number", title: "Option 1" },
{ value: 2, enum: [2], type: "number", title: "Option 2" },
],
},
};

const componentUnderTest = render(<SelectWidget {...props} />);

expect(componentUnderTest.container).toMatchSnapshot();
});

it("Matches the snapshot with a default value set", () => {
const props: any = {
id: "1",
placeholder: "test placeholder",
onChange: jest.fn(),
label: "Search",
value: 1,
required: false,
schema: {
anyOf: [
{ value: 1, enum: [1], type: "number", title: "Option 1" },
{ value: 2, enum: [2], type: "number", title: "Option 2" },
],
},
};

const componentUnderTest = render(<SelectWidget {...props} />);

expect(componentUnderTest.container).toMatchSnapshot();
});
});

0 comments on commit aaac8fd

Please sign in to comment.