From e3a795e40d949db9452d7b201fc1fa9ddd2dbd29 Mon Sep 17 00:00:00 2001 From: Maciej Lenartowicz Date: Thu, 10 Oct 2019 15:25:00 +0000 Subject: [PATCH 1/5] Client configuration --- package-lock.json | 2 +- package.json | 2 +- src/api/post.js | 9 ++- src/bootstrap/CheckBox.js | 2 +- src/bootstrap/FileInput.js | 34 ++++++++ src/bootstrap/FileInput.md | 15 ++++ src/bootstrap/Input.js | 32 ++++---- src/bootstrap/RadioSet.js | 2 +- src/bootstrap/Select.js | 2 +- .../__snapshots__/NumberInput.test.js.snap | 78 +++++++++---------- .../__snapshots__/PasswordInput.test.js.snap | 44 +++++------ .../__snapshots__/TextInput.test.js.snap | 42 +++++----- src/form/hooks.js | 23 ++++-- src/index.js | 3 +- 14 files changed, 170 insertions(+), 120 deletions(-) create mode 100644 src/bootstrap/FileInput.js create mode 100644 src/bootstrap/FileInput.md diff --git a/package-lock.json b/package-lock.json index b01e18d..081c0c2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "foris", - "version": "1.0.0", + "version": "1.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 8da249a..88f307d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "foris", - "version": "1.0.0", + "version": "1.1.0", "description": "Set of components and utils for Foris and its plugins.", "author": "CZ.NIC, z.s.p.o.", "repository": { diff --git a/src/api/post.js b/src/api/post.js index 705356e..6a3933a 100644 --- a/src/api/post.js +++ b/src/api/post.js @@ -12,7 +12,7 @@ import { API_ACTIONS, TIMEOUT, HEADERS, APIReducer, getErrorMessage, } from "./utils"; -export function useAPIPost(url) { +export function useAPIPost(url, contentType) { const [state, dispatch] = useReducer(APIReducer, { isSending: false, isError: false, @@ -20,12 +20,17 @@ export function useAPIPost(url) { data: null, }); + const headers = { ...HEADERS }; + if (contentType) { + headers["Content-Type"] = contentType; + } + const post = async (data) => { dispatch({ type: API_ACTIONS.INIT }); try { const result = await axios.post(url, data, { timeout: TIMEOUT, - headers: HEADERS, + headers, }); dispatch({ type: API_ACTIONS.SUCCESS, payload: result.data }); } catch (error) { diff --git a/src/bootstrap/CheckBox.js b/src/bootstrap/CheckBox.js index 8cc4658..02f336c 100644 --- a/src/bootstrap/CheckBox.js +++ b/src/bootstrap/CheckBox.js @@ -7,7 +7,7 @@ import React from "react"; import PropTypes from "prop-types"; -import { useUID } from "react-uid/dist/es5/index"; +import { useUID } from "react-uid"; import { formFieldsSize } from "./constants"; diff --git a/src/bootstrap/FileInput.js b/src/bootstrap/FileInput.js new file mode 100644 index 0000000..b66fcba --- /dev/null +++ b/src/bootstrap/FileInput.js @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/) + * + * This is free software, licensed under the GNU General Public License v3. + * See /LICENSE for more information. + */ + +import React from "react"; + +import PropTypes from "prop-types"; +import { Input } from "./Input"; + +FileInput.propTypes = { + /** Field label. */ + label: PropTypes.string.isRequired, + /** Error message. */ + error: PropTypes.string, + /** Help text message. */ + helpText: PropTypes.string, + /** Email value. */ + value: PropTypes.string, +}; + +export function FileInput({ ...props }) { + return ( + + ); +} diff --git a/src/bootstrap/FileInput.md b/src/bootstrap/FileInput.md new file mode 100644 index 0000000..75d76df --- /dev/null +++ b/src/bootstrap/FileInput.md @@ -0,0 +1,15 @@ +Bootstrap component for file input. Includes label and has predefined sizes and structure for using in foris forms. + +All additional `props` are passed to the `` HTML component. + +```js +import {useState} from 'react'; +const [files, setFiles] = useState([]); + +setFiles(event.target.files)} +/> +``` diff --git a/src/bootstrap/Input.js b/src/bootstrap/Input.js index 6784503..d5715ba 100644 --- a/src/bootstrap/Input.js +++ b/src/bootstrap/Input.js @@ -6,7 +6,7 @@ */ import React from "react"; -import { useUID } from "react-uid/dist/es5/index"; +import { useUID } from "react-uid"; import PropTypes from "prop-types"; import { formFieldsSize } from "./constants"; @@ -21,31 +21,31 @@ Input.propTypes = { PropTypes.arrayOf(PropTypes.node), PropTypes.node, ]), + labelClassName: PropTypes.string, + groupClassName: PropTypes.string, }; /** Base bootstrap input component. */ export function Input({ - type, label, helpText, error, className, children, ...props + type, label, helpText, error, className, children, labelClassName, groupClassName, ...props }) { const uid = useUID(); const inputClassName = `form-control ${className || ""} ${(error ? "is-invalid" : "")}`.trim(); return ( -
-
- -
- + +
+ - {children} -
- {error ?
{error}
: null} - {helpText ? {helpText} : null} + {...props} + /> + {children}
+ {error ?
{error}
: null} + {helpText ? {helpText} : null}
); } diff --git a/src/bootstrap/RadioSet.js b/src/bootstrap/RadioSet.js index 9dae6a6..7125cb6 100644 --- a/src/bootstrap/RadioSet.js +++ b/src/bootstrap/RadioSet.js @@ -7,7 +7,7 @@ import React from "react"; import PropTypes from "prop-types"; -import { useUID } from "react-uid/dist/es5/index"; +import { useUID } from "react-uid"; import { formFieldsSize } from "./constants"; diff --git a/src/bootstrap/Select.js b/src/bootstrap/Select.js index cc89ca7..bc524c4 100644 --- a/src/bootstrap/Select.js +++ b/src/bootstrap/Select.js @@ -7,7 +7,7 @@ import React from "react"; import PropTypes from "prop-types"; -import { useUID } from "react-uid/dist/es5/index"; +import { useUID } from "react-uid"; Select.propTypes = { diff --git a/src/bootstrap/__tests__/__snapshots__/NumberInput.test.js.snap b/src/bootstrap/__tests__/__snapshots__/NumberInput.test.js.snap index 67cf590..9729a53 100644 --- a/src/bootstrap/__tests__/__snapshots__/NumberInput.test.js.snap +++ b/src/bootstrap/__tests__/__snapshots__/NumberInput.test.js.snap @@ -2,53 +2,49 @@ exports[` Render number input 1`] = `
-
- + Test label + +
+
- -
- - -
+ + +
- - Some help text -
+ + Some help text +
`; diff --git a/src/bootstrap/__tests__/__snapshots__/PasswordInput.test.js.snap b/src/bootstrap/__tests__/__snapshots__/PasswordInput.test.js.snap index 95f4fe1..3e1f0b7 100644 --- a/src/bootstrap/__tests__/__snapshots__/PasswordInput.test.js.snap +++ b/src/bootstrap/__tests__/__snapshots__/PasswordInput.test.js.snap @@ -2,32 +2,28 @@ exports[` Render password input 1`] = `
-
- -
- -
- - Some help text - + Test label + +
+
+ + Some help text +
`; diff --git a/src/bootstrap/__tests__/__snapshots__/TextInput.test.js.snap b/src/bootstrap/__tests__/__snapshots__/TextInput.test.js.snap index a248d52..e77509f 100644 --- a/src/bootstrap/__tests__/__snapshots__/TextInput.test.js.snap +++ b/src/bootstrap/__tests__/__snapshots__/TextInput.test.js.snap @@ -2,31 +2,27 @@ exports[` Render text input 1`] = `
-
- -
- -
- - Some help text - + Test label + +
+
+ + Some help text +
`; diff --git a/src/form/hooks.js b/src/form/hooks.js index 8bbbd66..3b14499 100644 --- a/src/form/hooks.js +++ b/src/form/hooks.js @@ -17,7 +17,7 @@ const FORM_ACTIONS = { resetData: 2, }; -export function useForm(validator, prepData) { +export function useForm(validator, dataPreprocessor) { const [state, dispatch] = useReducer(formReducer, { data: null, initialData: null, @@ -28,10 +28,10 @@ export function useForm(validator, prepData) { dispatch({ type: FORM_ACTIONS.resetData, data, - prepData, + dataPreprocessor, validator, }); - }, [prepData, validator]); + }, [dataPreprocessor, validator]); const onFormChangeHandler = useCallback((updateRule) => (event) => { dispatch({ @@ -41,6 +41,7 @@ export function useForm(validator, prepData) { validator, }); }, [validator]); + return [ state, onFormChangeHandler, @@ -61,12 +62,15 @@ function formReducer(state, action) { }; } case FORM_ACTIONS.resetData: { - if (!action.data) return { ...state, initialData: state.data }; - const prepData = action.prepData ? action.prepData(action.data) : action.data; + if (!action.data) { + return { ...state, initialData: state.data }; + } + + const data = action.dataPreprocessor ? action.dataPreprocessor(action.data) : action.data; return { - data: prepData, - initialData: prepData, - errors: action.data ? action.validator(prepData) : undefined, + data, + initialData: data, + errors: action.data ? action.validator(data) : undefined, }; } default: { @@ -82,6 +86,9 @@ function getChangedValue(target) { } else if (target.type === "number") { const parsedValue = parseInt(value); value = Number.isNaN(parsedValue) ? value : parsedValue; + } else if (target.type === "file") { + // Return first file (we don't need multiple yet) + [value] = target.files; } return value; } diff --git a/src/index.js b/src/index.js index 7288d3c..ab4987c 100644 --- a/src/index.js +++ b/src/index.js @@ -15,15 +15,16 @@ export { useAPIPatch } from "api/patch"; export { Alert } from "bootstrap/Alert"; export { Button } from "bootstrap/Button"; export { CheckBox } from "bootstrap/CheckBox"; -export { formFieldsSize } from "bootstrap/constants"; export { DataTimeInput } from "bootstrap/DataTimeInput"; export { EmailInput } from "bootstrap/EmailInput"; +export { FileInput } from "bootstrap/FileInput"; export { Input } from "bootstrap/Input"; export { NumberInput } from "bootstrap/NumberInput"; export { PasswordInput } from "bootstrap/PasswordInput"; export { RadioSet } from "bootstrap/RadioSet"; export { Select } from "bootstrap/Select"; export { TextInput } from "bootstrap/TextInput"; +export { formFieldsSize } from "bootstrap/constants"; export { Spinner, From b320e6a860bcae5e8a405ce18157310b7e48d92c Mon Sep 17 00:00:00 2001 From: Maciej Lenartowicz Date: Fri, 11 Oct 2019 10:15:53 +0200 Subject: [PATCH 2/5] Changed beta versioning procedure --- README.md | 2 +- scripts/publish.sh | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2e1611a..f55d183 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Each commit to `dev` branch will result in publishing a new version of library tagged `beta`. Versions names are based on commit SHA, e.g. -`foris@0.1.0-d9073aa4.0`. +`foris@0.1.0-beta.d9073aa4`. ### Preparing a release diff --git a/scripts/publish.sh b/scripts/publish.sh index 4ad76f2..565bde3 100755 --- a/scripts/publish.sh +++ b/scripts/publish.sh @@ -10,7 +10,8 @@ else echo "unsafe-perm = true" >> ~/.npmrc if test "$1" = "beta" then - npm version prerelease --preid=$CI_COMMIT_SHORT_SHA --git-tag-version false + BETA_VERSION=$(npx -c 'echo "$npm_package_version"')-beta.$CI_COMMIT_SHORT_SHA + npm version $BETA_VERSION --git-tag-version false npm publish --tag beta elif test "$1" = "latest" then From 760e6d9243913604be486b8185f92e9888a96128 Mon Sep 17 00:00:00 2001 From: Maciej Lenartowicz Date: Fri, 11 Oct 2019 14:11:14 +0000 Subject: [PATCH 3/5] Download button --- src/bootstrap/DownloadButton.js | 21 +++++++++++++++++++ src/bootstrap/DownloadButton.md | 7 +++++++ .../__tests__/DownloadButton.test.js | 19 +++++++++++++++++ src/index.js | 1 + 4 files changed, 48 insertions(+) create mode 100644 src/bootstrap/DownloadButton.js create mode 100644 src/bootstrap/DownloadButton.md create mode 100644 src/bootstrap/__tests__/DownloadButton.test.js diff --git a/src/bootstrap/DownloadButton.js b/src/bootstrap/DownloadButton.js new file mode 100644 index 0000000..8b3d043 --- /dev/null +++ b/src/bootstrap/DownloadButton.js @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/) + * + * This is free software, licensed under the GNU General Public License v3. + * See /LICENSE for more information. + */ + +import React from "react"; +import PropTypes from "prop-types"; + +DownloadButton.propTypes = { + href: PropTypes.string.isRequired, + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node, + ]), +}; + +export function DownloadButton({ href, children }) { + return {children}; +} diff --git a/src/bootstrap/DownloadButton.md b/src/bootstrap/DownloadButton.md new file mode 100644 index 0000000..f96deef --- /dev/null +++ b/src/bootstrap/DownloadButton.md @@ -0,0 +1,7 @@ +Hyperlink with apperance of a button. + +It has `download` attribute, which prevents closing WebSocket connection on Firefox. See [related issue](https://bugzilla.mozilla.org/show_bug.cgi?id=858538) for more details. + +```js +Download +``` diff --git a/src/bootstrap/__tests__/DownloadButton.test.js b/src/bootstrap/__tests__/DownloadButton.test.js new file mode 100644 index 0000000..5f9108a --- /dev/null +++ b/src/bootstrap/__tests__/DownloadButton.test.js @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/) + * + * This is free software, licensed under the GNU General Public License v3. + * See /LICENSE for more information. + */ + +import React from "react"; + +import { render } from "customTestRender"; + +import { DownloadButton } from "../DownloadButton"; + +describe("", () => { + it("should have download attribute", () => { + const { container } = render(Test Button); + expect(container.firstChild.getAttribute("download")).not.toBeNull(); + }); +}); diff --git a/src/index.js b/src/index.js index ab4987c..9561621 100644 --- a/src/index.js +++ b/src/index.js @@ -15,6 +15,7 @@ export { useAPIPatch } from "api/patch"; export { Alert } from "bootstrap/Alert"; export { Button } from "bootstrap/Button"; export { CheckBox } from "bootstrap/CheckBox"; +export { DownloadButton } from "bootstrap/DownloadButton"; export { DataTimeInput } from "bootstrap/DataTimeInput"; export { EmailInput } from "bootstrap/EmailInput"; export { FileInput } from "bootstrap/FileInput"; From ff9e8fdeb14fef928d93dd05e194776e8bba6254 Mon Sep 17 00:00:00 2001 From: Maciej Lenartowicz Date: Tue, 15 Oct 2019 10:10:33 +0200 Subject: [PATCH 4/5] Added quotes to shell variables --- scripts/publish.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/publish.sh b/scripts/publish.sh index 565bde3..6aa73cd 100755 --- a/scripts/publish.sh +++ b/scripts/publish.sh @@ -6,12 +6,12 @@ then exit 1 else # Need to replace "_" with "_" as GitLab CI won't accept secret vars with "-" - echo "//registry.npmjs.org/:_authToken=$(echo $NPM_TOKEN | tr _ -)" > .npmrc + echo "//registry.npmjs.org/:_authToken=$(echo "$NPM_TOKEN" | tr _ -)" > .npmrc echo "unsafe-perm = true" >> ~/.npmrc if test "$1" = "beta" then BETA_VERSION=$(npx -c 'echo "$npm_package_version"')-beta.$CI_COMMIT_SHORT_SHA - npm version $BETA_VERSION --git-tag-version false + npm version "$BETA_VERSION" --git-tag-version false npm publish --tag beta elif test "$1" = "latest" then From 88f3836485e259559c1c675a9262ba898465e62d Mon Sep 17 00:00:00 2001 From: Maciej Lenartowicz Date: Thu, 24 Oct 2019 08:12:39 +0000 Subject: [PATCH 5/5] Radio checkbox whitespace --- Makefile | 2 ++ package-lock.json | 2 +- package.json | 3 +- src/bootstrap/CheckBox.js | 8 ++--- src/bootstrap/RadioSet.js | 16 +++------ src/bootstrap/RadioSet.md | 2 ++ .../__snapshots__/CheckBox.test.js.snap | 34 ++++++++----------- .../__snapshots__/RadioSet.test.js.snap | 4 +-- 8 files changed, 30 insertions(+), 41 deletions(-) diff --git a/Makefile b/Makefile index d44dba7..2ddbdea 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,8 @@ lint: test: npm test +test-js-update-snapshots: + npm test -- -u create-messages: pybabel extract -F babel.cfg -o ./translations/forisjs.pot . diff --git a/package-lock.json b/package-lock.json index 081c0c2..521c890 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "foris", - "version": "1.1.0", + "version": "1.1.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 88f307d..72984ef 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "foris", - "version": "1.1.0", + "version": "1.1.1", "description": "Set of components and utils for Foris and its plugins.", "author": "CZ.NIC, z.s.p.o.", "repository": { @@ -73,7 +73,6 @@ "test": "jest", "test:watch": "jest --watch", "test:coverage": "jest --coverage --colors", - "test:update-snapshots": "jest -u", "docs": "npx styleguidist build ", "docs:watch": "styleguidist server" }, diff --git a/src/bootstrap/CheckBox.js b/src/bootstrap/CheckBox.js index 02f336c..f97a90f 100644 --- a/src/bootstrap/CheckBox.js +++ b/src/bootstrap/CheckBox.js @@ -32,8 +32,8 @@ export function CheckBox({ }) { const uid = useUID(); return ( -
-
+
+
- + + {helpText && {helpText}}
- {helpText ? {helpText} : null}
); } diff --git a/src/bootstrap/RadioSet.js b/src/bootstrap/RadioSet.js index 7125cb6..48017a4 100644 --- a/src/bootstrap/RadioSet.js +++ b/src/bootstrap/RadioSet.js @@ -52,16 +52,10 @@ export function RadioSet({ }); return ( -
- {label - ? ( - - ) - : null} +
+ {label && } {radios} - {helpText ? {helpText} : null} + {helpText && {helpText}}
); } @@ -77,7 +71,7 @@ function Radio({ }) { return ( <> -
+
+ {helpText && {helpText}}
- {helpText ? {helpText} : null} ); } diff --git a/src/bootstrap/RadioSet.md b/src/bootstrap/RadioSet.md index 5ccc534..13c3338 100644 --- a/src/bootstrap/RadioSet.md +++ b/src/bootstrap/RadioSet.md @@ -2,6 +2,8 @@ Set of radio Bootstrap component input with label and predefined sizes and struc All additional `props` are passed to the `` HTML component. +Unless `helpText` is set for one of the options they are displayed inline. + ```js import {useState} from 'react'; const CHOICES=[ diff --git a/src/bootstrap/__tests__/__snapshots__/CheckBox.test.js.snap b/src/bootstrap/__tests__/__snapshots__/CheckBox.test.js.snap index fe9d182..31b0d57 100644 --- a/src/bootstrap/__tests__/__snapshots__/CheckBox.test.js.snap +++ b/src/bootstrap/__tests__/__snapshots__/CheckBox.test.js.snap @@ -2,12 +2,10 @@ exports[` Render checkbox 1`] = `
Render checkbox 1`] = ` + + Some help text +
- - Some help text -
`; exports[` Render uncheked checkbox 1`] = `
Render uncheked checkbox 1`] = ` + + Some help text +
- - Some help text -
`; diff --git a/src/bootstrap/__tests__/__snapshots__/RadioSet.test.js.snap b/src/bootstrap/__tests__/__snapshots__/RadioSet.test.js.snap index f142d87..ffec0b5 100644 --- a/src/bootstrap/__tests__/__snapshots__/RadioSet.test.js.snap +++ b/src/bootstrap/__tests__/__snapshots__/RadioSet.test.js.snap @@ -3,12 +3,10 @@ exports[` Render radio set 1`] = `