Skip to content

Commit

Permalink
Merge pull request #584 from sebgroup/develop
Browse files Browse the repository at this point in the history
Dynamic forms error messages feature and mics fixes beta release
  • Loading branch information
mario-subo authored Apr 22, 2021
2 parents f4b566a + 2ddf3c2 commit 4a0c793
Show file tree
Hide file tree
Showing 17 changed files with 8,510 additions and 14,454 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/build-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ jobs:
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node }}
- name: Install npm@6
run: npm i npm@6 # to use workspace
- name: Installing dependencies
run: npm ci
- name: Testing
Expand Down
6 changes: 3 additions & 3 deletions docs/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

141 changes: 131 additions & 10 deletions docs/src/pages/docs/dynamic-forms.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import Layout from "@common/Layout";
import { CodeSnippet } from "@common/CodeSnippet";
import { useDynamicForm, DynamicFormSection } from "@sebgroup/react-components/hooks";
import { Table, TableBody, TableCell, TableHeader, TableHeaderCell, TableRow } from "@sebgroup/react-components/Table";
import { Button } from "@sebgroup/react-components/Button";
import { isEmpty } from "@sebgroup/frontend-tools";

const DynamicForms: React.FC = React.memo(() => {
return (
Expand Down Expand Up @@ -124,6 +126,67 @@ export default ComponentConditionalRender;

<hr />

<h2 className="pt-3 pb-3">Form errors example</h2>
<p>Every form element defined can display an error message based on any validation rules you define yourself. Simply set the errors for that key as shown in the code snippet below.</p>
<CodeSnippet language="javascript">
{`
import { useDynamicForm } from "@sebgroup/react-components/hooks/useDynamicForm";
const FormWithErrors: React.FC = () => {
const sections: DynamicFormSection[] = [
{
key: "section-3-errors",
items: [
{
key: "normal",
label: "Non mandatory field",
order: 1,
value: false,
controlType: "Checkbox",
},
{
key: "with-error",
order: 2,
label: "Mandatory field",
controlType: "Text",
},
],
},
];
const [renderForm, state, , setErrors] = useDynamicForm(sections);
const validate = () => {
if (!isEmpty(state) && !isEmpty(state["section-3-errors"])) {
setErrors((existing) => {
return {
...existing,
"section-3-errors": {
...existing["section-3-errors"],
"with-error": !state["section-3-errors"]["with-error"] ? "Please fill in this field" : null,
},
};
});
}
};
return (
<>
<div>{renderForm()}</div>
<Button className="mt-3" onClick={validate}>Validate</Button>
</>
);
};
export default FormWithErrors;
`}
</CodeSnippet>
<div className="p-3 rounded bg-white">
<FormWithErrors />
</div>

<hr />

<h2 className="pt-3 pb-3">Dynamic forms API</h2>
<h3 className="pt-3 pb-3">
<code>DynamicFormSection</code>
Expand Down Expand Up @@ -156,7 +219,7 @@ export default ComponentConditionalRender;
<TableCell>
<code>string</code>
</TableCell>
<TableCell></TableCell>
<TableCell>The title of the header of the section</TableCell>
</TableRow>
<TableRow>
<TableCell>
Expand All @@ -166,7 +229,9 @@ export default ComponentConditionalRender;
<TableCell>
<code>number</code>
</TableCell>
<TableCell>The order of the section. Any number, lower number will be displayed before.</TableCell>
<TableCell>
Optional order of the section. Any number, lower number will be displayed before. If order is not provided the original order of the array will be used.
</TableCell>
</TableRow>
<TableRow>
<TableCell>
Expand Down Expand Up @@ -240,7 +305,7 @@ export default ComponentConditionalRender;
</TableCell>
<TableCell>&#10004;</TableCell>
<TableCell>
<code>{`string | string[] | DynamicFormOption | DynamicFormOption[] | Date | boolean | number`}</code>
<code>{`string | string[] | Date | boolean | number | null`}</code>
</TableCell>
<TableCell>Optional initial value of the element when it gets created.</TableCell>
</TableRow>
Expand Down Expand Up @@ -272,9 +337,7 @@ export default ComponentConditionalRender;
<TableCell>
<code>string</code>
</TableCell>
<TableCell>
This optional property will be applied to the following components: <code>Checkbox</code>, <code>Radio</code>, <code>Text</code>
</TableCell>
<TableCell>An optional description displayed below the form field.</TableCell>
</TableRow>
<TableRow>
<TableCell>
Expand All @@ -297,7 +360,12 @@ export default ComponentConditionalRender;
<code>{`number | Date`}</code>
</TableCell>
<TableCell>
The 'min' property which will applied to the following components: <code>Stepper</code>, <code>Datepicker</code>
<p>
The 'min' property which will applied to the following components: <code>Stepper</code>, <code>Datepicker</code>
</p>
<p>
This will also apply the 'minLength' property of <code>Text</code> and <code>TextArea</code>
</p>
</TableCell>
</TableRow>
<TableRow>
Expand All @@ -309,7 +377,12 @@ export default ComponentConditionalRender;
<code>{`number | Date`}</code>
</TableCell>
<TableCell>
The 'max' property which will applied to the following components: <code>Stepper</code>, <code>Datepicker</code>
<p>
The 'max' property which will applied to the following components: <code>Stepper</code>, <code>Datepicker</code>
</p>
<p>
This will also apply the 'maxLength' property of <code>Text</code> and <code>TextArea</code>
</p>
</TableCell>
</TableRow>
<TableRow>
Expand Down Expand Up @@ -367,7 +440,7 @@ export default ComponentConditionalRender;
</TableCell>
<TableCell>&#10004;</TableCell>
<TableCell>
<code>{`string | string[] | DynamicFormOption | DynamicFormOption[] | Date | boolean | number`}</code>
<code>{`string | string[] | Date | boolean | number | null`}</code>
</TableCell>
<TableCell>
<b>Conditional rendering:</b> The exact value of the <b>rulerKey</b> element, as the condition for this element to be rendered. The type of value must be the same as
Expand Down Expand Up @@ -441,7 +514,7 @@ export default ComponentConditionalRender;
<code>string</code>
</TableCell>
<TableCell>
An optional description displayed below the label for the following components: <code>Checkbox</code>, <code>Radio</code>
An optional description displayed below the label for the <code>Radio</code> component.
</TableCell>
</TableRow>
<TableRow>
Expand Down Expand Up @@ -529,3 +602,51 @@ const ComponentConditionalRender: React.FC = () => {

return <div>{renderForm()}</div>;
};

const FormWithErrors: React.FC = () => {
const sections: DynamicFormSection[] = [
{
key: "section-3-errors",
items: [
{
key: "normal",
label: "Non mandatory field",
order: 1,
value: false,
controlType: "Checkbox",
},
{
key: "with-error",
order: 2,
label: "Mandatory field",
controlType: "Text",
},
],
},
];

const [renderForm, state, , setErrors] = useDynamicForm(sections);

const validate = () => {
if (!isEmpty(state) && !isEmpty(state["section-3-errors"])) {
setErrors((existing) => {
return {
...existing,
"section-3-errors": {
...existing["section-3-errors"],
"with-error": !state["section-3-errors"]["with-error"] ? "Please fill in this field" : null,
},
};
});
}
};

return (
<>
<div>{renderForm()}</div>
<Button className="mt-3" onClick={validate}>
Validate
</Button>
</>
);
};
2 changes: 1 addition & 1 deletion docs/src/pages/docs/loader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const LoaderPage: React.FC = (): React.ReactElement<void> => {
{
key: "controls",
items: [
{ key: "size", label: "size", options: sizes, controlType: "Radio" },
{ key: "size", label: "size", options: sizes, controlType: "Radio", value: sizes[1].value },
{ key: "type", label: "type", options: types, controlType: "Radio", value: types[0].value },
{ key: "display", label: "Display types", options: displayTypes, controlType: "Radio", value: displayTypes[0].value },
{ key: "backdrop", label: "backdrop", controlType: "Checkbox", value: false },
Expand Down
14 changes: 9 additions & 5 deletions docs/src/pages/docs/radiobutton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,17 @@ const RadioButtonPage: React.FC = () => {
mainFile={importString}
example={
<div className="w-100">
<RadioGroup name="test-group" value={value} onChange={(e) => setValue(e.target.value)} {...controls} indicator={isGrouped ? indicator : null}>
<RadioButton value="Yes" indicator={isIndividual ? indicator : null}>
<RadioGroup name="test-group" value={value} onChange={(e) => setValue(e.target.value)} disabled={controls?.disabled} indicator={isGrouped ? indicator : null}>
<RadioButton value="Yes" wrapperProps={controls.inline ? { className: "d-inline-block" } : {}} indicator={isIndividual ? indicator : null}>
Yes
<p className="text-muted m-0">Express yourself here</p>
</RadioButton>
<RadioButton value="No">No</RadioButton>
<RadioButton value="Maybe">Maybe</RadioButton>
<RadioButton value="No" wrapperProps={controls.inline ? { className: "d-inline-block" } : {}}>
No
</RadioButton>
<RadioButton value="Maybe" wrapperProps={controls.inline ? { className: "d-inline-block" } : {}}>
Maybe
</RadioButton>
</RadioGroup>
</div>
}
Expand All @@ -90,7 +94,7 @@ const RadioButtonPage: React.FC = () => {
<h4>Radio group</h4>
<p>
We have exported a helper component that makes it easy for you to compose a radio group. The component is name <code>RadioGroup</code>. You can apply group level properties
like <code>inline</code> or <code>disabled</code>
like <code>indicator</code> or <code>disabled</code>
</p>

<br />
Expand Down
15 changes: 5 additions & 10 deletions docs/src/pages/docs/steptracker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ const StepTrackerPage: React.FC = React.memo(() => {
controlType: "Stepper",
},
{
label: "Optional configurations",
key: "checkboxes",
controlType: "Option",
options: [{ label: "Use numbers", value: "useNumbers", key: "useNumbers" }],
label: "Use numbers",
key: "useNumbers",
value: false,
controlType: "Checkbox",
},
],
},
Expand All @@ -59,11 +59,6 @@ const StepTrackerPage: React.FC = React.memo(() => {
const [renderForm, form, setForm] = useDynamicForm(fields);
const code: string = `<StepTracker list={[{ label: "hello" }]} step={0} onClick={null} />`;

/** check if key selected */
const checkSelectedKey = (key: string) => {
return form.controls.checkboxes?.some((item: DynamicFormOption) => item.key === key);
};

React.useEffect(() => {
setValue((form.controls as any)?.step);
}, [(form.controls as any)?.step]);
Expand All @@ -89,7 +84,7 @@ const StepTrackerPage: React.FC = React.memo(() => {
onClick={setValue}
orientation={(form.controls as any)?.orientation}
labelPosition={(form.controls as any)?.direction}
useNumbers={checkSelectedKey("useNumbers")}
useNumbers={(form.controls as any)?.useNumbers}
>
{stepList.map((item, i) => (
<StepLabel label={item.label} key={i} />
Expand Down
4 changes: 2 additions & 2 deletions docs/src/pages/docs/textlabel.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import Docs from "@common/Docs";
import { TextLabel } from "@sebgroup/react-components/TextLabel";
import { DynamicFormOption, DynamicFormSection, useDynamicForm } from "@sebgroup/react-components/hooks/useDynamicForm";
import { DynamicFormSection, useDynamicForm } from "@sebgroup/react-components/hooks/useDynamicForm";

const TextLabelPage: React.FC = React.memo(() => {
const importString: string = require("!raw-loader!@sebgroup/react-components/TextLabel/TextLabel");
Expand All @@ -23,7 +23,7 @@ const TextLabelPage: React.FC = React.memo(() => {

/** check if key selected */
const checkSelectedKey = (key: string) => {
return controls.checkboxes?.some((item: DynamicFormOption) => item.key === key);
return controls.checkboxes?.find((item: string) => item === key);
};

return (
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/docs/toggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const TogglePage: React.FC = () => {

/** check if key selected */
const checkSelectedKey = (key: string) => {
return controls.checkboxes?.some((item: DynamicFormOption) => item.key === key);
return controls.checkboxes?.find((item: string) => item === key);
};

return (
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/docs/tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ const TooltipPage: React.FC = () => {

/** check if key selected */
const checkSelectedKey = (key: string) => {
return controls.checkboxes?.some((item: DynamicFormOption) => item.key === key);
return controls.checkboxes?.find((item: string) => item === key);
};

return (
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/docs/video.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const VideoPage: React.FC = () => {
{ key: "language", value: null, label: "Language", placeholder: "Language of video player", controlType: "Text" },
{ key: "startTime", value: null, label: "Start time of playback", placeholder: "Playback starts at", controlType: "Text" },
{ key: "endTime", value: null, label: "End time of playback", placeholder: "Playback ends at", controlType: "Text" },
{ label: "Optional configurations", key: "checkboxes", value: defaultCheckboxControls, controlType: "Option", options: checkboxControls },
{ label: "Optional configurations", key: "checkboxes", value: defaultCheckboxControls.map((e) => e.value), controlType: "Option", options: checkboxControls },
],
},
];
Expand Down
4 changes: 1 addition & 3 deletions docs/src/utils/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { DynamicFormOption } from "@sebgroup/react-components/hooks/useDynamicForm";

/** check if key selected from options */

type Control = {
[T: string]: any;
};

export function checkDynamicFormSelectedKey<T>(key: string, controls: Control): T {
return controls.checkboxes?.some((item: DynamicFormOption) => item.key === key);
return controls.checkboxes?.find((item: string) => item === key);
}
Loading

0 comments on commit 4a0c793

Please sign in to comment.