diff --git a/README.md b/README.md index 68ff79b7..6ce1a6ed 100644 --- a/README.md +++ b/README.md @@ -161,36 +161,62 @@ Here's an example of a basic ProfileUploader component, demonstrating how to add We currently re-expose withWebId and LogoutButton so you can use the basic components without installing other libraries. -### ShexFormBuilder +### ShExFormBuilder + **Note**: This is an early preview build of a work-in-progress component and subject to large-scale changes in future releases. This component allows you to create a fully functional form, complete with submit, cancel, and validation rules, from a [ShEx](http://shex.io/shex-primer/index.html) Shape. +#### Supported Field Types: + +##### Textbox +Textboxes are the default input type for each field in a shape. In future versions, there will be a way to determine if you want a textbox vs a textarea based on properties such as maxlength. + +##### Select / Dropdown +Dropdowns are displayed when the shape has a reference to another shape that is only a list of values. The values are displayed in the dropdown. + + +#### Validation +Validation is done using ShEx constraints. You can read more about these constraints on the [ShEx website](http://shex.io/). Examples include: + +* Required vs Optional fields. +* Repeatable fields, and the min/max number of times they can be repeated. +* Min and/or max length of strings. +* Length of numbers, and min/max number values. +* Regular expression patterns. + +#### Labels +Currently, labels are assigned to a field by either: + +* Adding an rdfs:label annotation to the field in the ShEx shape (see [example shapes](https://shexshapes.inrupt.net/public/) for examples). +* Parsing the name of the predicate assigned to that field. + +In the future, labels will be generated more dynamically. -Usage: +#### Usage ``` ``` -| Props | Type | Default | Description | -| ------------------ | -------- | --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| documentUri | string | null | Required. The URL representing the root subject to save the form data to, for example a webID or file in the user's pod. | -| shexUri | string | null | Required. The URL to the shex shape to use to render the form | -| rootShape | string | null | Optional. The shape in the shexUri file to begin parsing. If a START shape is defined in the shape, this is not necessary. | -| theme | Object | null | Optional. An object (defined below) allowing custom overrides to the look and feel of the form +| Props | Type | Default | Description +| ------------------ | -------- | --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- +| documentUri | string | null | Required. The URL representing the root subject to save the form data to, for example a WebID or file in the user's Pod. +| shexUri | string | null | Required. The URL to the ShEx shape to use to render the form. +| rootShape | string | null | Optional. The shape in the shexUri file to begin parsing. If a START shape is defined in the shape, this is not necessary. +| theme | Object | null | Optional. An object (defined below) allowing custom overrides to the look and feel of the form. | language | string | null | Optional. The language identifier to translate text. For example, 'en' or 'es'. | successCallback | Function | Function that writes a success message to console | Optional. Overrides the existing success callback and allows custom success functions. -| errorCallback | Function | Function that writes the error message to console | Optional. Overrides the existing error callback function -| messageValidation | Object | null | An Object containing an array of error strings. The error strings will be used in most non-validation situations +| errorCallback | Function | Function that writes the error message to console | Optional. Overrides the existing error callback function. +| messageValidation | Object | null | An Object containing an array of error strings. The error strings will be used in most non-validation situations. Theme object: | Key | Type | Default | Description -| ------------------ | -------- | ------------------------------------- | -------------------- -| input | string | solid-input-shex | Custom class name for input fields in the form -| select | string | solid-input-shex solid-select-shex | Custom class name for select fields in the form -| deleteButton | string | solid-button-shex | Custom class name for the delete button -| form | string | solid-shex-form | Custom class name for the form +| ------------------ | -------- | ------------------------------------- | ------------------------------------------------ +| input | string | solid-input-shex | Custom class name for input fields in the form. +| select | string | solid-input-shex solid-select-shex | Custom class name for select fields in the form. +| deleteButton | string | solid-button-shex | Custom class name for the delete button. +| form | string | solid-shex-form | Custom class name for the form. ##### Shapes A set of example shapes can be found [here](https://shexshapes.inrupt.net/public/), which show various ShEx shapes. \ No newline at end of file diff --git a/package.json b/package.json index d8a27f9e..be9bc79e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@inrupt/solid-react-components", - "version": "0.3.2", + "version": "0.4.0-rc.1", "description": "Solid React Components", "main": "build/index.js", "scripts": { diff --git a/src/demo/components/HandleShexForm/handle-shex-form.component.js b/src/demo/components/HandleShexForm/handle-shex-form.component.js index b3f6dcc4..3794b37f 100644 --- a/src/demo/components/HandleShexForm/handle-shex-form.component.js +++ b/src/demo/components/HandleShexForm/handle-shex-form.component.js @@ -40,9 +40,11 @@ const HandleShexForm = ({ webId }:Props) => { // By default addButton and deleteButton will be Add new and Delete const languageTheme = { language: 'en', - addButtonText: '+ Add new ', - deleteButton: 'Delete', - dropdownDefaultText: '- Select -' + saveBtn: "Save", + resetBtn: "Reset", + addButtonText: "+ Add new ", + deleteButton: "Delete", + dropdownDefaultText: "- Select -" }; return( diff --git a/src/lib/components/ShexFormBuilder/shex-form-builder.component.js b/src/lib/components/ShexFormBuilder/shex-form-builder.component.js index 7db461c1..1a44767d 100644 --- a/src/lib/components/ShexFormBuilder/shex-form-builder.component.js +++ b/src/lib/components/ShexFormBuilder/shex-form-builder.component.js @@ -12,7 +12,7 @@ type Props = { shexUri: String, rootShape: String, theme: Object, - language: String + languageTheme: Object }; const ShexFormBuilder = ({ @@ -70,6 +70,8 @@ const ShexFormBuilder = ({ if (!formError) { updateShexJ(deleted, "delete"); successCallback(); + } else { + errorCallback(); } } catch (e) { errorCallback(e); @@ -86,7 +88,6 @@ const ShexFormBuilder = ({ errorCallback(e); } }); - return ( @@ -103,9 +104,9 @@ const ShexFormBuilder = ({ }} /> )} - + @@ -121,6 +122,14 @@ ShexFormBuilder.defaultProps = { select: "solid-input-shex solid-select-shex", deleteButton: "solid-button-shex", form: "solid-shex-form" + }, + languageTheme: { + language: "en", + saveBtn: "Save", + resetBtn: "Reset", + addButtonText: "+ Add new ", + deleteButton: "Delete", + dropdownDefaultText: "- Select -" } }; diff --git a/src/lib/hooks/useForm.js b/src/lib/hooks/useForm.js index d36cb259..ef20aad9 100644 --- a/src/lib/hooks/useForm.js +++ b/src/lib/hooks/useForm.js @@ -30,7 +30,7 @@ export const useForm = (documentUri: String) => { parentName: e.target.getAttribute('data-parent-name') } }; - + onError(null); setFormValues({ ...formValues, ...data }); }; @@ -189,6 +189,7 @@ export const useForm = (documentUri: String) => { const onSubmit = async (e: Event) => { try { + onError(null); if (!documentUri || documentUri === "") { throw Error("Document Uri is required"); } @@ -241,10 +242,12 @@ export const useForm = (documentUri: String) => { return true; } else { setFormValues({...updatedFields}); - return false; + if (keys.length !== 0) { + onError('Please ensure all values are in a proper format.'); + } } } catch (error) { - throw Error(error); + onError(error); } }; diff --git a/src/lib/hooks/useShex.js b/src/lib/hooks/useShex.js index 171a2471..8752eded 100644 --- a/src/lib/hooks/useShex.js +++ b/src/lib/hooks/useShex.js @@ -310,10 +310,10 @@ export const useShex = (fileShex: String, documentUri: String, rootShape: String if (newExpressions[i]._formValues[y]._formFocus.name === options.key) { if (action === 'delete') { - // If field is the last one will keep it but will update value and name - let toIndex = newExpressions[i]._formValues.length === 1 ? 1 : 0; + const _formValues = newExpressions[i]._formValues; + const currentFieldName = newExpressions[i]._formValues[y]._formFocus.name; - newExpressions[i]._formValues.splice(y, y + toIndex); + newExpressions[i]._formValues = _formValues.filter(val => val._formFocus.name !== currentFieldName); } else { newExpressions[i]._formValues[y] = {