From ee082d5da454b1890e9c3bc5b322cbf52f5c0b9f Mon Sep 17 00:00:00 2001 From: Jordan Fabian Valdez Date: Fri, 10 Jan 2020 19:27:03 -0600 Subject: [PATCH 1/5] Fixing issue with most of the UI types --- src/demo/App.js | 12 ++++++------ .../children/Form/UI/CheckBox/check-box.component.js | 3 ++- .../Form/UI/ColorPicker/color-picker.component.js | 3 ++- .../UI/DateTimePicker/date-time-picker.component.js | 6 ++++-- .../children/Form/UI/Decimal/decimal.component.js | 5 ++++- .../children/Form/UI/Email/email.component.js | 5 ++++- .../children/Form/UI/Float/float.component.js | 5 ++++- .../children/Form/UI/Input/input.component.js | 3 ++- .../children/Form/UI/Integer/integer.component.js | 5 ++++- .../children/Form/UI/Phone/phone.component.js | 5 ++++- .../Form/UI/RadioButton/radio-button.component.js | 5 ++++- .../children/Form/UI/TextArea/text-area.component.js | 5 ++++- src/lib/components/FormModel/form-model.component.js | 3 +-- 13 files changed, 45 insertions(+), 20 deletions(-) diff --git a/src/demo/App.js b/src/demo/App.js index 8a46bab9..b0880b5c 100644 --- a/src/demo/App.js +++ b/src/demo/App.js @@ -9,7 +9,7 @@ import { ProfileUploader, useNotification, FormModel, - AutoSaveDefaultSpinner, + Spinner, ProfileViewer } from '@lib'; import { AccessControlList } from '@classes'; @@ -167,15 +167,16 @@ const App = () => { { @@ -199,7 +200,6 @@ const App = () => { console.log(response); } }} - autoSave liveUpdate /> { const { [UI.LABEL]: label } = data; const onChange = event => { - updateData(id, String(event.target.checked)); + const updatedPart = { ...data, value: String(event.target.checked) }; + updateData(id, updatedPart); }; return ( diff --git a/src/lib/components/FormModel/children/Form/UI/ColorPicker/color-picker.component.js b/src/lib/components/FormModel/children/Form/UI/ColorPicker/color-picker.component.js index fb33f655..5a0e94fe 100644 --- a/src/lib/components/FormModel/children/Form/UI/ColorPicker/color-picker.component.js +++ b/src/lib/components/FormModel/children/Form/UI/ColorPicker/color-picker.component.js @@ -25,7 +25,8 @@ const ColorPicker = (props: Props) => { const handleChangeComplete = color => { setColor(color.hex); - updateData(id, color.hex); + const updatedPart = { ...data, value: color.hex }; + updateData(id, updatedPart); }; const handleClick = () => { diff --git a/src/lib/components/FormModel/children/Form/UI/DateTimePicker/date-time-picker.component.js b/src/lib/components/FormModel/children/Form/UI/DateTimePicker/date-time-picker.component.js index affac2c7..87ab3eb1 100644 --- a/src/lib/components/FormModel/children/Form/UI/DateTimePicker/date-time-picker.component.js +++ b/src/lib/components/FormModel/children/Form/UI/DateTimePicker/date-time-picker.component.js @@ -34,7 +34,8 @@ export const DateTimePicker = props => { const onChange = date => { /* User wants to remove the date */ if (!date) { - updateData(id, ''); + const updatedPart = { ...data, value: '' }; + updateData(id, updatedPart); setDate(null); return; } @@ -45,7 +46,8 @@ export const DateTimePicker = props => { if (type === UITypes.DateField) value = format(date, DATE_FORMAT.DATE); if (type === UITypes.DateTimeField) value = date.toISOString(); - updateData(id, value); + const updatedPart = { ...data, value }; + updateData(id, updatedPart); setDate(date); }; diff --git a/src/lib/components/FormModel/children/Form/UI/Decimal/decimal.component.js b/src/lib/components/FormModel/children/Form/UI/Decimal/decimal.component.js index 13e0eaae..453edc9d 100644 --- a/src/lib/components/FormModel/children/Form/UI/Decimal/decimal.component.js +++ b/src/lib/components/FormModel/children/Form/UI/Decimal/decimal.component.js @@ -21,7 +21,10 @@ export const Decimal = props => { setValue(event.target.value); }; - const onBlur = () => updateData(id, value); + const onBlur = () => { + const updatedPart = { ...data, value }; + updateData(id, updatedPart); + }; return (
diff --git a/src/lib/components/FormModel/children/Form/UI/Email/email.component.js b/src/lib/components/FormModel/children/Form/UI/Email/email.component.js index 792d4800..06cda49f 100644 --- a/src/lib/components/FormModel/children/Form/UI/Email/email.component.js +++ b/src/lib/components/FormModel/children/Form/UI/Email/email.component.js @@ -25,7 +25,10 @@ export const Email = (props: Props) => { const onChange = event => setValue(event.target.value); - const onBlur = () => updateData(id, value); + const onBlur = () => { + const updatedPart = { ...data, value }; + updateData(id, updatedPart); + }; return (
diff --git a/src/lib/components/FormModel/children/Form/UI/Float/float.component.js b/src/lib/components/FormModel/children/Form/UI/Float/float.component.js index f87bf830..4c44593b 100644 --- a/src/lib/components/FormModel/children/Form/UI/Float/float.component.js +++ b/src/lib/components/FormModel/children/Form/UI/Float/float.component.js @@ -25,7 +25,10 @@ export const Float = (props: Props) => { const onChange = event => setValue(event.target.value); - const onBlur = () => updateData(id, value); + const onBlur = () => { + const updatedPart = { ...data, value }; + updateData(id, updatedPart); + }; return (
diff --git a/src/lib/components/FormModel/children/Form/UI/Input/input.component.js b/src/lib/components/FormModel/children/Form/UI/Input/input.component.js index c35cdf56..62860146 100644 --- a/src/lib/components/FormModel/children/Form/UI/Input/input.component.js +++ b/src/lib/components/FormModel/children/Form/UI/Input/input.component.js @@ -22,7 +22,8 @@ export const Input = props => { }; const onBlur = () => { - updateData(id, value); + const updatedPart = { ...data, value }; + updateData(id, updatedPart); }; return ( diff --git a/src/lib/components/FormModel/children/Form/UI/Integer/integer.component.js b/src/lib/components/FormModel/children/Form/UI/Integer/integer.component.js index 89586333..9be71739 100644 --- a/src/lib/components/FormModel/children/Form/UI/Integer/integer.component.js +++ b/src/lib/components/FormModel/children/Form/UI/Integer/integer.component.js @@ -26,7 +26,10 @@ export const Integer = (props: Props) => { if (event.target.value === '' || re.test(event.target.value)) setValue(event.target.value); }; - const onBlur = () => updateData(id, value); + const onBlur = () => { + const updatedPart = { ...data, value }; + updateData(id, updatedPart); + }; return (
diff --git a/src/lib/components/FormModel/children/Form/UI/Phone/phone.component.js b/src/lib/components/FormModel/children/Form/UI/Phone/phone.component.js index 2f1ef5b7..2ff30f04 100644 --- a/src/lib/components/FormModel/children/Form/UI/Phone/phone.component.js +++ b/src/lib/components/FormModel/children/Form/UI/Phone/phone.component.js @@ -25,7 +25,10 @@ export const Phone = (props: Props) => { const onChange = event => setValue(event.target.value); - const onBlur = () => updateData(id, value); + const onBlur = () => { + const updatedPart = { ...data, value }; + updateData(id, updatedPart); + }; return (
diff --git a/src/lib/components/FormModel/children/Form/UI/RadioButton/radio-button.component.js b/src/lib/components/FormModel/children/Form/UI/RadioButton/radio-button.component.js index db3f27b5..8ea57f3f 100644 --- a/src/lib/components/FormModel/children/Form/UI/RadioButton/radio-button.component.js +++ b/src/lib/components/FormModel/children/Form/UI/RadioButton/radio-button.component.js @@ -18,7 +18,10 @@ export const RadioButton = (props: Props) => { const onChange = event => setValue(event.target.value); - const onBlur = () => updateData(id, value); + const onBlur = () => { + const updatedPart = { ...data, value }; + updateData(id, updatedPart); + }; return (
diff --git a/src/lib/components/FormModel/children/Form/UI/TextArea/text-area.component.js b/src/lib/components/FormModel/children/Form/UI/TextArea/text-area.component.js index c5c2672c..a6558fa9 100644 --- a/src/lib/components/FormModel/children/Form/UI/TextArea/text-area.component.js +++ b/src/lib/components/FormModel/children/Form/UI/TextArea/text-area.component.js @@ -19,7 +19,10 @@ export const TextArea = (props: Props) => { const onChange = event => setValue(event.target.value); - const onBlur = () => updateData(id, value); + const onBlur = () => { + const updatedPart = { ...data, value }; + updateData(id, updatedPart); + }; return (
diff --git a/src/lib/components/FormModel/form-model.component.js b/src/lib/components/FormModel/form-model.component.js index 341fa320..ed2b20bc 100644 --- a/src/lib/components/FormModel/form-model.component.js +++ b/src/lib/components/FormModel/form-model.component.js @@ -70,8 +70,7 @@ export const FormModel = (props: FormProps) => { const saveChanges = async () => { if (Object.keys(pendingChanges).length === 0) return; - for (const [id, self] of Object.entries(pendingChanges)) { - const name = formModel[UI.PARTS][id][UI.NAME]; + for (const [name, self] of Object.entries(pendingChanges)) { /* besides retrieving the updated parts ('formObject') also adds the new part to the formObject */ actions.retrieveNewFormObject(name, self); } From 78bd5f7b469b1b12f1540e1f63eed9001baacbf5 Mon Sep 17 00:00:00 2001 From: Jordan Fabian Valdez Date: Mon, 13 Jan 2020 13:28:22 -0600 Subject: [PATCH 2/5] Updates on group --- .../FormModel/children/Form/UI/Input/input.component.js | 3 +++ .../FormModel/children/Form/UI/component-mapping.js | 2 +- .../components/FormModel/children/Group/group.component.js | 2 +- .../FormModel/children/Multiple/multiple.component.js | 6 ++++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/lib/components/FormModel/children/Form/UI/Input/input.component.js b/src/lib/components/FormModel/children/Form/UI/Input/input.component.js index 62860146..40be2930 100644 --- a/src/lib/components/FormModel/children/Form/UI/Input/input.component.js +++ b/src/lib/components/FormModel/children/Form/UI/Input/input.component.js @@ -5,6 +5,7 @@ import { ThemeContext } from '@context'; import { UI, RDF, InputTextTypes } from '@constants'; export const Input = props => { + console.log(props); const { id, data, updateData } = props; const { theme } = useContext(ThemeContext); @@ -23,6 +24,8 @@ export const Input = props => { const onBlur = () => { const updatedPart = { ...data, value }; + console.log(id); + console.log(updatedPart); updateData(id, updatedPart); }; diff --git a/src/lib/components/FormModel/children/Form/UI/component-mapping.js b/src/lib/components/FormModel/children/Form/UI/component-mapping.js index 68a92881..6afa0f22 100644 --- a/src/lib/components/FormModel/children/Form/UI/component-mapping.js +++ b/src/lib/components/FormModel/children/Form/UI/component-mapping.js @@ -31,5 +31,5 @@ export const Mapping = { [VOCAB.UI.PhoneField]: Phone, [VOCAB.UI.ColorField]: ColorPicker, [VOCAB.UI.Multiple]: Multiple, - [VOCAB.UI.Group]: Group + [VOCAB.UI.Group]: Multiple }; diff --git a/src/lib/components/FormModel/children/Group/group.component.js b/src/lib/components/FormModel/children/Group/group.component.js index f9519194..12f4c9c0 100644 --- a/src/lib/components/FormModel/children/Group/group.component.js +++ b/src/lib/components/FormModel/children/Group/group.component.js @@ -19,12 +19,12 @@ export const Group = (props: Props) => { const { data, updateData, mapper, savingData } = props; const { theme } = useContext(ThemeContext); + console.log(data); return (
{Object.entries(data).map(([, part]) => { const { [RDF.TYPE]: type, [UI.NAME]: name } = part; const Component = mapper[type]; - if (!Component) return null; /* if this component is being saved right now */ diff --git a/src/lib/components/FormModel/children/Multiple/multiple.component.js b/src/lib/components/FormModel/children/Multiple/multiple.component.js index e3c53d91..647be880 100644 --- a/src/lib/components/FormModel/children/Multiple/multiple.component.js +++ b/src/lib/components/FormModel/children/Multiple/multiple.component.js @@ -20,12 +20,14 @@ type Props = { export const Multiple = (props: Props) => { const { id, data, updateData, mapper, savingData } = props; const { theme } = useContext(ThemeContext); - /** * A multiple should **not** have a 'parts' predicate, however the current implementation * links the data in it. */ - const { [UI.LABEL]: label, [UI.PARTS]: parts } = data; + const { + [UI.LABEL]: label, + [data[RDF.TYPE].includes('Group') ? UI.PARTS : UI.PART]: parts + } = data; /** * TODO: check if this is the right behaviour for when the pod does not have data From 655fbc954993d9501391514514a78e501509db6f Mon Sep 17 00:00:00 2001 From: James Martin Date: Thu, 16 Jan 2020 17:02:02 -0500 Subject: [PATCH 3/5] Fixed a bunch of issues with the form like styles, saving, and various other changes --- src/demo/App.js | 8 +- .../Form/UI/CheckBox/check-box.component.js | 1 + .../UI/Classifier/classifier.component.js | 114 ++++++++++-------- .../children/Form/UI/Input/input.component.js | 10 +- .../children/Form/UI/Multiple/index.js | 3 - .../Form/UI/Multiple/multiple.component.js | 8 -- .../Form/UI/Multiple/multiple.styles.js | 0 .../Form/UI/TextArea/text-area.component.js | 3 +- .../children/Form/UI/component-mapping.js | 4 +- .../children/Group/group.component.js | 16 +-- .../children/Multiple/multiple.component.js | 95 +++++++++------ .../FormModel/form-model.component.js | 107 +++++++++++++--- src/lib/constants/index.js | 5 +- 13 files changed, 238 insertions(+), 136 deletions(-) delete mode 100644 src/lib/components/FormModel/children/Form/UI/Multiple/index.js delete mode 100644 src/lib/components/FormModel/children/Form/UI/Multiple/multiple.component.js delete mode 100644 src/lib/components/FormModel/children/Form/UI/Multiple/multiple.styles.js diff --git a/src/demo/App.js b/src/demo/App.js index b0880b5c..97da8633 100644 --- a/src/demo/App.js +++ b/src/demo/App.js @@ -167,13 +167,15 @@ const App = () => { { {label} { + const { id, data, updateData } = props; + const { theme } = useContext(ThemeContext); + + const { + [UI.LABEL]: label, + [UI.VALUE]: initialValue, + [UI.CATEGORY]: category, + [UI.VALUES]: values + } = data; -const Classifier = ({ - value, - id, - modifyFormObject, - formObject, - onSave, - autoSave, - onBlur, - ...rest -}: Props) => { const [options, setOptions] = useState([]); - const from = rest['ui:category'] || null; - const label = rest['ui:label'] || ''; + const [value, setValue] = useState(initialValue); + /** + * Init function to make use of async + * This function fetches the classifier option list from a helper, or returns the list of hardcoded values + * if such a list exists as a prop + * @returns {Promise} + */ const init = async () => { - const values = rest['ui:values']; - let docOptions = []; - if (from) { - docOptions = await n3Helper.getClassifierOptions(from); + let optionsList = []; + if (category) { + optionsList = await n3Helper.getClassifierOptions(category); } else { - docOptions = values ? [...values] : []; + optionsList = values ? [...values] : []; } - setOptions(docOptions); + setOptions(optionsList); }; - const getValueFromObject = useCallback(value => { - return typeof value === 'object' ? value.value : value; - }); + /** + * Initialize data for the dropdown + */ + useEffect(() => { + init(); + }, []); + /** + * Fetch a user-friendly label for the option. If the option is a link, this returns the predicate name + * @type {function(string): string} + */ const getDropDownLabel = useCallback((value: string) => { return value && value.includes('#') ? value.split('#')[1] : value; }); + const onChange = async event => { + await setValue(event.target.value); + }; + + useEffect(() => { + if (value !== initialValue) { + const updatedPart = { ...data, value }; + console.log('updatedPart', updatedPart); + updateData(id, updatedPart); + } + }, [value]); + + /* + const getValueFromObject = useCallback(value => { + return typeof value === 'object' ? value.value : value; + }); + const onChange = ({ target }) => { const obj = { value: target.value, ...rest }; modifyFormObject(id, obj); }; + console.log(formObject); const actualValue = formObject[id] || formObject[id] === '' ? getValueFromObject(formObject[id].value) : value; - useEffect(() => { - init(); - }, []); +*/ return ( - - {({ theme }) => ( - - - - - )} - + + + + ); }; diff --git a/src/lib/components/FormModel/children/Form/UI/Input/input.component.js b/src/lib/components/FormModel/children/Form/UI/Input/input.component.js index 40be2930..31e9809b 100644 --- a/src/lib/components/FormModel/children/Form/UI/Input/input.component.js +++ b/src/lib/components/FormModel/children/Form/UI/Input/input.component.js @@ -1,11 +1,9 @@ import React, { useContext, useState } from 'react'; - +import { InputGroup } from './input.styles'; import { ThemeContext } from '@context'; - import { UI, RDF, InputTextTypes } from '@constants'; export const Input = props => { - console.log(props); const { id, data, updateData } = props; const { theme } = useContext(ThemeContext); @@ -24,13 +22,11 @@ export const Input = props => { const onBlur = () => { const updatedPart = { ...data, value }; - console.log(id); - console.log(updatedPart); updateData(id, updatedPart); }; return ( -
+ { onBlur }} /> -
+ ); }; diff --git a/src/lib/components/FormModel/children/Form/UI/Multiple/index.js b/src/lib/components/FormModel/children/Form/UI/Multiple/index.js deleted file mode 100644 index f6a6fcc5..00000000 --- a/src/lib/components/FormModel/children/Form/UI/Multiple/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import { Multiple } from './multiple.component'; - -export default Multiple; diff --git a/src/lib/components/FormModel/children/Form/UI/Multiple/multiple.component.js b/src/lib/components/FormModel/children/Form/UI/Multiple/multiple.component.js deleted file mode 100644 index 595c55b4..00000000 --- a/src/lib/components/FormModel/children/Form/UI/Multiple/multiple.component.js +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; - -export const Multiple = ({ field, addNewField, className }) => - field['rdf:type'].includes('Multiple') && ( - - ); diff --git a/src/lib/components/FormModel/children/Form/UI/Multiple/multiple.styles.js b/src/lib/components/FormModel/children/Form/UI/Multiple/multiple.styles.js deleted file mode 100644 index e69de29b..00000000 diff --git a/src/lib/components/FormModel/children/Form/UI/TextArea/text-area.component.js b/src/lib/components/FormModel/children/Form/UI/TextArea/text-area.component.js index a6558fa9..3a51a4cb 100644 --- a/src/lib/components/FormModel/children/Form/UI/TextArea/text-area.component.js +++ b/src/lib/components/FormModel/children/Form/UI/TextArea/text-area.component.js @@ -32,7 +32,8 @@ export const TextArea = (props: Props) => { id, value, onChange, - onBlur + onBlur, + maxLength }} />
diff --git a/src/lib/components/FormModel/children/Form/UI/component-mapping.js b/src/lib/components/FormModel/children/Form/UI/component-mapping.js index 6afa0f22..4959493d 100644 --- a/src/lib/components/FormModel/children/Form/UI/component-mapping.js +++ b/src/lib/components/FormModel/children/Form/UI/component-mapping.js @@ -14,6 +14,7 @@ import { Integer } from './Integer'; import { ColorPicker } from './ColorPicker'; import { Multiple } from '../../Multiple'; import { Group } from '../../Group'; +import Classifier from './Classifier'; export const Mapping = { [VOCAB.UI.Heading]: Heading, @@ -31,5 +32,6 @@ export const Mapping = { [VOCAB.UI.PhoneField]: Phone, [VOCAB.UI.ColorField]: ColorPicker, [VOCAB.UI.Multiple]: Multiple, - [VOCAB.UI.Group]: Multiple + [VOCAB.UI.Group]: Group, + [VOCAB.UI.Classifier]: Classifier }; diff --git a/src/lib/components/FormModel/children/Group/group.component.js b/src/lib/components/FormModel/children/Group/group.component.js index 12f4c9c0..5c7f20ff 100644 --- a/src/lib/components/FormModel/children/Group/group.component.js +++ b/src/lib/components/FormModel/children/Group/group.component.js @@ -1,12 +1,13 @@ -import React, { useContext } from 'react'; +import React from 'react'; import { UI, RDF } from '@constants'; -import { ThemeContext } from '@context'; type Props = { data: object, updateData: (string, string) => void, mapper: object, + addNewField: string => void, + deleteField: string => void, savingData: { autosaveIndicator: React.Component, running: boolean, @@ -16,15 +17,14 @@ type Props = { }; export const Group = (props: Props) => { - const { data, updateData, mapper, savingData } = props; - const { theme } = useContext(ThemeContext); + const { data, updateData, mapper, savingData, addNewField, deleteField } = props; - console.log(data); return ( -
+
{Object.entries(data).map(([, part]) => { const { [RDF.TYPE]: type, [UI.NAME]: name } = part; const Component = mapper[type]; + if (!Component) return null; /* if this component is being saved right now */ @@ -34,13 +34,15 @@ export const Group = (props: Props) => { if (savingData.running && savingThis) Indicator = savingData.autosaveIndicator; return ( -
+
void, mapper: object, + addNewField: string => void, + deleteField: string => void, savingData: { autosaveIndicator: React.Component, running: boolean, @@ -18,45 +21,65 @@ type Props = { }; export const Multiple = (props: Props) => { - const { id, data, updateData, mapper, savingData } = props; + const { id, data, updateData, mapper, savingData, addNewField, deleteField } = props; const { theme } = useContext(ThemeContext); - /** - * A multiple should **not** have a 'parts' predicate, however the current implementation - * links the data in it. - */ - const { - [UI.LABEL]: label, - [data[RDF.TYPE].includes('Group') ? UI.PARTS : UI.PART]: parts - } = data; - - /** - * TODO: check if this is the right behaviour for when the pod does not have data - */ - if (!parts) { - const { [UI.PART]: part } = data; - const { [RDF.TYPE]: partType } = part; - const Component = mapper[partType]; - - if (!Component) return null; - - return ( -
- -
- ); - } // TODO: should render the single 'ui:part'? + const { [UI.LABEL]: label, [UI.PART]: part } = data; + + const parts = []; + + // Get list of parts for the + Object.keys(part).forEach(item => { + parts.push(part[item]); + }); + + // Quick and dirty setup of custom classes. + // TODO: Refactor this + let classes = ''; + if (theme) { + if (theme.form) { + classes += theme.form; + } + if (theme.childGroup) { + if (classes.length > 0) { + classes += ' '; + } + classes += theme.childGroup; + } + } return ( -
+

{label}

- + {parts.map(item => { + // Fetch the name from the object for a unique key + const key = item[UI.NAME]; + const type = VOCAB.UI.Group; + return ( +
+ + +
+ ); + })} + +
); }; diff --git a/src/lib/components/FormModel/form-model.component.js b/src/lib/components/FormModel/form-model.component.js index ed2b20bc..7fa30e2b 100644 --- a/src/lib/components/FormModel/form-model.component.js +++ b/src/lib/components/FormModel/form-model.component.js @@ -5,7 +5,7 @@ import { useLiveUpdate } from '@solid/react'; import { ThemeContext } from '@context'; import { UI } from '@constants'; -import { SolidError } from '@utils'; +import { SolidError, solidResponse } from '@utils'; import { Mapping } from './children/Form/UI/component-mapping'; import { Group } from './children/Group'; @@ -18,7 +18,14 @@ type FormProps = { autosave: boolean, theme: object, autosaveIndicator: React.Component - } + }, + onInit: () => void, + onLoaded: () => void, + onError: () => void, + onSuccess: () => void, + onSave: () => void, + onAddNewField: () => void, + onDelete: () => void }; /** @@ -35,7 +42,19 @@ type FormProps = { * {React.Component} spinner component indicating whether the saving process has been completed or nor */ export const FormModel = (props: FormProps) => { - const { modelSource, dataSource, customComponents, options } = props; + const { + modelSource, + dataSource, + customComponents, + options, + onAddNewField, + onDelete, + onError, + onSave, + onInit, + onLoaded, + onSuccess + } = props; const { autosave, theme, autosaveIndicator } = options; @@ -52,6 +71,10 @@ export const FormModel = (props: FormProps) => { const actions = new FormActions(formModel, {}); const timestamp = useLiveUpdate(); + const init = async () => { + if (onInit) onInit(); + }; + /** * Updates the list of values changed by the user and that are yet to update in the pod * @param {string} name unique identifier for this part ('ui:name') @@ -63,6 +86,34 @@ export const FormModel = (props: FormProps) => { setPendingChanges({ ...pendingChanges, [name]: self }); }; + /** + * Create a new set of fields, for when a user wants to add a new set of fields in a Multiple, e.g. Address fields + * @param id + */ + const addNewField = id => { + try { + const updatedFormModelObject = actions.addNewField(id); + setFormModel(updatedFormModelObject); + onAddNewField(solidResponse(200, 'New field successfully added')); + } catch (error) { + onError(new SolidError(error, 'Error adding new field', 500)); + } + }; + + /** + * Delete an existing set of fields, such as an Address. This currently only supports deleting Groups + * @param id + */ + const deleteField = async id => { + try { + const updatedFormModelObject = await actions.deleteField(id); + setFormModel(updatedFormModelObject); + onDelete(solidResponse(200, 'Field successfully deleted')); + } catch (error) { + onError(new SolidError(error, 'Error deleting field', 500)); + } + }; + /** * Builds a 'formObject' (list of parts with updated values) for 'actions' to use as an input for * saving the data back into the pod @@ -81,14 +132,26 @@ export const FormModel = (props: FormProps) => { setFormModel(updatedModel); setPendingChanges({}); setSavingState({ errored: false, running: false }); + onSave(); } catch (e) { setSavingState({ errored: true, running: false }); + onError(new SolidError(e, 'Error saving form', 500)); } }; + /** + * Initialize the form, and execute the onInit callback + */ + useEffect(() => { + init(); + }, []); + /* Create a new model if any of the sources changes */ useEffect(() => { - formUi.convertFormModel(modelSource, dataSource).then(model => setFormModel(model)); + formUi.convertFormModel(modelSource, dataSource).then(model => { + setFormModel(model); + if (onLoaded) onLoaded(); + }); }, [modelSource, dataSource]); useEffect(() => { @@ -101,8 +164,10 @@ export const FormModel = (props: FormProps) => { */ useEffect(() => { formUi - .mapFormModelWithData(formModel, modelSource) - .then(model => setFormModel(model)) + .mapFormModelWithData(modelSource, dataSource) + .then(model => { + setFormModel(model); + }) .catch(e => new SolidError('Error while saving data', e, 500)); }, [timestamp]); @@ -113,19 +178,23 @@ export const FormModel = (props: FormProps) => { return ( - +
+ +
); }; diff --git a/src/lib/constants/index.js b/src/lib/constants/index.js index e3b99dcf..eb830a18 100644 --- a/src/lib/constants/index.js +++ b/src/lib/constants/index.js @@ -29,7 +29,8 @@ export const VOCAB = { PhoneField: 'http://www.w3.org/ns/ui#PhoneField', TriStateField: 'http://www.w3.org/ns/ui#TriStateField', Multiple: 'http://www.w3.org/ns/ui#Multiple', - Group: 'http://www.w3.org/ns/ui#Group' + Group: 'http://www.w3.org/ns/ui#Group', + Classifier: 'http://www.w3.org/ns/ui#Classifier' } }; @@ -43,7 +44,9 @@ export const UI = { PARTS: `${uiBase}parts`, PART: `${uiBase}part`, VALUE: `${uiBase}value`, + VALUES: `${uiBase}values`, CONTENTS: `${uiBase}contents`, + CATEGORY: `${uiBase}category`, NAME: `${uiBase}name`, LABEL: `${uiBase}label`, MAX_LENGTH: `${uiBase}maxLength`, From 14c47e2ff3bc69835ef0c6ca4d2eeab866c293a7 Mon Sep 17 00:00:00 2001 From: James Martin Date: Thu, 16 Jan 2020 18:02:47 -0500 Subject: [PATCH 4/5] Adding theme/style code to various components --- .../FormModel/children/Form/UI/Email/email.component.js | 5 +++-- .../FormModel/children/Form/UI/Phone/phone.component.js | 5 +++-- .../children/Form/UI/TextArea/text-area.component.js | 6 +++--- .../FormModel/children/Multiple/multiple.component.js | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/lib/components/FormModel/children/Form/UI/Email/email.component.js b/src/lib/components/FormModel/children/Form/UI/Email/email.component.js index 06cda49f..d282221b 100644 --- a/src/lib/components/FormModel/children/Form/UI/Email/email.component.js +++ b/src/lib/components/FormModel/children/Form/UI/Email/email.component.js @@ -1,6 +1,7 @@ import React, { useState, useContext } from 'react'; import { InputTextTypes, UI, RDF } from '@constants'; import { ThemeContext } from '@context'; +import { InputGroup } from '../Input/input.styles'; type Props = { id: string, @@ -31,7 +32,7 @@ export const Email = (props: Props) => { }; return ( -
+ { onBlur }} /> -
+ ); }; diff --git a/src/lib/components/FormModel/children/Form/UI/Phone/phone.component.js b/src/lib/components/FormModel/children/Form/UI/Phone/phone.component.js index 2ff30f04..ac1aad33 100644 --- a/src/lib/components/FormModel/children/Form/UI/Phone/phone.component.js +++ b/src/lib/components/FormModel/children/Form/UI/Phone/phone.component.js @@ -1,6 +1,7 @@ import React, { useState, useContext } from 'react'; import { InputTextTypes, UI, RDF } from '@constants'; import { ThemeContext } from '@context'; +import { InputGroup } from '../Input/input.styles'; type Props = { id: string, @@ -31,7 +32,7 @@ export const Phone = (props: Props) => { }; return ( -
+ { onBlur }} /> -
+ ); }; diff --git a/src/lib/components/FormModel/children/Form/UI/TextArea/text-area.component.js b/src/lib/components/FormModel/children/Form/UI/TextArea/text-area.component.js index 3a51a4cb..1ca58fb9 100644 --- a/src/lib/components/FormModel/children/Form/UI/TextArea/text-area.component.js +++ b/src/lib/components/FormModel/children/Form/UI/TextArea/text-area.component.js @@ -1,7 +1,7 @@ import React, { useState, useContext } from 'react'; import { ThemeContext } from '@context'; - import { UI } from '@constants'; +import { TextAreaGroup } from './text-area.styles'; type Props = { id: string, @@ -25,7 +25,7 @@ export const TextArea = (props: Props) => { }; return ( -
+