mirror of
				https://gitlab.nic.cz/turris/reforis/foris-js.git
				synced 2025-11-03 23:00:31 +01:00 
			
		
		
		
	Merge branch 'client-configuration' into 'dev'
Client configuration See merge request turris/reforis/foris-js!20
This commit is contained in:
		
							
								
								
									
										2
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "foris",
 | 
			
		||||
  "version": "1.0.0",
 | 
			
		||||
  "version": "1.1.0",
 | 
			
		||||
  "lockfileVersion": 1,
 | 
			
		||||
  "requires": true,
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
 
 | 
			
		||||
@@ -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": {
 | 
			
		||||
 
 | 
			
		||||
@@ -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) {
 | 
			
		||||
 
 | 
			
		||||
@@ -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";
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										34
									
								
								src/bootstrap/FileInput.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/bootstrap/FileInput.js
									
									
									
									
									
										Normal file
									
								
							@@ -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 (
 | 
			
		||||
        <Input
 | 
			
		||||
            type="file"
 | 
			
		||||
            className="custom-file-input"
 | 
			
		||||
            labelClassName="custom-file-label"
 | 
			
		||||
            groupClassName="custom-file"
 | 
			
		||||
            {...props}
 | 
			
		||||
        />
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								src/bootstrap/FileInput.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/bootstrap/FileInput.md
									
									
									
									
									
										Normal file
									
								
							@@ -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 `<input type="file">` HTML component.
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
import {useState} from 'react';
 | 
			
		||||
const [files, setFiles] = useState([]);
 | 
			
		||||
 | 
			
		||||
<FileInput
 | 
			
		||||
    files={files}
 | 
			
		||||
    label="Some file"
 | 
			
		||||
    helpText="Will be uploaded"
 | 
			
		||||
    onChange={event =>setFiles(event.target.files)}
 | 
			
		||||
/>
 | 
			
		||||
```
 | 
			
		||||
@@ -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,19 +21,20 @@ 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 (
 | 
			
		||||
        <div className={formFieldsSize}>
 | 
			
		||||
            <div className="form-group">
 | 
			
		||||
                <label htmlFor={uid}>{label}</label>
 | 
			
		||||
                <div className="input-group">
 | 
			
		||||
        <div className={`form-group ${formFieldsSize}`}>
 | 
			
		||||
            <label className={labelClassName} htmlFor={uid}>{label}</label>
 | 
			
		||||
            <div className={`input-group ${groupClassName || ""}`.trim()}>
 | 
			
		||||
                <input
 | 
			
		||||
                    className={inputClassName}
 | 
			
		||||
                    type={type}
 | 
			
		||||
@@ -46,6 +47,5 @@ export function Input({
 | 
			
		||||
            {error ? <div className="invalid-feedback">{error}</div> : null}
 | 
			
		||||
            {helpText ? <small className="form-text text-muted">{helpText}</small> : null}
 | 
			
		||||
        </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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";
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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 = {
 | 
			
		||||
 
 | 
			
		||||
@@ -2,11 +2,8 @@
 | 
			
		||||
 | 
			
		||||
exports[`<NumberInput/> Render number input 1`] = `
 | 
			
		||||
<div
 | 
			
		||||
  class="col-sm-12 offset-lg-1 col-lg-10"
 | 
			
		||||
  class="form-group col-sm-12 offset-lg-1 col-lg-10"
 | 
			
		||||
>
 | 
			
		||||
  <div
 | 
			
		||||
    class="form-group"
 | 
			
		||||
  >
 | 
			
		||||
  <label
 | 
			
		||||
    for="1"
 | 
			
		||||
  >
 | 
			
		||||
@@ -49,6 +46,5 @@ exports[`<NumberInput/> Render number input 1`] = `
 | 
			
		||||
  >
 | 
			
		||||
    Some help text
 | 
			
		||||
  </small>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
`;
 | 
			
		||||
 
 | 
			
		||||
@@ -2,11 +2,8 @@
 | 
			
		||||
 | 
			
		||||
exports[`<PasswordInput/> Render password input 1`] = `
 | 
			
		||||
<div
 | 
			
		||||
  class="col-sm-12 offset-lg-1 col-lg-10"
 | 
			
		||||
  class="form-group col-sm-12 offset-lg-1 col-lg-10"
 | 
			
		||||
>
 | 
			
		||||
  <div
 | 
			
		||||
    class="form-group"
 | 
			
		||||
  >
 | 
			
		||||
  <label
 | 
			
		||||
    for="1"
 | 
			
		||||
  >
 | 
			
		||||
@@ -28,6 +25,5 @@ exports[`<PasswordInput/> Render password input 1`] = `
 | 
			
		||||
  >
 | 
			
		||||
    Some help text
 | 
			
		||||
  </small>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
`;
 | 
			
		||||
 
 | 
			
		||||
@@ -2,11 +2,8 @@
 | 
			
		||||
 | 
			
		||||
exports[`<TextInput/> Render text input 1`] = `
 | 
			
		||||
<div
 | 
			
		||||
  class="col-sm-12 offset-lg-1 col-lg-10"
 | 
			
		||||
  class="form-group col-sm-12 offset-lg-1 col-lg-10"
 | 
			
		||||
>
 | 
			
		||||
  <div
 | 
			
		||||
    class="form-group"
 | 
			
		||||
  >
 | 
			
		||||
  <label
 | 
			
		||||
    for="1"
 | 
			
		||||
  >
 | 
			
		||||
@@ -27,6 +24,5 @@ exports[`<TextInput/> Render text input 1`] = `
 | 
			
		||||
  >
 | 
			
		||||
    Some help text
 | 
			
		||||
  </small>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
`;
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user