1
0
mirror of https://gitlab.nic.cz/turris/reforis/foris-js.git synced 2024-12-25 00:11:36 +01:00

Set modules.

This commit is contained in:
Bogdan Bodnar 2019-08-27 11:54:57 +02:00
parent 7b38c1658c
commit 19df5c2630
No known key found for this signature in database
GPG Key ID: 49E4169AD3CA42B0
53 changed files with 275 additions and 224 deletions

View File

@ -1,9 +1,21 @@
module.exports = { module.exports = {
presets: [ presets: [
'@babel/preset-env', ["@babel/preset-env", {
'@babel/preset-react', targets: {
esmodules: true,
},
}],
"@babel/preset-react",
], ],
plugins: [ plugins: [
'@babel/plugin-transform-runtime' "@babel/plugin-syntax-export-default-from",
] "@babel/plugin-transform-runtime",
["module-resolver", {
root: ["./src"],
alias: {
test: "./test",
underscore: "lodash",
},
}],
],
}; };

70
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "foris", "name": "foris",
"version": "0.0.1", "version": "0.0.2",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@ -417,6 +417,15 @@
"@babel/helper-plugin-utils": "^7.0.0" "@babel/helper-plugin-utils": "^7.0.0"
} }
}, },
"@babel/plugin-syntax-export-default-from": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.2.0.tgz",
"integrity": "sha512-c7nqUnNST97BWPtoe+Ssi+fJukc9P9/JMZ71IOMNQWza2E+Psrd46N6AEvtw6pqK+gt7ChjXyrw4SPDO79f3Lw==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-syntax-json-strings": { "@babel/plugin-syntax-json-strings": {
"version": "7.2.0", "version": "7.2.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz",
@ -1864,6 +1873,19 @@
"@types/babel__traverse": "^7.0.6" "@types/babel__traverse": "^7.0.6"
} }
}, },
"babel-plugin-module-resolver": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-3.2.0.tgz",
"integrity": "sha512-tjR0GvSndzPew/Iayf4uICWZqjBwnlMWjSx6brryfQ81F9rxBVqwDJtFCV8oOs0+vJeefK9TmdZtkIFdFe1UnA==",
"dev": true,
"requires": {
"find-babel-config": "^1.1.0",
"glob": "^7.1.2",
"pkg-up": "^2.0.0",
"reselect": "^3.0.1",
"resolve": "^1.4.0"
}
},
"babel-plugin-react-transform": { "babel-plugin-react-transform": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/babel-plugin-react-transform/-/babel-plugin-react-transform-3.0.0.tgz", "resolved": "https://registry.npmjs.org/babel-plugin-react-transform/-/babel-plugin-react-transform-3.0.0.tgz",
@ -3418,6 +3440,28 @@
} }
} }
}, },
"eslint-config-airbnb": {
"version": "18.0.1",
"resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-18.0.1.tgz",
"integrity": "sha512-hLb/ccvW4grVhvd6CT83bECacc+s4Z3/AEyWQdIT2KeTsG9dR7nx1gs7Iw4tDmGKozCNHFn4yZmRm3Tgy+XxyQ==",
"dev": true,
"requires": {
"eslint-config-airbnb-base": "^14.0.0",
"object.assign": "^4.1.0",
"object.entries": "^1.1.0"
}
},
"eslint-config-airbnb-base": {
"version": "14.0.0",
"resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.0.0.tgz",
"integrity": "sha512-2IDHobw97upExLmsebhtfoD3NAKhV4H0CJWP3Uprd/uk+cHuWYOczPVxQ8PxLFUAw7o3Th1RAU8u1DoUpr+cMA==",
"dev": true,
"requires": {
"confusing-browser-globals": "^1.0.7",
"object.assign": "^4.1.0",
"object.entries": "^1.1.0"
}
},
"eslint-config-react-app": { "eslint-config-react-app": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-4.0.1.tgz", "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-4.0.1.tgz",
@ -4233,6 +4277,24 @@
} }
} }
}, },
"find-babel-config": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.2.0.tgz",
"integrity": "sha512-jB2CHJeqy6a820ssiqwrKMeyC6nNdmrcgkKWJWmpoxpE8RKciYJXCcXRq1h2AzCo5I5BJeN2tkGEO3hLTuePRA==",
"dev": true,
"requires": {
"json5": "^0.5.1",
"path-exists": "^3.0.0"
},
"dependencies": {
"json5": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
"dev": true
}
}
},
"find-cache-dir": { "find-cache-dir": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
@ -9013,6 +9075,12 @@
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
"dev": true "dev": true
}, },
"reselect": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-3.0.1.tgz",
"integrity": "sha1-79qpjqdFEyTQkrKyFjpqHXqaIUc=",
"dev": true
},
"resolve": { "resolve": {
"version": "1.12.0", "version": "1.12.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz",

View File

@ -1,6 +1,6 @@
{ {
"name": "foris", "name": "foris",
"version": "0.0.1", "version": "0.0.2",
"description": "Set of components and utils for Foris and its plugins.", "description": "Set of components and utils for Foris and its plugins.",
"author": "CZ.NIC, z.s.p.o.", "author": "CZ.NIC, z.s.p.o.",
"repository": { "repository": {
@ -31,6 +31,7 @@
"@babel/cli": "^7.4.4", "@babel/cli": "^7.4.4",
"@babel/core": "^7.4.5", "@babel/core": "^7.4.5",
"@babel/plugin-proposal-class-properties": "^7.4.4", "@babel/plugin-proposal-class-properties": "^7.4.4",
"@babel/plugin-syntax-export-default-from": "^7.2.0",
"@babel/plugin-transform-runtime": "^7.4.4", "@babel/plugin-transform-runtime": "^7.4.4",
"@babel/preset-env": "^7.4.5", "@babel/preset-env": "^7.4.5",
"@babel/preset-react": "^7.0.0", "@babel/preset-react": "^7.0.0",
@ -38,9 +39,11 @@
"babel-eslint": "^9.0.0", "babel-eslint": "^9.0.0",
"babel-jest": "^24.8.0", "babel-jest": "^24.8.0",
"babel-loader": "^8.0.6", "babel-loader": "^8.0.6",
"babel-plugin-module-resolver": "^3.2.0",
"babel-plugin-react-transform": "^3.0.0", "babel-plugin-react-transform": "^3.0.0",
"babel-polyfill": "^6.26.0", "babel-polyfill": "^6.26.0",
"eslint": "^5.16.0", "eslint": "^5.16.0",
"eslint-config-airbnb": "^18.0.1",
"eslint-config-react-app": "^4.0.1", "eslint-config-react-app": "^4.0.1",
"eslint-plugin-flowtype": "^2.50.3", "eslint-plugin-flowtype": "^2.50.3",
"eslint-plugin-import": "^2.17.3", "eslint-plugin-import": "^2.17.3",
@ -57,7 +60,7 @@
"snapshot-diff": "^0.5.1" "snapshot-diff": "^0.5.1"
}, },
"scripts": { "scripts": {
"build": "babel ./src --out-dir ./dist -s inline", "build": "rm -rf dist; babel src --out-dir dist --ignore '**/__tests__' --source-maps inline",
"prepare": "rm -rf ./dist && npm run build", "prepare": "rm -rf ./dist && npm run build",
"lint": "eslint src", "lint": "eslint src",
"test": "jest", "test": "jest",
@ -65,6 +68,6 @@
"test:coverage": "jest --coverage --colors" "test:coverage": "jest --coverage --colors"
}, },
"files": [ "files": [
"dist" "dist/**"
] ]
} }

View File

@ -6,8 +6,9 @@
*/ */
import axios from "axios"; import axios from "axios";
import {useCallback, useReducer} from "react"; import { useCallback, useReducer } from "react";
import {ForisURLs} from './constants';
import { ForisUrls } from "forisUrls";
const POST_HEADERS = { const POST_HEADERS = {
@ -42,29 +43,29 @@ const API_ACTIONS = {
const APIGetReducer = (state, action) => { const APIGetReducer = (state, action) => {
switch (action.type) { switch (action.type) {
case API_ACTIONS.INIT: case API_ACTIONS.INIT:
return { return {
...state, ...state,
isLoading: true, isLoading: true,
isError: false, isError: false,
}; };
case API_ACTIONS.SUCCESS: case API_ACTIONS.SUCCESS:
return { return {
...state, ...state,
isLoading: false, isLoading: false,
isError: false, isError: false,
data: action.payload, data: action.payload,
}; };
case API_ACTIONS.FAILURE: case API_ACTIONS.FAILURE:
if (action.status === 403) window.location.assign(ForisURLs.login); if (action.status === 403) window.location.assign(ForisUrls.login);
return { return {
...state, ...state,
isLoading: false, isLoading: false,
isError: true, isError: true,
data: action.payload, data: action.payload,
}; };
default: default:
throw new Error(); throw new Error();
} }
}; };
@ -81,12 +82,12 @@ export function useAPIGet(url) {
}); });
const get = useCallback(async () => { const get = useCallback(async () => {
dispatch({type: API_ACTIONS.INIT}); dispatch({ type: API_ACTIONS.INIT });
try { try {
const result = await axios.get(url, { const result = await axios.get(url, {
timeout: TIMEOUT, timeout: TIMEOUT,
}); });
dispatch({type: API_ACTIONS.SUCCESS, payload: result.data}); dispatch({ type: API_ACTIONS.SUCCESS, payload: result.data });
} catch (error) { } catch (error) {
dispatch({ dispatch({
type: API_ACTIONS.FAILURE, type: API_ACTIONS.FAILURE,
@ -101,32 +102,32 @@ export function useAPIGet(url) {
const APIPostReducer = (state, action) => { const APIPostReducer = (state, action) => {
switch (action.type) { switch (action.type) {
case API_ACTIONS.INIT: case API_ACTIONS.INIT:
return { return {
...state, ...state,
isSending: true, isSending: true,
isError: false, isError: false,
isSuccess: false, isSuccess: false,
}; };
case API_ACTIONS.SUCCESS: case API_ACTIONS.SUCCESS:
return { return {
...state, ...state,
isSending: false, isSending: false,
isError: false, isError: false,
isSuccess: true, isSuccess: true,
data: action.payload, data: action.payload,
}; };
case API_ACTIONS.FAILURE: case API_ACTIONS.FAILURE:
if (action.status === 403) window.location.assign(ForisURLs.login); if (action.status === 403) window.location.assign(ForisUrls.login);
return { return {
...state, ...state,
isSending: false, isSending: false,
isError: true, isError: true,
isSuccess: false, isSuccess: false,
data: action.payload, data: action.payload,
}; };
default: default:
throw new Error(); throw new Error();
} }
}; };
@ -139,13 +140,13 @@ export function useAPIPost(url) {
}); });
const post = async (data) => { const post = async (data) => {
dispatch({type: API_ACTIONS.INIT}); dispatch({ type: API_ACTIONS.INIT });
try { try {
const result = await axios.post(url, data, { const result = await axios.post(url, data, {
timeout: TIMEOUT, timeout: TIMEOUT,
headers: POST_HEADERS, headers: POST_HEADERS,
}); });
dispatch({type: API_ACTIONS.SUCCESS, payload: result.data}); dispatch({ type: API_ACTIONS.SUCCESS, payload: result.data });
} catch (error) { } catch (error) {
dispatch({ dispatch({
type: API_ACTIONS.FAILURE, type: API_ACTIONS.FAILURE,

View File

@ -1 +0,0 @@
export * from "./hooks";

View File

@ -22,7 +22,7 @@ Alert.propTypes = {
onDismiss: PropTypes.func onDismiss: PropTypes.func
}; };
export default function Alert({type, message, onDismiss, children}) { export function Alert({type, message, onDismiss, children}) {
return <div className={`alert alert-dismissible alert-${type}`}> return <div className={`alert alert-dismissible alert-${type}`}>
{onDismiss ? <button type="button" className="close" onClick={onDismiss}>&times;</button> : false} {onDismiss ? <button type="button" className="close" onClick={onDismiss}>&times;</button> : false}
{message} {message}

View File

@ -29,7 +29,7 @@ Button.propTypes = {
]).isRequired ]).isRequired
}; };
export default function Button({className, loading, forisFormSize, children, ...props}) { export function Button({className, loading, forisFormSize, children, ...props}) {
className = className ? 'btn ' + className : 'btn btn-primary '; className = className ? 'btn ' + className : 'btn btn-primary ';
if (forisFormSize) if (forisFormSize)
className += SIZE_CLASS + SIZE_CLASS_SM; className += SIZE_CLASS + SIZE_CLASS_SM;

View File

@ -7,7 +7,7 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import {useUID} from 'react-uid/dist/es5/index'; import {useUID} from 'react-uid';
import {formFieldsSize} from './constants'; import {formFieldsSize} from './constants';
@ -27,7 +27,7 @@ CheckBox.defaultProps = {
disabled: false disabled: false
}; };
export default function CheckBox({label, helpText, useDefaultSize, disabled, ...props}) { export function CheckBox({label, helpText, useDefaultSize, disabled, ...props}) {
const uid = useUID(); const uid = useUID();
return <div className={useDefaultSize ? formFieldsSize : ""} style={{marginBottom: '1rem'}}> return <div className={useDefaultSize ? formFieldsSize : ""} style={{marginBottom: '1rem'}}>
<div className='custom-control custom-checkbox' style={{marginBottom: '0'}}> <div className='custom-control custom-checkbox' style={{marginBottom: '0'}}>

View File

@ -10,7 +10,7 @@ import PropTypes from 'prop-types';
import Datetime from 'react-datetime/DateTime'; import Datetime from 'react-datetime/DateTime';
import moment from 'moment/moment'; import moment from 'moment/moment';
import Input from './Input'; import {Input} from './Input';
DataTimeInput.propTypes = { DataTimeInput.propTypes = {
/** Field label. */ /** Field label. */
@ -35,7 +35,7 @@ DataTimeInput.propTypes = {
const DEFAULT_DATE_FORMAT = 'YYYY-MM-DD'; const DEFAULT_DATE_FORMAT = 'YYYY-MM-DD';
const DEFAULT_TIME_FORMAT = 'HH:mm:ss'; const DEFAULT_TIME_FORMAT = 'HH:mm:ss';
export default function DataTimeInput({value, onChange, isValidDate, dateFormat, timeFormat, children, ...props}) { export function DataTimeInput({value, onChange, isValidDate, dateFormat, timeFormat, children, ...props}) {
function renderInput(datetimeProps) { function renderInput(datetimeProps) {
return <Input return <Input
{...props} {...props}

View File

@ -7,11 +7,10 @@
import React from 'react'; import React from 'react';
import Input from './Input'; import {Input} from './Input';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
const EmailInput = ({...props}) => <Input type="email" {...props}/>; export const EmailInput = ({...props}) => <Input type="email" {...props}/>;
EmailInput.propTypes = { EmailInput.propTypes = {
/** Field label. */ /** Field label. */
@ -23,5 +22,3 @@ EmailInput.propTypes = {
/** Email value. */ /** Email value. */
value: PropTypes.string, value: PropTypes.string,
}; };
export default EmailInput;

View File

@ -6,7 +6,7 @@
*/ */
import React from 'react'; import React from 'react';
import {useUID} from 'react-uid/dist/es5/index'; import {useUID} from 'react-uid';
import {formFieldsSize} from './constants'; import {formFieldsSize} from './constants';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
@ -23,7 +23,7 @@ Input.propTypes = {
} }
/** Base bootstrap input component. */ /** Base bootstrap input component. */
export default function Input({type, label, helpText, error, className, children, ...props}) { export function Input({type, label, helpText, error, className, children, ...props}) {
const uid = useUID(); const uid = useUID();
const inputClassName = `form-control ${className ? className : ''} ${(error ? 'is-invalid' : '')}`.trim(); const inputClassName = `form-control ${className ? className : ''} ${(error ? 'is-invalid' : '')}`.trim();
return <div className={formFieldsSize}> return <div className={formFieldsSize}>

View File

@ -7,7 +7,8 @@
import React, {useEffect, useRef} from 'react'; import React, {useEffect, useRef} from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Portal from 'utils/Portal';
import {Portal} from 'utils/Portal';
Modal.propTypes = { Modal.propTypes = {
/** Is modal shown value */ /** Is modal shown value */

View File

@ -7,10 +7,10 @@
import React from 'react'; import React from 'react';
import Input from './Input'; import {Input} from './Input';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
const NumberInput = ({...props}) => <Input type="number" {...props}/>; export const NumberInput = ({...props}) => <Input type="number" {...props}/>;
NumberInput.propTypes = { NumberInput.propTypes = {
/** Field label. */ /** Field label. */
@ -25,5 +25,3 @@ NumberInput.propTypes = {
PropTypes.number, PropTypes.number,
]), ]),
}; };
export default NumberInput;

View File

@ -8,7 +8,7 @@
import React, {useState} from 'react'; import React, {useState} from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Input from './Input'; import {Input} from './Input';
PasswordInput.propTypes = { PasswordInput.propTypes = {
/** Field label. */ /** Field label. */
@ -23,7 +23,7 @@ PasswordInput.propTypes = {
withEye: PropTypes.bool, withEye: PropTypes.bool,
}; };
export default function PasswordInput({withEye, ...props}) { export function PasswordInput({withEye, ...props}) {
const [isHidden, setHidden] = useState(true); const [isHidden, setHidden] = useState(true);
return <Input return <Input
type={withEye ? isHidden ? 'password' : 'text' : 'password'} type={withEye ? isHidden ? 'password' : 'text' : 'password'}

View File

@ -7,7 +7,7 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import {useUID} from 'react-uid/dist/es5/index'; import {useUID} from 'react-uid';
import {formFieldsSize} from './constants'; import {formFieldsSize} from './constants';
@ -30,7 +30,7 @@ RadioSet.propTypes = {
helpText: PropTypes.string, helpText: PropTypes.string,
}; };
export default function RadioSet({name, label, choices, value, helpText, ...props}) { export function RadioSet({name, label, choices, value, helpText, ...props}) {
const uid = useUID(); const uid = useUID();
const radios = choices.map((choice, key) => const radios = choices.map((choice, key) =>
<Radio <Radio

View File

@ -7,7 +7,7 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import {useUID} from 'react-uid/dist/es5/index'; import {useUID} from 'react-uid';
Select.propTypes = { Select.propTypes = {
@ -24,7 +24,7 @@ Select.propTypes = {
helpText: PropTypes.string, helpText: PropTypes.string,
}; };
export default function Select({label, choices, helpText, ...props}) { export function Select({label, choices, helpText, ...props}) {
const uid = useUID(); const uid = useUID();
const options = Object.keys(choices).map( const options = Object.keys(choices).map(

View File

@ -23,7 +23,7 @@ Spinner.defaultProps = {
fullScreen: false, fullScreen: false,
}; };
export default function Spinner({fullScreen, children, className, ...props}) { export function Spinner({fullScreen, children, className, ...props}) {
if (!fullScreen) { if (!fullScreen) {
return <div className={'spinner-wrapper ' + (className ? className : '')} {...props}> return <div className={'spinner-wrapper ' + (className ? className : '')} {...props}>
<SpinnerElement>{children}</SpinnerElement> <SpinnerElement>{children}</SpinnerElement>

View File

@ -8,10 +8,10 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Input from './Input'; import {Input} from './Input';
const TextInput = ({...props}) => <Input type="text" {...props}/>; export const TextInput = ({...props}) => <Input type="text" {...props}/>;
TextInput.propTypes = { TextInput.propTypes = {
@ -22,5 +22,3 @@ TextInput.propTypes = {
/** Help text message. */ /** Help text message. */
helpText: PropTypes.string, helpText: PropTypes.string,
}; };
export default TextInput;

View File

@ -9,7 +9,7 @@ import React from 'react';
import {render} from 'customTestRender'; import {render} from 'customTestRender';
import Button from '../components/Button' import Button from '../Button'
describe('<Button />', () => { describe('<Button />', () => {
it('Render button correctly', () => { it('Render button correctly', () => {

View File

@ -9,7 +9,7 @@ import React from 'react';
import {render} from 'customTestRender'; import {render} from 'customTestRender';
import Checkbox from '../components/Checkbox' import Checkbox from '../Checkbox'
describe('<Checkbox/>', () => { describe('<Checkbox/>', () => {
it('Render checkbox', () => { it('Render checkbox', () => {

View File

@ -9,7 +9,7 @@ import React from 'react';
import {render} from 'customTestRender'; import {render} from 'customTestRender';
import NumberInput from '../components/NumberInput'; import NumberInput from '../NumberInput';
describe('<NumberInput/>', () => { describe('<NumberInput/>', () => {

View File

@ -9,7 +9,7 @@ import React from 'react';
import {render} from 'customTestRender'; import {render} from 'customTestRender';
import PasswordInput from '../components/PasswordInput'; import PasswordInput from '../PasswordInput';
describe('<PasswordInput/>', () => { describe('<PasswordInput/>', () => {
it('Render password input', () => { it('Render password input', () => {

View File

@ -9,7 +9,7 @@ import React from 'react';
import {render} from 'customTestRender'; import {render} from 'customTestRender';
import RadioSet from '../components/RadioSet'; import RadioSet from '../RadioSet';
const TEST_CHOICES = [ const TEST_CHOICES = [
{label: 'label', value: 'value'}, {label: 'label', value: 'value'},

View File

@ -9,7 +9,7 @@ import React from 'react';
import {fireEvent, getByDisplayValue, getByText, render} from 'customTestRender'; import {fireEvent, getByDisplayValue, getByText, render} from 'customTestRender';
import Select from '../components/Select'; import Select from '../Select';
const TEST_CHOICES = { const TEST_CHOICES = {
'1': 'one', '1': 'one',

View File

@ -9,7 +9,7 @@ import React from 'react';
import {render} from 'customTestRender'; import {render} from 'customTestRender';
import TextInput from '../components/TextInput'; import TextInput from '../TextInput';
describe('<TextInput/>', () => { describe('<TextInput/>', () => {
it('Render text input', () => { it('Render text input', () => {

View File

@ -1,31 +0,0 @@
import * as Alert from "./components/Alert";
import * as Button from "./components/Button";
import * as Checkbox from "./components/Checkbox";
import * as constants from "./components/constants";
import * as DataTimeInput from "./components/DataTimeInput";
import * as EmailInput from "./components/EmailInput";
import * as Input from "./components/Input";
import * as Modal from "./components/Modal";
import * as NumberInput from "./components/NumberInput";
import * as PasswordInput from "./components/PasswordInput";
import * as RadioSet from "./components/RadioSet";
import * as Select from "./components/Select";
import * as Spinner from "./components/Spinner";
import * as TextInput from "./components/TextInput";
export {
Alert,
Button,
Checkbox,
constants,
DataTimeInput,
EmailInput,
Input,
Modal,
NumberInput,
PasswordInput,
RadioSet,
Select,
Spinner,
TextInput,
}

View File

@ -1,10 +1,3 @@
/*
* 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.
*/
export const REFORIS_URL_PREFIX = process.env.LIGHTTPD ? "/reforis" : ""; export const REFORIS_URL_PREFIX = process.env.LIGHTTPD ? "/reforis" : "";
export const ForisURLs = { export const ForisURLs = {

View File

@ -9,11 +9,11 @@ import React, {useEffect, useState} from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import {Prompt} from 'react-router'; import {Prompt} from 'react-router';
import Spinner from 'bootstrap/components/Spinner'; import {Spinner} from 'bootstrap/Spinner';
import {useAPIPost} from 'api'; import {useAPIPost} from 'api/hooks';
import {useForisModule, useForm} from '../hooks'; import {useForisModule, useForm} from '../hooks';
import SubmitButton, {STATES as SUBMIT_BUTTON_STATES} from './SubmitButton'; import {STATES as SUBMIT_BUTTON_STATES, SubmitButton} from './SubmitButton';
import {FailAlert, SuccessAlert} from './alerts'; import {FailAlert, SuccessAlert} from './alerts';
ForisForm.propTypes = { ForisForm.propTypes = {
@ -57,17 +57,17 @@ ForisForm.defaultProps = {
}; };
/** Serves as HOC for all foris forms components. */ /** Serves as HOC for all foris forms components. */
export default function ForisForm({ export function ForisForm({
ws, ws,
forisConfig, forisConfig,
prepData, prepData,
prepDataToSubmit, prepDataToSubmit,
postCallback, postCallback,
validator, validator,
disabled, disabled,
onSubmitOverridden, onSubmitOverridden,
children children
}) { }) {
const [formState, onFormChangeHandler, resetFormData] = useForm(validator, prepData); const [formState, onFormChangeHandler, resetFormData] = useForm(validator, prepData);
const [forisModuleState] = useForisModule(ws, forisConfig); const [forisModuleState] = useForisModule(ws, forisConfig);

View File

@ -8,7 +8,7 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Button from 'bootstrap/components/Button'; import {Button} from 'bootstrap/Button';
export const STATES = { export const STATES = {
READY: 1, READY: 1,
@ -21,7 +21,7 @@ SubmitButton.propTypes = {
state: PropTypes.oneOf(Object.keys(STATES).map(key => STATES[key])) state: PropTypes.oneOf(Object.keys(STATES).map(key => STATES[key]))
}; };
export default function SubmitButton({disabled, state, ...props}) { export function SubmitButton({disabled, state, ...props}) {
const disableSubmitButton = disabled || state !== STATES.READY; const disableSubmitButton = disabled || state !== STATES.READY;
const loadingSubmitButton = state !== STATES.READY; const loadingSubmitButton = state !== STATES.READY;

View File

@ -8,8 +8,8 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Alert from 'bootstrap/components/Alert'; import {Alert} from 'bootstrap/Alert';
import Portal from 'utils/Portal'; import {Portal} from 'utils/Portal';
SuccessAlert.propTypes = { SuccessAlert.propTypes = {
onDismiss: PropTypes.func.isRequired, onDismiss: PropTypes.func.isRequired,

View File

@ -9,7 +9,7 @@ import {useCallback, useEffect, useReducer} from 'react';
import update from 'immutability-helper'; import update from 'immutability-helper';
import {useAPIGet} from 'api/hooks'; import {useAPIGet} from 'api/hooks';
import useWSForisModule from 'webSockets/hooks'; import {useWSForisModule} from 'webSockets/hooks';
export function useForm(validator, prepData) { export function useForm(validator, prepData) {

View File

@ -1,5 +0,0 @@
import * as ForisForm from "./components/ForisForm";
import * as SubmitButton from "./components/SubmitButton";
import * as hooks from "./hooks";
export {ForisForm, SubmitButton, hooks}

View File

@ -1,16 +1,51 @@
import * as api from './api'; //API
import * as bootstrap from './bootstrap'; export {useAPIGet, useAPIPost} from "./api/hooks";
import * as form from './form';
import * as testUtils from './testUtils';
import * as validations from './validations';
import {Portal} from './utils'; // Bootstrap
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 {Input} from "bootstrap/Input";
export {Modal, ModalBody, ModalFooter, ModalHeader} from "bootstrap/Modal";
export {NumberInput} from "bootstrap/NumberInput";
export {PasswordInput} from "bootstrap/PasswordInput";
export {RadioSet} from "bootstrap/RadioSet";
export {Select} from "bootstrap/Select";
export {Spinner, SpinnerElement} from "bootstrap/Spinner";
export {TextInput} from "bootstrap/TextInput";
// Form
export {ForisForm} from "form/components/ForisForm";
export {SubmitButton, STATES as SUBMIT_BUTTON_STATES} from "form/components/SubmitButton";
export {useForisModule, useForm} from "form/hooks";
// // Test Utils
export {render} from "testUtils/customTestRender";
export {mockedWS} from "testUtils/mockWS";
export {setupGlobals} from "testUtils/setupGlobals";
// WebSockets
export {useWSForisModule} from "webSockets/hooks";
export {WebSockets} from "webSockets/WebSockets";
// Utils
export {Portal} from "utils/Portal";
// Foris URL
export {ForisURLs, REFORIS_URL_PREFIX} from "./forisUrls"
// Validation
export { export {
api, validateIPv4Address,
bootstrap, validateIPv6Address,
form, validateIPv6Prefix,
testUtils, validateDomain,
validations, validateDUID,
Portal, validateMAC,
} validateMultipleEmails,
} from "validations"

View File

@ -1,11 +0,0 @@
import * as customTestRender from "./customTestRender";
import * as mockWS from "./mockWS";
import * as setupGlobals from "./setupGlobals";
import * as setupTest from "./setupTest";
export {
customTestRender,
mockWS,
setupGlobals,
setupTest,
}

View File

@ -6,6 +6,9 @@
*/ */
// Fake babel (gettext) used for docs // Fake babel (gettext) used for docs
global._ = str => str;
global.babel = {format: (str) => str}; export function setupGlobals() {
global.ForisTranslations = {}; global._ = str => str;
global.babel = {format: (str) => str};
global.ForisTranslations = {};
}

View File

@ -5,33 +5,28 @@
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import mockAxios from 'jest-mock-axios';
import moment from 'moment-timezone';
export function setUpTest() { // Setup axios cleanup
const mockAxios = require('jest-mock-axios'); global.afterEach(() => {
const moment = require('moment-timezone'); mockAxios.reset();
});
// Setup axios cleanup // Mock babel (gettext)
global.afterEach(() => { global._ = str => str;
mockAxios.reset(); global.babel = {format: (str) => str};
}); global.ForisTranslations = {};
// Mock babel (gettext)
window._ = str => str;
window.babel = {format: (str) => str};
window.ForisTranslations = {};
// Mock scrollIntoView
window.HTMLElement.prototype.scrollIntoView = () => {
};
jest.doMock('moment', () => {
moment.tz.setDefault('UTC');
return moment;
});
Date.now = jest.fn(() => new Date(Date.UTC(2019, 1, 1, 12, 13, 14)).valueOf());
}
// Mock scrollIntoView
global.HTMLElement.prototype.scrollIntoView = () => {
};
jest.doMock('moment', () => {
moment.tz.setDefault('UTC');
return moment;
});
Date.now = jest.fn(() => new Date(Date.UTC(2019, 1, 1, 12, 13, 14)).valueOf());
jest.doMock("utils/vfs_fonts", () => ({}));

View File

@ -7,7 +7,7 @@
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
export default function Portal({containerId, children}) { export function Portal({containerId, children}) {
const container = document.getElementById(containerId); const container = document.getElementById(containerId);
if (container) if (container)
return ReactDOM.createPortal(children, container); return ReactDOM.createPortal(children, container);

View File

@ -1,3 +0,0 @@
import Portal from './Portal';
export {Portal}

View File

@ -5,9 +5,7 @@
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
/* eslint no-console: "off" */ import { ForisUrls } from "forisUrls";
import { ForisURLs } from "./constants";
const PROTOCOL = window.location.protocol === "http:" ? "ws" : "wss"; const PROTOCOL = window.location.protocol === "http:" ? "ws" : "wss";
@ -17,13 +15,13 @@ const URL = process.env.LIGHTTPD
const WAITING_FOR_CONNECTION_TIMEOUT = 500; const WAITING_FOR_CONNECTION_TIMEOUT = 500;
export default class WebSockets { export class WebSockets {
constructor() { constructor() {
this.ws = new WebSocket(URL); this.ws = new WebSocket(URL);
this.ws.onerror = (e) => { this.ws.onerror = (e) => {
if (window.location.pathname !== ForisURLs.login) { if (window.location.pathname !== ForisUrls.login) {
console.error("WS: Error observed, you aren't logged probably."); console.error("WS: Error observed, you aren't logged probably.");
window.location.replace(ForisURLs.login); window.location.replace(ForisUrls.login);
} }
console.log(`WS: Error: ${e}`); console.log(`WS: Error: ${e}`);
}; };

View File

@ -7,7 +7,7 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
export default function useWSForisModule(ws, module, action = "update_settings") { export function useWSForisModule(ws, module, action = "update_settings") {
const [data, setData] = useState(null); const [data, setData] = useState(null);
useEffect(() => { useEffect(() => {