1
0
mirror of https://gitlab.nic.cz/turris/reforis/foris-js.git synced 2024-11-14 17:35:35 +01:00

Merge branch 'bump-version-600' into 'dev'

Draft: Bump v6.0.0

See merge request turris/reforis/foris-js!219
This commit is contained in:
Aleksandr Gumroian 2024-06-07 16:40:03 +02:00
commit 9d229f91f2
62 changed files with 14177 additions and 14960 deletions

View File

@ -1,8 +1,3 @@
module.exports = { module.exports = {
extends: ["eslint-config-reforis", "prettier"], extends: "eslint-config-reforis",
plugins: ["prettier"],
rules: {
"prettier/prettier": ["error"],
"import/prefer-default-export": "off",
},
}; };

View File

@ -1,11 +0,0 @@
{
"singleQuote": false,
"printWidth": 80,
"proseWrap": "always",
"tabWidth": 4,
"useTabs": false,
"trailingComma": "es5",
"bracketSpacing": true,
"jsxBracketSameLine": false,
"semi": true
}

View File

@ -19,6 +19,7 @@ module.exports = {
collectCoverageFrom: ["src/**/*.{js,jsx}"], collectCoverageFrom: ["src/**/*.{js,jsx}"],
coverageDirectory: "coverage", coverageDirectory: "coverage",
testPathIgnorePatterns: ["/node_modules/", "/__fixtures__/", "/dist/"], testPathIgnorePatterns: ["/node_modules/", "/__fixtures__/", "/dist/"],
testEnvironment: "jsdom",
verbose: false, verbose: false,
setupFilesAfterEnv: [ setupFilesAfterEnv: [
"@testing-library/react/cleanup-after-each", "@testing-library/react/cleanup-after-each",

28105
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "foris", "name": "foris",
"version": "5.6.1", "version": "6.0.0",
"description": "Foris JS library is a set of components and utils for reForis application and plugins.", "description": "Foris JS library is a set of components and utils for reForis application and plugins.",
"author": "CZ.NIC, z.s.p.o.", "author": "CZ.NIC, z.s.p.o.",
"repository": { "repository": {
@ -14,12 +14,12 @@
"license": "GPL-3.0", "license": "GPL-3.0",
"main": "./src/index.js", "main": "./src/index.js",
"dependencies": { "dependencies": {
"axios": "^0.21.1", "axios": "^1.7.2",
"immutability-helper": "3.0.1", "immutability-helper": "^3.1.1",
"moment": "^2.24.0", "moment": "^2.30.1",
"qrcode.react": "^1.0.1", "qrcode.react": "^3.1.0",
"react-datetime": "^3.1.1", "react-datetime": "^3.2.0",
"react-uid": "^2.2.0" "react-uid": "^2.3.3"
}, },
"peerDependencies": { "peerDependencies": {
"bootstrap": "^5.3.3", "bootstrap": "^5.3.3",
@ -29,34 +29,33 @@
"react-router-dom": "^5.1.2" "react-router-dom": "^5.1.2"
}, },
"devDependencies": { "devDependencies": {
"@babel/cli": "^7.12.10", "@babel/cli": "^7.24.7",
"@babel/core": "^7.9.0", "@babel/core": "^7.24.7",
"@babel/plugin-transform-runtime": "^7.9.0", "@babel/plugin-transform-runtime": "^7.24.7",
"@babel/preset-env": "^7.9.0", "@babel/preset-env": "^7.24.7",
"@babel/preset-react": "^7.9.4", "@babel/preset-react": "^7.24.7",
"@fortawesome/fontawesome-free": "^6.5.2", "@fortawesome/fontawesome-free": "^6.5.2",
"@testing-library/react": "^8.0.9", "@testing-library/react": "^8.0.9",
"babel-loader": "^8.1.0", "babel-loader": "^8.1.0",
"babel-polyfill": "^6.26.0", "babel-polyfill": "^6.26.0",
"bootstrap": "^5.3.3", "bootstrap": "^5.3.3",
"css-loader": "^5.2.4", "css-loader": "^5.2.4",
"eslint": "^6.8.0", "eslint": "^8.57.0",
"eslint-config-prettier": "^6.11.0", "eslint-config-reforis": "^2.1.1",
"eslint-config-reforis": "^1.0.0",
"eslint-plugin-prettier": "^3.1.4",
"file-loader": "^6.0.0", "file-loader": "^6.0.0",
"jest": "^25.2.0", "jest": "^29.7.0",
"jest-mock-axios": "^3.2.0", "jest-environment-jsdom": "^29.7.0",
"moment-timezone": "^0.5.34", "jest-mock-axios": "^4.7.3",
"prettier": "2.0.5", "moment-timezone": "^0.5.45",
"prettier": "^3.3.1",
"prop-types": "15.8.1", "prop-types": "15.8.1",
"react": "16.9.0", "react": "16.9.0",
"react-dom": "16.9.0", "react-dom": "16.9.0",
"react-router-dom": "^5.1.2", "react-router-dom": "^5.1.2",
"react-styleguidist": "^11.2.0", "react-styleguidist": "^12.0.1",
"snapshot-diff": "^0.7.0", "snapshot-diff": "^0.10.0",
"style-loader": "^1.2.1", "style-loader": "^1.2.1",
"webpack": "^5.68.0" "webpack": "^5.91.0"
}, },
"scripts": { "scripts": {
"lint": "eslint src", "lint": "eslint src",

1
prettier.config.js Normal file
View File

@ -0,0 +1 @@
module.exports = require("eslint-config-reforis/prettier.config");

View File

@ -111,9 +111,8 @@ const useAPIPatch = createAPIHook("PATCH");
const useAPIPut = createAPIHook("PUT"); const useAPIPut = createAPIHook("PUT");
const useAPIDelete = createAPIHook("DELETE"); const useAPIDelete = createAPIHook("DELETE");
export { useAPIGet, useAPIPost, useAPIPatch, useAPIPut, useAPIDelete }; /* eslint-disable default-param-last */
function useAPIPolling(endpoint, delay = 1000, until) {
export function useAPIPolling(endpoint, delay = 1000, until) {
// delay ms // delay ms
const [state, setState] = useState({ state: API_STATE.INIT }); const [state, setState] = useState({ state: API_STATE.INIT });
const [getResponse, get] = useAPIGet(endpoint); const [getResponse, get] = useAPIGet(endpoint);
@ -133,3 +132,12 @@ export function useAPIPolling(endpoint, delay = 1000, until) {
return [state]; return [state];
} }
export {
useAPIGet,
useAPIPost,
useAPIPatch,
useAPIPut,
useAPIDelete,
useAPIPolling,
};

View File

@ -1,11 +1,12 @@
/* /*
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import React from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
export const ALERT_TYPES = Object.freeze({ export const ALERT_TYPES = Object.freeze({
@ -35,7 +36,7 @@ Alert.defaultProps = {
type: ALERT_TYPES.DANGER, type: ALERT_TYPES.DANGER,
}; };
export function Alert({ type, onDismiss, children }) { function Alert({ type, onDismiss, children }) {
return ( return (
<div <div
className={`alert alert-${type} ${ className={`alert alert-${type} ${
@ -54,3 +55,5 @@ export function Alert({ type, onDismiss, children }) {
</div> </div>
); );
} }
export default Alert;

View File

@ -1,11 +1,12 @@
/* /*
* Copyright (C) 2019-2023 CZ.NIC z.s.p.o. (https://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import React from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
Button.propTypes = { Button.propTypes = {
@ -24,13 +25,7 @@ Button.propTypes = {
]).isRequired, ]).isRequired,
}; };
export function Button({ function Button({ className, loading, forisFormSize, children, ...props }) {
className,
loading,
forisFormSize,
children,
...props
}) {
let buttonClass = className ? `btn ${className}` : "btn btn-primary"; let buttonClass = className ? `btn ${className}` : "btn btn-primary";
if (forisFormSize) { if (forisFormSize) {
buttonClass = `${buttonClass} col-12 col-md-3 col-lg-2`; buttonClass = `${buttonClass} col-12 col-md-3 col-lg-2`;
@ -53,3 +48,5 @@ export function Button({
</button> </button>
); );
} }
export default Button;

View File

@ -1,11 +1,12 @@
/* /*
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import React from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { useUID } from "react-uid"; import { useUID } from "react-uid";
@ -22,7 +23,7 @@ CheckBox.defaultProps = {
disabled: false, disabled: false,
}; };
export function CheckBox({ label, helpText, disabled, ...props }) { function CheckBox({ label, helpText, disabled, ...props }) {
const uid = useUID(); const uid = useUID();
return ( return (
@ -45,3 +46,5 @@ export function CheckBox({ label, helpText, disabled, ...props }) {
</div> </div>
); );
} }
export default CheckBox;

View File

@ -1,13 +1,15 @@
/* /*
* Copyright (C) 2019-2022 CZ.NIC z.s.p.o. (https://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import React, { useState, useRef } from "react"; import React, { useState, useRef } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { Input } from "./Input";
import Input from "./Input";
CopyInput.propTypes = { CopyInput.propTypes = {
/** Field label. */ /** Field label. */
@ -22,7 +24,7 @@ CopyInput.propTypes = {
readOnly: PropTypes.bool, readOnly: PropTypes.bool,
}; };
export function CopyInput({ value, ...props }) { function CopyInput({ value, ...props }) {
const inputTextRef = useRef(); const inputTextRef = useRef();
const [isCopied, setIsCopied] = useState(false); const [isCopied, setIsCopied] = useState(false);
@ -58,3 +60,5 @@ export function CopyInput({ value, ...props }) {
</Input> </Input>
); );
} }
export default CopyInput;

View File

@ -1,18 +1,19 @@
/* /*
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import React from "react"; import React from "react";
import moment from "moment/moment";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import Datetime from "react-datetime"; import Datetime from "react-datetime";
import moment from "moment/moment";
import "react-datetime/css/react-datetime.css"; import "react-datetime/css/react-datetime.css";
import "./DataTimeInput.css"; import "./DataTimeInput.css";
import { Input } from "./Input"; import Input from "./Input";
DataTimeInput.propTypes = { DataTimeInput.propTypes = {
/** Field label. */ /** Field label. */
@ -37,7 +38,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 function DataTimeInput({ function DataTimeInput({
value, value,
onChange, onChange,
isValidDate, isValidDate,
@ -46,13 +47,13 @@ export function DataTimeInput({
children, children,
...props ...props
}) { }) {
function renderInput(datetimeProps) { const renderInput = (datetimeProps) => {
return ( return (
<Input {...props} {...datetimeProps}> <Input {...props} {...datetimeProps}>
{children} {children}
</Input> </Input>
); );
} };
return ( return (
<Datetime <Datetime
@ -70,3 +71,5 @@ export function DataTimeInput({
/> />
); );
} }
export default DataTimeInput;

View File

@ -1,11 +1,12 @@
/* /*
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import React from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
DownloadButton.propTypes = { DownloadButton.propTypes = {
@ -21,7 +22,7 @@ DownloadButton.defaultProps = {
className: "btn-primary", className: "btn-primary",
}; };
export function DownloadButton({ href, className, children, ...props }) { function DownloadButton({ href, className, children, ...props }) {
return ( return (
<a <a
href={href} href={href}
@ -33,3 +34,5 @@ export function DownloadButton({ href, className, children, ...props }) {
</a> </a>
); );
} }
export default DownloadButton;

View File

@ -6,11 +6,14 @@
*/ */
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";
export const EmailInput = ({ ...props }) => <Input type="email" {...props} />; function EmailInput({ ...props }) {
return <Input type="email" {...props} />;
}
EmailInput.propTypes = { EmailInput.propTypes = {
/** Field label. */ /** Field label. */
@ -22,3 +25,5 @@ EmailInput.propTypes = {
/** Email value. */ /** Email value. */
value: PropTypes.string, value: PropTypes.string,
}; };
export default EmailInput;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
@ -8,7 +8,8 @@
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";
FileInput.propTypes = { FileInput.propTypes = {
/** Field label. */ /** Field label. */
@ -23,7 +24,7 @@ FileInput.propTypes = {
multiple: PropTypes.bool, multiple: PropTypes.bool,
}; };
export function FileInput({ ...props }) { function FileInput({ ...props }) {
return ( return (
<Input <Input
type="file" type="file"
@ -34,3 +35,5 @@ export function FileInput({ ...props }) {
/> />
); );
} }
export default FileInput;

View File

@ -6,11 +6,12 @@
*/ */
import React, { forwardRef } from "react"; import React, { forwardRef } from "react";
import { useUID } from "react-uid";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { useUID } from "react-uid";
/** Base bootstrap input component. */ /** Base bootstrap input component. */
export const Input = forwardRef( const Input = forwardRef(
( (
{ {
type, type,
@ -60,6 +61,8 @@ export const Input = forwardRef(
} }
); );
Input.displayName = "Input";
Input.propTypes = { Input.propTypes = {
type: PropTypes.string.isRequired, type: PropTypes.string.isRequired,
label: PropTypes.string.isRequired, label: PropTypes.string.isRequired,
@ -73,3 +76,5 @@ Input.propTypes = {
labelClassName: PropTypes.string, labelClassName: PropTypes.string,
groupClassName: PropTypes.string, groupClassName: PropTypes.string,
}; };
export default Input;

View File

@ -1,15 +1,16 @@
/* /*
* Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/) * Copyright (C) 2020-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import React, { useRef, useEffect } from "react"; import React, { useRef, useEffect } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { Portal } from "../utils/Portal";
import { useClickOutside } from "../utils/hooks"; import { useClickOutside } from "../utils/hooks";
import Portal from "../utils/Portal";
import "./Modal.css"; import "./Modal.css";
Modal.propTypes = { Modal.propTypes = {

View File

@ -1,15 +1,16 @@
/* /*
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import React from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import Input from "./Input";
import { useConditionalTimeout } from "../utils/hooks"; import { useConditionalTimeout } from "../utils/hooks";
import { Input } from "./Input";
import "./NumberInput.css"; import "./NumberInput.css";
NumberInput.propTypes = { NumberInput.propTypes = {
@ -31,7 +32,7 @@ NumberInput.defaultProps = {
value: 0, value: 0,
}; };
export function NumberInput({ onChange, inlineText, value, ...props }) { function NumberInput({ onChange, inlineText, value, ...props }) {
function updateValue(initialValue, difference) { function updateValue(initialValue, difference) {
onChange({ target: { value: initialValue + difference } }); onChange({ target: { value: initialValue + difference } });
} }
@ -73,3 +74,5 @@ export function NumberInput({ onChange, inlineText, value, ...props }) {
</Input> </Input>
); );
} }
export default NumberInput;

View File

@ -1,14 +1,15 @@
/* /*
* Copyright (C) 2019-2022 CZ.NIC z.s.p.o. (https://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
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. */
@ -25,7 +26,7 @@ PasswordInput.propTypes = {
newPass: PropTypes.bool, newPass: PropTypes.bool,
}; };
export function PasswordInput({ withEye, newPass, ...props }) { function PasswordInput({ withEye, newPass, ...props }) {
const [isHidden, setHidden] = useState(true); const [isHidden, setHidden] = useState(true);
return ( return (
@ -51,3 +52,5 @@ export function PasswordInput({ withEye, newPass, ...props }) {
</Input> </Input>
); );
} }
export default PasswordInput;

View File

@ -1,11 +1,12 @@
/* /*
* Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/) * Copyright (C) 2020-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import React from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { useUID } from "react-uid"; import { useUID } from "react-uid";
@ -36,15 +37,7 @@ RadioSet.propTypes = {
inline: PropTypes.bool, inline: PropTypes.bool,
}; };
export function RadioSet({ function RadioSet({ name, label, choices, value, helpText, inline, ...props }) {
name,
label,
choices,
value,
helpText,
inline,
...props
}) {
const uid = useUID(); const uid = useUID();
const radios = choices.map((choice, key) => { const radios = choices.map((choice, key) => {
const id = `${name}-${key}`; const id = `${name}-${key}`;
@ -94,27 +87,25 @@ Radio.propTypes = {
export function Radio({ label, id, helpText, inline, ...props }) { export function Radio({ label, id, helpText, inline, ...props }) {
return ( return (
<> <div
<div className={`mb-2 ${inline ? "form-check form-check-inline" : ""}`.trim()}
className={`mb-2 ${ >
inline ? "form-check form-check-inline" : "" <input
}`.trim()} id={id}
> className="form-check-input me-2"
<input type="radio"
id={id} {...props}
className="form-check-input me-2" />
type="radio" <label className="form-check-label" htmlFor={id}>
{...props} {label}
/> {helpText && (
<label className="form-check-label" htmlFor={id}> <div className="form-text">
{label} <small>{helpText}</small>
{helpText && ( </div>
<div className="form-text"> )}
<small>{helpText}</small> </label>
</div> </div>
)}
</label>
</div>
</>
); );
} }
export default RadioSet;

View File

@ -1,11 +1,12 @@
/* /*
* Copyright (C) 2019-2022 CZ.NIC z.s.p.o. (https://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import React from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { useUID } from "react-uid"; import { useUID } from "react-uid";
@ -20,7 +21,7 @@ Select.propTypes = {
helpText: PropTypes.string, helpText: PropTypes.string,
}; };
export function Select({ label, choices, helpText, ...props }) { function Select({ label, choices, helpText, ...props }) {
const uid = useUID(); const uid = useUID();
const options = Object.keys(choices).map((choice) => ( const options = Object.keys(choices).map((choice) => (
@ -45,3 +46,5 @@ export function Select({ label, choices, helpText, ...props }) {
</div> </div>
); );
} }
export default Select;

View File

@ -6,6 +6,7 @@
*/ */
import React from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import "./Spinner.css"; import "./Spinner.css";

View File

@ -1,11 +1,12 @@
/* /*
* Copyright (c) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/) * Copyright (c) 2020-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import React from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { useUID } from "react-uid"; import { useUID } from "react-uid";
@ -20,7 +21,7 @@ Switch.propTypes = {
switchHeading: PropTypes.bool, switchHeading: PropTypes.bool,
}; };
export function Switch({ label, helpText, switchHeading, ...props }) { function Switch({ label, helpText, switchHeading, ...props }) {
const uid = useUID(); const uid = useUID();
return ( return (
@ -31,9 +32,7 @@ export function Switch({ label, helpText, switchHeading, ...props }) {
> >
<input <input
type="checkbox" type="checkbox"
className={`form-check-input ${ className={`form-check-input ${switchHeading ? "me-2" : ""}`.trim()}
switchHeading ? "me-2" : ""
}`.trim()}
role="switch" role="switch"
id={uid} id={uid}
{...props} {...props}
@ -49,3 +48,5 @@ export function Switch({ label, helpText, switchHeading, ...props }) {
</div> </div>
); );
} }
export default Switch;

View File

@ -1,16 +1,19 @@
/* /*
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
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";
export const TextInput = ({ ...props }) => <Input type="text" {...props} />; function TextInput({ ...props }) {
return <Input type="text" {...props} />;
}
TextInput.propTypes = { TextInput.propTypes = {
/** Field label. */ /** Field label. */
@ -20,3 +23,5 @@ 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 "../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 "../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 { DownloadButton } from "../DownloadButton"; import DownloadButton from "../DownloadButton";
describe("<DownloadButton />", () => { describe("<DownloadButton />", () => {
it("should have download attribute", () => { it("should have download attribute", () => {

View File

@ -9,7 +9,7 @@ import React from "react";
import { render, fireEvent, getByLabelText, wait } from "customTestRender"; import { render, fireEvent, getByLabelText, wait } from "customTestRender";
import { NumberInput } from "../NumberInput"; import NumberInput from "../NumberInput";
describe("<NumberInput/>", () => { describe("<NumberInput/>", () => {
const onChangeMock = jest.fn(); const onChangeMock = jest.fn();

View File

@ -9,7 +9,7 @@ import React from "react";
import { render } from "customTestRender"; import { render } from "customTestRender";
import { PasswordInput } from "../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 "../RadioSet"; import RadioSet from "../RadioSet";
const TEST_CHOICES = [ const TEST_CHOICES = [
{ {

View File

@ -14,7 +14,7 @@ import {
render, render,
} from "customTestRender"; } from "customTestRender";
import { Select } from "../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 { Switch } from "../Switch"; import Switch from "../Switch";
describe("<Switch/>", () => { describe("<Switch/>", () => {
it("Render switch", () => { it("Render switch", () => {

View File

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

View File

@ -1,11 +1,12 @@
/* /*
* Copyright (C) 2019-2021 CZ.NIC z.s.p.o. (http://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
/** Bootstrap column size for form fields */ /** Bootstrap column size for form fields */
// eslint-disable-next-line import/prefer-default-export const formFieldsSize = "card p-4 col-sm-12 col-lg-12 p-0 mb-4";
export const formFieldsSize = "card p-4 col-sm-12 col-lg-12 p-0 mb-4"; const buttonFormFieldsSize = "col-sm-12 col-lg-12 p-0 mb-3";
export const buttonFormFieldsSize = "col-sm-12 col-lg-12 p-0 mb-3";
export { formFieldsSize, buttonFormFieldsSize };

View File

@ -1,22 +1,22 @@
/* /*
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { useAPIPost } from "../api/hooks"; import { useAPIPost } from "../api/hooks";
import { API_STATE } from "../api/utils"; import { API_STATE } from "../api/utils";
import { ForisURLs } from "../utils/forisUrls"; import Button from "../bootstrap/Button";
import { Button } from "../bootstrap/Button";
import { Modal, ModalHeader, ModalBody, ModalFooter } from "../bootstrap/Modal"; import { Modal, ModalHeader, ModalBody, ModalFooter } from "../bootstrap/Modal";
import { useAlert } from "../context/alertContext/AlertContext"; import { useAlert } from "../context/alertContext/AlertContext";
import { ForisURLs } from "../utils/forisUrls";
export function RebootButton(props) { function RebootButton(props) {
const [triggered, setTriggered] = useState(false); const [triggered, setTriggered] = useState(false);
const [modalShown, setModalShown] = useState(false); const [modalShown, setModalShown] = useState(false);
const [triggerRebootStatus, triggerReboot] = useAPIPost(ForisURLs.reboot); const [triggerRebootStatus, triggerReboot] = useAPIPost(ForisURLs.reboot);
@ -28,11 +28,11 @@ export function RebootButton(props) {
} }
}); });
function rebootHandler() { const rebootHandler = () => {
setTriggered(true); setTriggered(true);
triggerReboot(); triggerReboot();
setModalShown(false); setModalShown(false);
} };
return ( return (
<> <>
@ -76,3 +76,5 @@ function RebootModal({ shown, setShown, onReboot }) {
</Modal> </Modal>
); );
} }
export default RebootButton;

View File

@ -1,26 +1,27 @@
/* /*
* Copyright (C) 2019-2022 CZ.NIC z.s.p.o. (https://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { Button } from "../../bootstrap/Button";
import { useAlert } from "../../context/alertContext/AlertContext";
import { ALERT_TYPES } from "../../bootstrap/Alert";
import { useAPIPost } from "../../api/hooks"; import { useAPIPost } from "../../api/hooks";
import { API_STATE } from "../../api/utils"; import { API_STATE } from "../../api/utils";
import { ALERT_TYPES } from "../../bootstrap/Alert";
import Button from "../../bootstrap/Button";
import { formFieldsSize } from "../../bootstrap/constants"; import { formFieldsSize } from "../../bootstrap/constants";
import { useAlert } from "../../context/alertContext/AlertContext";
ResetWiFiSettings.propTypes = { ResetWiFiSettings.propTypes = {
ws: PropTypes.object.isRequired, ws: PropTypes.object.isRequired,
endpoint: PropTypes.string.isRequired, endpoint: PropTypes.string.isRequired,
}; };
export function ResetWiFiSettings({ ws, endpoint }) { function ResetWiFiSettings({ ws, endpoint }) {
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
useEffect(() => { useEffect(() => {
@ -44,11 +45,11 @@ export function ResetWiFiSettings({ ws, endpoint }) {
} }
}, [postResetResponse, setAlert]); }, [postResetResponse, setAlert]);
function onReset() { const onReset = () => {
dismissAlert(); dismissAlert();
setIsLoading(true); setIsLoading(true);
postReset(); postReset();
} };
return ( return (
<div className={formFieldsSize}> <div className={formFieldsSize}>
@ -72,3 +73,5 @@ export function ResetWiFiSettings({ ws, endpoint }) {
</div> </div>
); );
} }
export default ResetWiFiSettings;

View File

@ -6,15 +6,17 @@
*/ */
import React from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { Switch } from "../../bootstrap/Switch";
import { PasswordInput } from "../../bootstrap/PasswordInput";
import { RadioSet } from "../../bootstrap/RadioSet";
import { Select } from "../../bootstrap/Select";
import { TextInput } from "../../bootstrap/TextInput";
import WiFiQRCode from "./WiFiQRCode";
import WifiGuestForm from "./WiFiGuestForm";
import { HELP_TEXTS, HTMODES, HWMODES, ENCRYPTIONMODES } from "./constants"; import { HELP_TEXTS, HTMODES, HWMODES, ENCRYPTIONMODES } from "./constants";
import WifiGuestForm from "./WiFiGuestForm";
import WiFiQRCode from "./WiFiQRCode";
import PasswordInput from "../../bootstrap/PasswordInput";
import RadioSet from "../../bootstrap/RadioSet";
import Select from "../../bootstrap/Select";
import Switch from "../../bootstrap/Switch";
import TextInput from "../../bootstrap/TextInput";
WiFiForm.propTypes = { WiFiForm.propTypes = {
formData: PropTypes.shape({ devices: PropTypes.arrayOf(PropTypes.object) }) formData: PropTypes.shape({ devices: PropTypes.arrayOf(PropTypes.object) })
@ -267,8 +269,8 @@ function getChannelChoices(device) {
channelChoices[availableChannel.number.toString()] = ` channelChoices[availableChannel.number.toString()] = `
${availableChannel.number} ${availableChannel.number}
(${availableChannel.frequency} MHz ${ (${availableChannel.frequency} MHz ${
availableChannel.radar ? " ,DFS" : "" availableChannel.radar ? " ,DFS" : ""
}) })
`; `;
}); });
}); });

View File

@ -1,18 +1,19 @@
/* /*
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import React from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { TextInput } from "../../bootstrap/TextInput";
import { Switch } from "../../bootstrap/Switch";
import { PasswordInput } from "../../bootstrap/PasswordInput";
import WiFiQRCode from "./WiFiQRCode";
import { HELP_TEXTS } from "./constants"; import { HELP_TEXTS } from "./constants";
import WiFiQRCode from "./WiFiQRCode";
import PasswordInput from "../../bootstrap/PasswordInput";
import Switch from "../../bootstrap/Switch";
import TextInput from "../../bootstrap/TextInput";
WifiGuestForm.propTypes = { WifiGuestForm.propTypes = {
formData: PropTypes.shape({ formData: PropTypes.shape({

View File

@ -6,18 +6,19 @@
*/ */
import React, { useState } from "react"; import React, { useState } from "react";
import QRCode from "qrcode.react";
import PropTypes from "prop-types";
import { ForisURLs } from "../../utils/forisUrls"; import PropTypes from "prop-types";
import { Button } from "../../bootstrap/Button"; import QRCode from "qrcode.react";
import { createAndDownloadPdf, toQRCodeContent } from "./qrCodeHelpers";
import Button from "../../bootstrap/Button";
import { import {
Modal, Modal,
ModalBody, ModalBody,
ModalFooter, ModalFooter,
ModalHeader, ModalHeader,
} from "../../bootstrap/Modal"; } from "../../bootstrap/Modal";
import { createAndDownloadPdf, toQRCodeContent } from "./qrCodeHelpers"; import { ForisURLs } from "../../utils/forisUrls";
WiFiQRCode.propTypes = { WiFiQRCode.propTypes = {
SSID: PropTypes.string.isRequired, SSID: PropTypes.string.isRequired,

View File

@ -1,16 +1,17 @@
/* /*
* Copyright (C) 2019-2021 CZ.NIC z.s.p.o. (http://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import React from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { ForisForm } from "../../form/components/ForisForm"; import ResetWiFiSettings from "./ResetWiFiSettings";
import WiFiForm from "./WiFiForm"; import WiFiForm from "./WiFiForm";
import { ResetWiFiSettings } from "./ResetWiFiSettings"; import ForisForm from "../../form/components/ForisForm";
WiFiSettings.propTypes = { WiFiSettings.propTypes = {
ws: PropTypes.object.isRequired, ws: PropTypes.object.isRequired,
@ -19,7 +20,7 @@ WiFiSettings.propTypes = {
hasGuestNetwork: PropTypes.bool, hasGuestNetwork: PropTypes.bool,
}; };
export function WiFiSettings({ ws, endpoint, resetEndpoint, hasGuestNetwork }) { function WiFiSettings({ ws, endpoint, resetEndpoint, hasGuestNetwork }) {
return ( return (
<> <>
<ForisForm <ForisForm
@ -117,3 +118,5 @@ export function validator(formData) {
}); });
return JSON.stringify(formErrors).match(/\[[{},?]+\]/) ? null : formErrors; return JSON.stringify(formErrors).match(/\[[{},?]+\]/) ? null : formErrors;
} }
export default WiFiSettings;

View File

@ -9,12 +9,12 @@ import React from "react";
import { render, fireEvent, wait } from "customTestRender"; import { render, fireEvent, wait } from "customTestRender";
import mockAxios from "jest-mock-axios"; import mockAxios from "jest-mock-axios";
import { WebSockets } from "webSockets/WebSockets"; import WebSockets from "webSockets/WebSockets";
import { mockJSONError } from "testUtils/network"; import { mockJSONError } from "testUtils/network";
import { mockSetAlert } from "testUtils/alertContextMock"; import { mockSetAlert } from "testUtils/alertContextMock";
import { ALERT_TYPES } from "../../../bootstrap/Alert"; import { ALERT_TYPES } from "../../../bootstrap/Alert";
import { ResetWiFiSettings } from "../ResetWiFiSettings"; import ResetWiFiSettings from "../ResetWiFiSettings";
describe("<ResetWiFiSettings/>", () => { describe("<ResetWiFiSettings/>", () => {
const webSockets = new WebSockets(); const webSockets = new WebSockets();

View File

@ -10,7 +10,7 @@ import diffSnapshot from "snapshot-diff";
import mockAxios from "jest-mock-axios"; import mockAxios from "jest-mock-axios";
import { fireEvent, render, wait } from "customTestRender"; import { fireEvent, render, wait } from "customTestRender";
import { WebSockets } from "webSockets/WebSockets"; import WebSockets from "webSockets/WebSockets";
import { mockJSONError } from "testUtils/network"; import { mockJSONError } from "testUtils/network";
import { import {
@ -19,7 +19,7 @@ import {
twoDevices, twoDevices,
threeDevices, threeDevices,
} from "./__fixtures__/wifiSettings"; } from "./__fixtures__/wifiSettings";
import { WiFiSettings, validator, byteCount } from "../WiFiSettings"; import WiFiSettings, { validator, byteCount } from "../WiFiSettings";
describe("<WiFiSettings/>", () => { describe("<WiFiSettings/>", () => {
let firstRender; let firstRender;

View File

@ -6,13 +6,13 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
+ Second value + Second value
@@ -243,207 +243,95 @@ @@ -243,207 +243,95 @@
value=\\"0\\" value="0"
> >
auto auto
</option> </option>
<option <option
- value=\\"36\\" - value="36"
+ value=\\"1\\" + value="1"
> >
- 36 - 36
@ -22,8 +22,8 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
</option> </option>
<option <option
- value=\\"40\\" - value="40"
+ value=\\"2\\" + value="2"
> >
- 40 - 40
@ -33,8 +33,8 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
</option> </option>
<option <option
- value=\\"44\\" - value="44"
+ value=\\"3\\" + value="3"
> >
- 44 - 44
@ -44,7 +44,7 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
</option> </option>
<option <option
- value=\\"48\\" - value="48"
- > - >
- -
- 48 - 48
@ -52,7 +52,7 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
- -
- </option> - </option>
- <option - <option
- value=\\"52\\" - value="52"
- > - >
- -
- 52 - 52
@ -60,7 +60,7 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
- -
- </option> - </option>
- <option - <option
- value=\\"56\\" - value="56"
- > - >
- -
- 56 - 56
@ -68,8 +68,8 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
- -
- </option> - </option>
- <option - <option
- value=\\"60\\" - value="60"
+ value=\\"4\\" + value="4"
> >
- 60 - 60
@ -79,8 +79,8 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
</option> </option>
<option <option
- value=\\"64\\" - value="64"
+ value=\\"5\\" + value="5"
> >
- 64 - 64
@ -90,8 +90,8 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
</option> </option>
<option <option
- value=\\"100\\" - value="100"
+ value=\\"6\\" + value="6"
> >
- 100 - 100
@ -101,8 +101,8 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
</option> </option>
<option <option
- value=\\"104\\" - value="104"
+ value=\\"7\\" + value="7"
> >
- 104 - 104
@ -112,8 +112,8 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
</option> </option>
<option <option
- value=\\"108\\" - value="108"
+ value=\\"8\\" + value="8"
> >
- 108 - 108
@ -123,8 +123,8 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
</option> </option>
<option <option
- value=\\"112\\" - value="112"
+ value=\\"9\\" + value="9"
> >
- 112 - 112
@ -134,8 +134,8 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
</option> </option>
<option <option
- value=\\"116\\" - value="116"
+ value=\\"10\\" + value="10"
> >
- 116 - 116
@ -145,8 +145,8 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
</option> </option>
<option <option
- value=\\"120\\" - value="120"
+ value=\\"11\\" + value="11"
> >
- 120 - 120
@ -154,7 +154,7 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
- -
- </option> - </option>
- <option - <option
- value=\\"124\\" - value="124"
- > - >
- -
- 124 - 124
@ -162,7 +162,7 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
- -
- </option> - </option>
- <option - <option
- value=\\"128\\" - value="128"
- > - >
- -
- 128 - 128
@ -170,7 +170,7 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
- -
- </option> - </option>
- <option - <option
- value=\\"132\\" - value="132"
- > - >
- -
- 132 - 132
@ -178,7 +178,7 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
- -
- </option> - </option>
- <option - <option
- value=\\"136\\" - value="136"
- > - >
- -
- 136 - 136
@ -186,7 +186,7 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
- -
- </option> - </option>
- <option - <option
- value=\\"140\\" - value="140"
- > - >
- -
- 140 - 140
@ -194,7 +194,7 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
- -
- </option> - </option>
- <option - <option
- value=\\"144\\" - value="144"
- > - >
- -
- 144 - 144
@ -202,7 +202,7 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
- -
- </option> - </option>
- <option - <option
- value=\\"149\\" - value="149"
- > - >
- -
- 149 - 149
@ -210,7 +210,7 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
- -
- </option> - </option>
- <option - <option
- value=\\"153\\" - value="153"
- > - >
- -
- 153 - 153
@ -218,7 +218,7 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
- -
- </option> - </option>
- <option - <option
- value=\\"157\\" - value="157"
- > - >
- -
- 157 - 157
@ -226,7 +226,7 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
- -
- </option> - </option>
- <option - <option
- value=\\"161\\" - value="161"
- > - >
- -
- 161 - 161
@ -234,7 +234,7 @@ exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
- -
- </option> - </option>
- <option - <option
- value=\\"165\\" - value="165"
- > - >
- -
- 165 - 165
@ -346,41 +346,41 @@ exports[`<WiFiSettings/> Snapshot guest network. 1`] = `
</div> </div>
</div> </div>
+ <div + <div
+ class=\\"mb-3\\" + class="mb-3"
+ > + >
+ <label + <label
+ class=\\"form-label\\" + class="form-label"
+ for=\\"24\\" + for="12"
+ > + >
+ SSID + SSID
+ </label> + </label>
+ <div + <div
+ class=\\"input-group\\" + class="input-group"
+ > + >
+ <input + <input
+ class=\\"form-control\\" + class="form-control"
+ id=\\"24\\" + id="12"
+ type=\\"text\\" + type="text"
+ value=\\"TestGuestSSID\\" + value="TestGuestSSID"
+ /> + />
+ <div + <div
+ class=\\"input-group-append\\" + class="input-group-append"
+ > + >
+ <button + <button
+ class=\\"input-group-text\\" + class="input-group-text"
+ type=\\"button\\" + type="button"
+ > + >
+ <img + <img
+ alt=\\"QR\\" + alt="QR"
+ src=\\"/reforis/static/reforis/imgs/QR_icon.svg\\" + src="/reforis/static/reforis/imgs/QR_icon.svg"
+ style=\\"opacity: 0.67;\\" + style="opacity: 0.67;"
+ width=\\"20\\" + width="20"
+ /> + />
+ </button> + </button>
+ </div> + </div>
+ </div> + </div>
+ <div + <div
+ class=\\"form-text\\" + class="form-text"
+ > + >
+ <small> + <small>
+ SSID which contains non-standard characters could cause problems on some devices. + SSID which contains non-standard characters could cause problems on some devices.
@ -388,41 +388,41 @@ exports[`<WiFiSettings/> Snapshot guest network. 1`] = `
+ </div> + </div>
+ </div> + </div>
+ <div + <div
+ class=\\"mb-3\\" + class="mb-3"
+ > + >
+ <label + <label
+ class=\\"form-label\\" + class="form-label"
+ for=\\"25\\" + for="13"
+ > + >
+ Password + Password
+ </label> + </label>
+ <div + <div
+ class=\\"input-group\\" + class="input-group"
+ > + >
+ <input + <input
+ autocomplete=\\"current-password\\" + autocomplete="current-password"
+ class=\\"form-control is-invalid\\" + class="form-control is-invalid"
+ id=\\"25\\" + id="13"
+ required=\\"\\" + required=""
+ type=\\"password\\" + type="password"
+ value=\\"\\" + value=""
+ /> + />
+ <button + <button
+ class=\\"input-group-text\\" + class="input-group-text"
+ type=\\"button\\" + type="button"
+ > + >
+ <i + <i
+ class=\\"fa fa-eye\\" + class="fa fa-eye"
+ /> + />
+ </button> + </button>
+ </div> + </div>
+ <div + <div
+ class=\\"invalid-feedback\\" + class="invalid-feedback"
+ > + >
+ Password must contain at least 8 symbols + Password must contain at least 8 symbols
+ </div> + </div>
+ <div + <div
+ class=\\"form-text\\" + class="form-text"
+ > + >
+ <small> + <small>
+ WPA2/3 pre-shared key, that is required to connect to the network. + WPA2/3 pre-shared key, that is required to connect to the network.
@ -431,17 +431,17 @@ exports[`<WiFiSettings/> Snapshot guest network. 1`] = `
+ </div> + </div>
<hr /> <hr />
<div <div
class=\\"form-check form-switch mb-3 d-flex align-items-center\\" class="form-check form-switch mb-3 d-flex align-items-center"
> >
<input <input
@@ -553,10 +637,11 @@ @@ -553,10 +637,11 @@
<div <div
class=\\"text-end\\" class="text-end"
> >
<button <button
class=\\"btn btn-primary col-12 col-md-3 col-lg-2 d-inline-flex justify-content-center align-items-center\\" class="btn btn-primary col-12 col-md-3 col-lg-2 d-inline-flex justify-content-center align-items-center"
+ disabled=\\"\\" + disabled=""
type=\\"submit\\" type="submit"
> >
<span> <span>
Save Save
@ -460,38 +460,38 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
</label> </label>
</div> </div>
+ <div + <div
+ class=\\"mb-3\\" + class="mb-3"
+ > + >
+ <label + <label
+ class=\\"form-label\\" + class="form-label"
+ for=\\"4\\" + for="3"
+ > + >
+ SSID + SSID
+ </label> + </label>
+ <div + <div
+ class=\\"input-group\\" + class="input-group"
+ > + >
+ <input + <input
+ class=\\"form-control\\" + class="form-control"
+ id=\\"4\\" + id="3"
+ required=\\"\\" + required=""
+ type=\\"text\\" + type="text"
+ value=\\"TestSSID1\\" + value="TestSSID1"
+ /> + />
+ <button + <button
+ class=\\"input-group-text\\" + class="input-group-text"
+ type=\\"button\\" + type="button"
+ > + >
+ <img + <img
+ alt=\\"QR\\" + alt="QR"
+ src=\\"/reforis/static/reforis/imgs/QR_icon.svg\\" + src="/reforis/static/reforis/imgs/QR_icon.svg"
+ style=\\"opacity: 0.67;\\" + style="opacity: 0.67;"
+ width=\\"20\\" + width="20"
+ /> + />
+ </button> + </button>
+ </div> + </div>
+ <div + <div
+ class=\\"form-text\\" + class="form-text"
+ > + >
+ <small> + <small>
+ SSID which contains non-standard characters could cause problems on some devices. + SSID which contains non-standard characters could cause problems on some devices.
@ -499,36 +499,36 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ </div> + </div>
+ </div> + </div>
+ <div + <div
+ class=\\"mb-3\\" + class="mb-3"
+ > + >
+ <label + <label
+ class=\\"form-label\\" + class="form-label"
+ for=\\"5\\" + for="4"
+ > + >
+ Password + Password
+ </label> + </label>
+ <div + <div
+ class=\\"input-group\\" + class="input-group"
+ > + >
+ <input + <input
+ autocomplete=\\"current-password\\" + autocomplete="current-password"
+ class=\\"form-control\\" + class="form-control"
+ id=\\"5\\" + id="4"
+ required=\\"\\" + required=""
+ type=\\"password\\" + type="password"
+ value=\\"TestPass\\" + value="TestPass"
+ /> + />
+ <button + <button
+ class=\\"input-group-text\\" + class="input-group-text"
+ type=\\"button\\" + type="button"
+ > + >
+ <i + <i
+ class=\\"fa fa-eye\\" + class="fa fa-eye"
+ /> + />
+ </button> + </button>
+ </div> + </div>
+ <div + <div
+ class=\\"form-text\\" + class="form-text"
+ > + >
+ <small> + <small>
+ WPA2/3 pre-shared key, that is required to connect to the network. + WPA2/3 pre-shared key, that is required to connect to the network.
@ -536,22 +536,22 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ </div> + </div>
+ </div> + </div>
+ <div + <div
+ class=\\"form-check form-switch mb-3 null\\" + class="form-check form-switch mb-3 null"
+ > + >
+ <input + <input
+ class=\\"form-check-input\\" + class="form-check-input"
+ id=\\"6\\" + id="5"
+ role=\\"switch\\" + role="switch"
+ type=\\"checkbox\\" + type="checkbox"
+ /> + />
+ <label + <label
+ class=\\"form-check-label\\" + class="form-check-label"
+ for=\\"6\\" + for="5"
+ > + >
+ Hide SSID + Hide SSID
+ </label> + </label>
+ <div + <div
+ class=\\"form-text\\" + class="form-text"
+ > + >
+ <small> + <small>
+ If set, network is not visible when scanning for available networks. + If set, network is not visible when scanning for available networks.
@ -559,51 +559,51 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ </div> + </div>
+ </div> + </div>
+ <div + <div
+ class=\\"mb-3\\" + class="mb-3"
+ > + >
+ <label + <label
+ class=\\"d-block\\" + class="d-block"
+ for=\\"7\\" + for="6"
+ > + >
+ GHz + GHz
+ </label> + </label>
+ <div + <div
+ class=\\"mb-2 form-check form-check-inline\\" + class="mb-2 form-check form-check-inline"
+ > + >
+ <input + <input
+ class=\\"form-check-input me-2\\" + class="form-check-input me-2"
+ id=\\"hwmode-0-0\\" + id="hwmode-0-0"
+ name=\\"hwmode-0\\" + name="hwmode-0"
+ type=\\"radio\\" + type="radio"
+ value=\\"11g\\" + value="11g"
+ /> + />
+ <label + <label
+ class=\\"form-check-label\\" + class="form-check-label"
+ for=\\"hwmode-0-0\\" + for="hwmode-0-0"
+ > + >
+ 2.4 + 2.4
+ </label> + </label>
+ </div> + </div>
+ <div + <div
+ class=\\"mb-2 form-check form-check-inline\\" + class="mb-2 form-check form-check-inline"
+ > + >
+ <input + <input
+ checked=\\"\\" + checked=""
+ class=\\"form-check-input me-2\\" + class="form-check-input me-2"
+ id=\\"hwmode-0-1\\" + id="hwmode-0-1"
+ name=\\"hwmode-0\\" + name="hwmode-0"
+ type=\\"radio\\" + type="radio"
+ value=\\"11a\\" + value="11a"
+ /> + />
+ <label + <label
+ class=\\"form-check-label\\" + class="form-check-label"
+ for=\\"hwmode-0-1\\" + for="hwmode-0-1"
+ > + >
+ 5 + 5
+ </label> + </label>
+ </div> + </div>
+ <div + <div
+ class=\\"form-text\\" + class="form-text"
+ > + >
+ <small> + <small>
+ The 2.4 GHz band is more widely supported by clients, but tends to have more interference. The 5 GHz band is a newer standard and may not be supported by all your devices. It usually has less interference, but the signal does not carry so well indoors. + The 2.4 GHz band is more widely supported by clients, but tends to have more interference. The 5 GHz band is a newer standard and may not be supported by all your devices. It usually has less interference, but the signal does not carry so well indoors.
@ -611,51 +611,51 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ </div> + </div>
+ </div> + </div>
+ <div + <div
+ class=\\"mb-3\\" + class="mb-3"
+ > + >
+ <label + <label
+ class=\\"form-label\\" + class="form-label"
+ for=\\"8\\" + for="7"
+ > + >
+ 802.11n/ac/ax mode + 802.11n/ac/ax mode
+ </label> + </label>
+ <select + <select
+ class=\\"form-select\\" + class="form-select"
+ id=\\"8\\" + id="7"
+ > + >
+ <option + <option
+ value=\\"NOHT\\" + value="NOHT"
+ > + >
+ Disabled + Disabled
+ </option> + </option>
+ <option + <option
+ value=\\"HT20\\" + value="HT20"
+ > + >
+ 802.11n - 20 MHz wide channel + 802.11n - 20 MHz wide channel
+ </option> + </option>
+ <option + <option
+ value=\\"HT40\\" + value="HT40"
+ > + >
+ 802.11n - 40 MHz wide channel + 802.11n - 40 MHz wide channel
+ </option> + </option>
+ <option + <option
+ value=\\"VHT20\\" + value="VHT20"
+ > + >
+ 802.11ac - 20 MHz wide channel + 802.11ac - 20 MHz wide channel
+ </option> + </option>
+ <option + <option
+ value=\\"VHT40\\" + value="VHT40"
+ > + >
+ 802.11ac - 40 MHz wide channel + 802.11ac - 40 MHz wide channel
+ </option> + </option>
+ <option + <option
+ value=\\"VHT80\\" + value="VHT80"
+ > + >
+ 802.11ac - 80 MHz wide channel + 802.11ac - 80 MHz wide channel
+ </option> + </option>
+ </select> + </select>
+ <div + <div
+ class=\\"form-text\\" + class="form-text"
+ > + >
+ <small> + <small>
+ Change this to adjust 802.11n/ac/ax mode of operation. 802.11n with 40 MHz wide channels can yield higher throughput but can cause more interference in the network. If you don't know what to choose, use the default option with 20 MHz wide channel. + Change this to adjust 802.11n/ac/ax mode of operation. 802.11n with 40 MHz wide channels can yield higher throughput but can cause more interference in the network. If you don't know what to choose, use the default option with 20 MHz wide channel.
@ -663,25 +663,25 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ </div> + </div>
+ </div> + </div>
+ <div + <div
+ class=\\"mb-3\\" + class="mb-3"
+ > + >
+ <label + <label
+ class=\\"form-label\\" + class="form-label"
+ for=\\"9\\" + for="8"
+ > + >
+ Channel + Channel
+ </label> + </label>
+ <select + <select
+ class=\\"form-select\\" + class="form-select"
+ id=\\"9\\" + id="8"
+ > + >
+ <option + <option
+ value=\\"0\\" + value="0"
+ > + >
+ auto + auto
+ </option> + </option>
+ <option + <option
+ value=\\"36\\" + value="36"
+ > + >
+ +
+ 36 + 36
@ -689,7 +689,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"40\\" + value="40"
+ > + >
+ +
+ 40 + 40
@ -697,7 +697,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"44\\" + value="44"
+ > + >
+ +
+ 44 + 44
@ -705,7 +705,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"48\\" + value="48"
+ > + >
+ +
+ 48 + 48
@ -713,7 +713,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"52\\" + value="52"
+ > + >
+ +
+ 52 + 52
@ -721,7 +721,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"56\\" + value="56"
+ > + >
+ +
+ 56 + 56
@ -729,7 +729,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"60\\" + value="60"
+ > + >
+ +
+ 60 + 60
@ -737,7 +737,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"64\\" + value="64"
+ > + >
+ +
+ 64 + 64
@ -745,7 +745,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"100\\" + value="100"
+ > + >
+ +
+ 100 + 100
@ -753,7 +753,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"104\\" + value="104"
+ > + >
+ +
+ 104 + 104
@ -761,7 +761,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"108\\" + value="108"
+ > + >
+ +
+ 108 + 108
@ -769,7 +769,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"112\\" + value="112"
+ > + >
+ +
+ 112 + 112
@ -777,7 +777,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"116\\" + value="116"
+ > + >
+ +
+ 116 + 116
@ -785,7 +785,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"120\\" + value="120"
+ > + >
+ +
+ 120 + 120
@ -793,7 +793,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"124\\" + value="124"
+ > + >
+ +
+ 124 + 124
@ -801,7 +801,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"128\\" + value="128"
+ > + >
+ +
+ 128 + 128
@ -809,7 +809,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"132\\" + value="132"
+ > + >
+ +
+ 132 + 132
@ -817,7 +817,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"136\\" + value="136"
+ > + >
+ +
+ 136 + 136
@ -825,7 +825,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"140\\" + value="140"
+ > + >
+ +
+ 140 + 140
@ -833,7 +833,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"144\\" + value="144"
+ > + >
+ +
+ 144 + 144
@ -841,7 +841,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"149\\" + value="149"
+ > + >
+ +
+ 149 + 149
@ -849,7 +849,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"153\\" + value="153"
+ > + >
+ +
+ 153 + 153
@ -857,7 +857,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"157\\" + value="157"
+ > + >
+ +
+ 157 + 157
@ -865,7 +865,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"161\\" + value="161"
+ > + >
+ +
+ 161 + 161
@ -873,7 +873,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ +
+ </option> + </option>
+ <option + <option
+ value=\\"165\\" + value="165"
+ > + >
+ +
+ 165 + 165
@ -883,36 +883,36 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ </select> + </select>
+ </div> + </div>
+ <div + <div
+ class=\\"mb-3\\" + class="mb-3"
+ > + >
+ <label + <label
+ class=\\"form-label\\" + class="form-label"
+ for=\\"10\\" + for="9"
+ > + >
+ Encryption + Encryption
+ </label> + </label>
+ <select + <select
+ class=\\"form-select\\" + class="form-select"
+ id=\\"10\\" + id="9"
+ > + >
+ <option + <option
+ value=\\"WPA3\\" + value="WPA3"
+ > + >
+ WPA3 only + WPA3 only
+ </option> + </option>
+ <option + <option
+ value=\\"WPA2/3\\" + value="WPA2/3"
+ > + >
+ WPA3 with WPA2 as fallback (default) + WPA3 with WPA2 as fallback (default)
+ </option> + </option>
+ <option + <option
+ value=\\"WPA2\\" + value="WPA2"
+ > + >
+ WPA2 only + WPA2 only
+ </option> + </option>
+ </select> + </select>
+ <div + <div
+ class=\\"form-text\\" + class="form-text"
+ > + >
+ <small> + <small>
+ The WPA3 standard is the new most secure encryption method that is suggested to be used with any device that supports it. The older devices without WPA3 support require older WPA2. If you experience issues with connecting older devices, try to enable WPA2. + The WPA3 standard is the new most secure encryption method that is suggested to be used with any device that supports it. The older devices without WPA3 support require older WPA2. If you experience issues with connecting older devices, try to enable WPA2.
@ -920,22 +920,22 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ </div> + </div>
+ </div> + </div>
+ <div + <div
+ class=\\"form-check form-switch mb-3 null\\" + class="form-check form-switch mb-3 null"
+ > + >
+ <input + <input
+ class=\\"form-check-input\\" + class="form-check-input"
+ id=\\"11\\" + id="10"
+ role=\\"switch\\" + role="switch"
+ type=\\"checkbox\\" + type="checkbox"
+ /> + />
+ <label + <label
+ class=\\"form-check-label\\" + class="form-check-label"
+ for=\\"11\\" + for="10"
+ > + >
+ Disable Management Frame Protection + Disable Management Frame Protection
+ </label> + </label>
+ <div + <div
+ class=\\"form-text\\" + class="form-text"
+ > + >
+ <small> + <small>
+ In case you have trouble connecting to WiFi Access Point, try disabling Management Frame Protection. + In case you have trouble connecting to WiFi Access Point, try disabling Management Frame Protection.
@ -943,22 +943,22 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ </div> + </div>
+ </div> + </div>
+ <div + <div
+ class=\\"form-check form-switch mb-3 null\\" + class="form-check form-switch mb-3 null"
+ > + >
+ <input + <input
+ class=\\"form-check-input\\" + class="form-check-input"
+ id=\\"12\\" + id="11"
+ role=\\"switch\\" + role="switch"
+ type=\\"checkbox\\" + type="checkbox"
+ /> + />
+ <label + <label
+ class=\\"form-check-label\\" + class="form-check-label"
+ for=\\"12\\" + for="11"
+ > + >
+ Enable Guest Wi-Fi + Enable Guest Wi-Fi
+ </label> + </label>
+ <div + <div
+ class=\\"form-text\\" + class="form-text"
+ > + >
+ <small> + <small>
+ Enables Wi-Fi for guests, which is separated from LAN network. Devices connected to this network are allowed to access the internet, but aren't allowed to access other devices and the configuration interface of the router. Parameters of the guest network can be set in the Guest network tab. + Enables Wi-Fi for guests, which is separated from LAN network. Devices connected to this network are allowed to access the internet, but aren't allowed to access other devices and the configuration interface of the router. Parameters of the guest network can be set in the Guest network tab.
@ -967,7 +967,7 @@ exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
+ </div> + </div>
<hr /> <hr />
<div <div
class=\\"form-check form-switch mb-3 d-flex align-items-center\\" class="form-check form-switch mb-3 d-flex align-items-center"
> >
<input" <input"
`; `;

View File

@ -18,7 +18,7 @@ import mockAxios from "jest-mock-axios";
import { mockJSONError } from "testUtils/network"; import { mockJSONError } from "testUtils/network";
import { mockSetAlert } from "testUtils/alertContextMock"; import { mockSetAlert } from "testUtils/alertContextMock";
import { RebootButton } from "../RebootButton"; import RebootButton from "../RebootButton";
describe("<RebootButton/>", () => { describe("<RebootButton/>", () => {
let componentContainer; let componentContainer;

View File

@ -1,15 +1,16 @@
/* /*
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import React, { useState, useContext, useCallback } from "react"; import React, { useState, useContext, useCallback, useMemo } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { Alert, ALERT_TYPES } from "../../bootstrap/Alert"; import Alert, { ALERT_TYPES } from "../../bootstrap/Alert";
import { Portal } from "../../utils/Portal"; import Portal from "../../utils/Portal";
AlertContextProvider.propTypes = { AlertContextProvider.propTypes = {
children: PropTypes.oneOfType([ children: PropTypes.oneOfType([
@ -30,6 +31,10 @@ function AlertContextProvider({ children }) {
); );
const dismissAlert = useCallback(() => setAlert(null), [setAlert]); const dismissAlert = useCallback(() => setAlert(null), [setAlert]);
const contextValue = useMemo(
() => [setAlertWrapper, dismissAlert],
[setAlertWrapper, dismissAlert]
);
return ( return (
<> <>
@ -40,7 +45,7 @@ function AlertContextProvider({ children }) {
</Alert> </Alert>
</Portal> </Portal>
)} )}
<AlertContext.Provider value={[setAlertWrapper, dismissAlert]}> <AlertContext.Provider value={contextValue}>
{children} {children}
</AlertContext.Provider> </AlertContext.Provider>
</> </>

View File

@ -1,17 +1,17 @@
/* /*
* Copyright (C) 2019-2022 CZ.NIC z.s.p.o. (https://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import React, { useContext, useEffect } from "react"; import React, { useContext, useEffect, useMemo } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { useAPIGet } from "../../api/hooks"; import { useAPIGet } from "../../api/hooks";
import { ForisURLs } from "../../utils/forisUrls";
import { Spinner } from "../../bootstrap/Spinner"; import { Spinner } from "../../bootstrap/Spinner";
import { ForisURLs } from "../../utils/forisUrls";
CustomizationContextProvider.propTypes = { CustomizationContextProvider.propTypes = {
children: PropTypes.oneOfType([ children: PropTypes.oneOfType([
@ -30,20 +30,31 @@ function CustomizationContextProvider({ children }) {
getCustomization(); getCustomization();
}, [getCustomization]); }, [getCustomization]);
const deviceDetails = useMemo(
() => getCustomizationResponse.data || {},
[getCustomizationResponse.data]
);
const isCustomized = useMemo(
() =>
!!(
deviceDetails.customization !== undefined &&
deviceDetails.customization === "shield"
),
[deviceDetails.customization]
);
const contextValue = useMemo(
() => ({ deviceDetails, isCustomized }),
[deviceDetails, isCustomized]
);
if (getCustomizationResponse.state !== "success") { if (getCustomizationResponse.state !== "success") {
return <Spinner fullScreen />; return <Spinner fullScreen />;
} }
const deviceDetails = getCustomizationResponse.data || {};
const isCustomized = !!(
deviceDetails &&
deviceDetails.customization !== undefined &&
deviceDetails.customization === "shield"
);
return ( return (
<CustomizationContext.Provider value={{ deviceDetails, isCustomized }}> <CustomizationContext.Provider value={contextValue}>
{children} {children}
</CustomizationContext.Provider> </CustomizationContext.Provider>
); );

View File

@ -9,8 +9,8 @@ import React from "react";
import { act, fireEvent, render, waitForElement } from "customTestRender"; import { act, fireEvent, render, waitForElement } from "customTestRender";
import mockAxios from "jest-mock-axios"; import mockAxios from "jest-mock-axios";
import { WebSockets } from "webSockets/WebSockets"; import WebSockets from "webSockets/WebSockets";
import { ForisForm } from "../components/ForisForm"; import ForisForm from "../components/ForisForm";
// It's possible to unittest each hooks via react-hooks-testing-library. // It's possible to unittest each hooks via react-hooks-testing-library.
// But it's better and easier to test it by test components which uses this hooks. // But it's better and easier to test it by test components which uses this hooks.

View File

@ -1,24 +1,24 @@
/* /*
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { Prompt } from "react-router-dom"; import { Prompt } from "react-router-dom";
import { ALERT_TYPES } from "../../bootstrap/Alert"; import { STATES as SUBMIT_BUTTON_STATES, SubmitButton } from "./SubmitButton";
import { useAPIPost } from "../../api/hooks";
import { API_STATE } from "../../api/utils"; import { API_STATE } from "../../api/utils";
import { ALERT_TYPES } from "../../bootstrap/Alert";
import { formFieldsSize } from "../../bootstrap/constants"; import { formFieldsSize } from "../../bootstrap/constants";
import { Spinner } from "../../bootstrap/Spinner"; import { Spinner } from "../../bootstrap/Spinner";
import { useAlert } from "../../context/alertContext/AlertContext"; import { useAlert } from "../../context/alertContext/AlertContext";
import { useAPIPost } from "../../api/hooks"; import ErrorMessage from "../../utils/ErrorMessage";
import { useForisModule, useForm } from "../hooks"; import { useForisModule, useForm } from "../hooks";
import { STATES as SUBMIT_BUTTON_STATES, SubmitButton } from "./SubmitButton";
import { ErrorMessage } from "../../utils/ErrorMessage";
ForisForm.propTypes = { ForisForm.propTypes = {
/** Optional WebSocket object. See `scr/common/WebSockets.js`. /** Optional WebSocket object. See `scr/common/WebSockets.js`.
@ -89,7 +89,7 @@ ForisForm.defaultProps = {
* use exposed `ReactRouterDOM` object from `react-router-dom` library which is exposed by reForis. * use exposed `ReactRouterDOM` object from `react-router-dom` library which is exposed by reForis.
* See README for more information. * See README for more information.
* */ * */
export function ForisForm({ function ForisForm({
ws, ws,
forisConfig, forisConfig,
prepData, prepData,
@ -131,16 +131,16 @@ export function ForisForm({
return <Spinner />; return <Spinner />;
} }
function onSubmitHandler(event) { const onSubmitHandler = (event) => {
event.preventDefault(); event.preventDefault();
resetFormData(); resetFormData();
dismissAlert(); dismissAlert();
const copiedFormData = JSON.parse(JSON.stringify(formState.data)); const copiedFormData = JSON.parse(JSON.stringify(formState.data));
const preparedData = prepDataToSubmit(copiedFormData); const preparedData = prepDataToSubmit(copiedFormData);
post({ data: preparedData }); post({ data: preparedData });
} };
function getSubmitButtonState() { const getSubmitButtonState = () => {
if (postState.state === API_STATE.SENDING) { if (postState.state === API_STATE.SENDING) {
return SUBMIT_BUTTON_STATES.SAVING; return SUBMIT_BUTTON_STATES.SAVING;
} }
@ -148,7 +148,7 @@ export function ForisForm({
return SUBMIT_BUTTON_STATES.LOAD; return SUBMIT_BUTTON_STATES.LOAD;
} }
return SUBMIT_BUTTON_STATES.READY; return SUBMIT_BUTTON_STATES.READY;
} };
const formIsDisabled = const formIsDisabled =
disabled || disabled ||
@ -174,7 +174,7 @@ export function ForisForm({
) )
: onSubmitHandler; : onSubmitHandler;
function getMessageOnLeavingPage() { const getMessageOnLeavingPage = () => {
if ( if (
JSON.stringify(formState.data) === JSON.stringify(formState.data) ===
JSON.stringify(formState.initialData) JSON.stringify(formState.initialData)
@ -183,7 +183,7 @@ export function ForisForm({
return _( return _(
"Changes you made may not be saved. Are you sure you want to leave?" "Changes you made may not be saved. Are you sure you want to leave?"
); );
} };
return ( return (
<div className={formFieldsSize}> <div className={formFieldsSize}>
@ -200,3 +200,5 @@ export function ForisForm({
</div> </div>
); );
} }
export default ForisForm;

View File

@ -6,9 +6,10 @@
*/ */
import React from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { Button } from "../../bootstrap/Button"; import Button from "../../bootstrap/Button";
export const STATES = { export const STATES = {
READY: 1, READY: 1,

View File

@ -1,15 +1,16 @@
/* /*
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import { useCallback, useEffect, useReducer } from "react"; 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";
const FORM_ACTIONS = { const FORM_ACTIONS = {
updateValue: 1, updateValue: 1,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2019-2022 CZ.NIC z.s.p.o. (https://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
@ -17,32 +17,32 @@ export {
export { API_STATE } from "./api/utils"; export { API_STATE } from "./api/utils";
// Bootstrap // Bootstrap
export { Alert, ALERT_TYPES } from "./bootstrap/Alert"; export { default as Alert, ALERT_TYPES } from "./bootstrap/Alert";
export { Button } from "./bootstrap/Button"; export { default as Button } from "./bootstrap/Button";
export { CheckBox } from "./bootstrap/CheckBox"; export { default as CheckBox } from "./bootstrap/CheckBox";
export { CopyInput } from "./bootstrap/CopyInput"; export { default as CopyInput } from "./bootstrap/CopyInput";
export { DownloadButton } from "./bootstrap/DownloadButton"; export { default as DownloadButton } from "./bootstrap/DownloadButton";
export { DataTimeInput } from "./bootstrap/DataTimeInput"; export { default as DataTimeInput } from "./bootstrap/DataTimeInput";
export { EmailInput } from "./bootstrap/EmailInput"; export { default as EmailInput } from "./bootstrap/EmailInput";
export { FileInput } from "./bootstrap/FileInput"; export { default as FileInput } from "./bootstrap/FileInput";
export { Input } from "./bootstrap/Input"; export { default as Input } from "./bootstrap/Input";
export { NumberInput } from "./bootstrap/NumberInput"; export { default as NumberInput } from "./bootstrap/NumberInput";
export { PasswordInput } from "./bootstrap/PasswordInput"; export { default as PasswordInput } from "./bootstrap/PasswordInput";
export { Radio, RadioSet } from "./bootstrap/RadioSet"; export { default as RadioSet, Radio } from "./bootstrap/RadioSet";
export { Select } from "./bootstrap/Select"; export { default as Select } from "./bootstrap/Select";
export { TextInput } from "./bootstrap/TextInput"; export { default as TextInput } from "./bootstrap/TextInput";
export { formFieldsSize, buttonFormFieldsSize } from "./bootstrap/constants"; export { formFieldsSize, buttonFormFieldsSize } from "./bootstrap/constants";
export { Switch } from "./bootstrap/Switch"; export { default as Switch } from "./bootstrap/Switch";
export { Spinner, SpinnerElement } from "./bootstrap/Spinner"; export { Spinner, SpinnerElement } from "./bootstrap/Spinner";
export { Modal, ModalBody, ModalFooter, ModalHeader } from "./bootstrap/Modal"; export { Modal, ModalBody, ModalFooter, ModalHeader } from "./bootstrap/Modal";
// Common // Common
export { RebootButton } from "./common/RebootButton"; export { default as RebootButton } from "./common/RebootButton";
export { WiFiSettings } from "./common/WiFiSettings/WiFiSettings"; export { default as WiFiSettings } from "./common/WiFiSettings/WiFiSettings";
export { ResetWiFiSettings } from "./common/WiFiSettings/ResetWiFiSettings"; export { default as ResetWiFiSettings } from "./common/WiFiSettings/ResetWiFiSettings";
// Form // Form
export { ForisForm } from "./form/components/ForisForm"; export { default as ForisForm } from "./form/components/ForisForm";
export { export {
SubmitButton, SubmitButton,
STATES as SUBMIT_BUTTON_STATES, STATES as SUBMIT_BUTTON_STATES,
@ -50,11 +50,11 @@ export {
export { useForisModule, useForm } from "./form/hooks"; export { useForisModule, useForm } from "./form/hooks";
// WebSockets // WebSockets
export { useWSForisModule } from "./webSockets/hooks"; export { default as useWSForisModule } from "./webSockets/hooks";
export { WebSockets } from "./webSockets/WebSockets"; export { default as WebSockets } from "./webSockets/WebSockets";
// Utils // Utils
export { Portal } from "./utils/Portal"; export { default as Portal } from "./utils/Portal";
export { export {
undefinedIfEmpty, undefinedIfEmpty,
withoutUndefinedKeys, withoutUndefinedKeys,
@ -68,11 +68,11 @@ export {
withError, withError,
withErrorMessage, withErrorMessage,
} from "./utils/conditionalHOCs"; } from "./utils/conditionalHOCs";
export { ErrorMessage } from "./utils/ErrorMessage"; export { default as ErrorMessage } from "./utils/ErrorMessage";
export { useClickOutside } from "./utils/hooks"; export { useClickOutside } from "./utils/hooks";
export { toLocaleDateString } from "./utils/datetime"; export { default as toLocaleDateString } from "./utils/datetime";
export { displayCard } from "./utils/displayCard"; export { default as displayCard } from "./utils/displayCard";
export { isPluginInstalled } from "./utils/isPluginInstalled"; export { default as isPluginInstalled } from "./utils/isPluginInstalled";
// Foris URL // Foris URL
export { ForisURLs, REFORIS_URL_PREFIX } from "./utils/forisUrls"; export { ForisURLs, REFORIS_URL_PREFIX } from "./utils/forisUrls";

View File

@ -1,11 +1,12 @@
/* /*
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import React from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
ErrorMessage.propTypes = { ErrorMessage.propTypes = {
@ -16,6 +17,8 @@ ErrorMessage.defaultProps = {
message: _("An error occurred while fetching data."), message: _("An error occurred while fetching data."),
}; };
export function ErrorMessage({ message }) { function ErrorMessage({ message }) {
return <p className="text-center text-danger">{message}</p>; return <p className="text-center text-danger">{message}</p>;
} }
export default ErrorMessage;

View File

@ -1,14 +1,22 @@
/* /*
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import PropTypes from "prop-types";
import ReactDOM from "react-dom"; import ReactDOM from "react-dom";
export function Portal({ containerId, children }) { Portal.propTypes = {
containerId: PropTypes.string.isRequired,
children: PropTypes.node.isRequired,
};
function Portal({ containerId, children }) {
const container = document.getElementById(containerId); const container = document.getElementById(containerId);
if (container) return ReactDOM.createPortal(children, container); if (container) return ReactDOM.createPortal(children, container);
return null; return null;
} }
export default Portal;

View File

@ -5,7 +5,7 @@
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import { toLocaleDateString } from "../datetime"; import toLocaleDateString from "../datetime";
describe("toLocaleDateString", () => { describe("toLocaleDateString", () => {
it("should work with different locale", () => { it("should work with different locale", () => {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
@ -7,16 +7,23 @@
import React from "react"; import React from "react";
import { Spinner } from "../bootstrap/Spinner"; import ErrorMessage from "./ErrorMessage";
import { API_STATE } from "../api/utils"; import { API_STATE } from "../api/utils";
import { ErrorMessage } from "./ErrorMessage"; import { Spinner } from "../bootstrap/Spinner";
function withEither(conditionalFn, Either) { function withEither(conditionalFn, Either) {
return (Component) => (props) => { return (Component) => {
if (conditionalFn(props)) { function WithEither(props) {
return <Either {...props} />; if (conditionalFn(props)) {
return <Either {...props} />;
}
return <Component {...props} />;
} }
return <Component {...props} />;
// Setting displayName for better debugging
WithEither.displayName = `WithEither(${Component.displayName || Component.name || "Component"})`;
return WithEither;
}; };
} }

View File

@ -1,9 +1,8 @@
import moment from "moment"; import moment from "moment";
export function toLocaleDateString( function toLocaleDateString(date, { inputFormat, outputFormat = "LLL" } = {}) {
date,
{ inputFormat, outputFormat = "LLL" } = {}
) {
const parsedDate = inputFormat ? moment(date, inputFormat) : moment(date); const parsedDate = inputFormat ? moment(date, inputFormat) : moment(date);
return parsedDate.locale(ForisTranslations.locale).format(outputFormat); return parsedDate.locale(ForisTranslations.locale).format(outputFormat);
} }
export default toLocaleDateString;

View File

@ -1,11 +1,11 @@
/* /*
* Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/) * Copyright (C) 2020-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
export function displayCard({ package_lists: packages }, cardName) { function displayCard({ package_lists: packages }, cardName) {
const enabledPackagesNames = []; const enabledPackagesNames = [];
packages packages
.filter((item) => item.enabled) .filter((item) => item.enabled)
@ -21,3 +21,5 @@ export function displayCard({ package_lists: packages }, cardName) {
}); });
return enabledPackagesNames.includes(cardName); return enabledPackagesNames.includes(cardName);
} }
export default displayCard;

View File

@ -1,9 +1,11 @@
/* /*
* Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/) * Copyright (C) 2020-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
export const isPluginInstalled = (pluginName) => const isPluginInstalled = (pluginName) =>
ForisPlugins.some((plugin) => plugin.name === pluginName); ForisPlugins.some((plugin) => plugin.name === pluginName);
export default isPluginInstalled;

View File

@ -23,12 +23,15 @@ export const ERROR_MESSAGES = {
const REs = { const REs = {
IPv4: /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/, IPv4: /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,
IPv6: /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/, IPv6: /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/,
IPv6Prefix: /^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))$/, IPv6Prefix:
/^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))$/,
domain: /^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/, domain: /^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/,
hostname: /^[a-z\d]([a-z\d-]{0,61}[a-z\d])?(\.[a-z\d]([a-z\d-]{0,61}[a-z\d])?)*$/i, hostname:
/^[a-z\d]([a-z\d-]{0,61}[a-z\d])?(\.[a-z\d]([a-z\d-]{0,61}[a-z\d])?)*$/i,
DUID: /^([0-9a-fA-F]{2}){4}([0-9a-fA-F]{2})*$/, DUID: /^([0-9a-fA-F]{2}){4}([0-9a-fA-F]{2})*$/,
MAC: /^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$/, MAC: /^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$/,
MultipleEmails: /^([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+ *)( *, *[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+ *)*$/, MultipleEmails:
/^([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+ *)( *, *[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+ *)*$/,
}; };
const createValidator = (fieldType) => (value) => { const createValidator = (fieldType) => (value) => {

View File

@ -10,14 +10,12 @@
const PROTOCOL = window.location.protocol === "http:" ? "ws" : "wss"; const PROTOCOL = window.location.protocol === "http:" ? "ws" : "wss";
const URL = process.env.LIGHTTPD const URL = process.env.LIGHTTPD
? `${PROTOCOL}://${window.location.host}/${ ? `${PROTOCOL}://${window.location.host}/${process.env.WSPATH || "foris-ws"}`
process.env.WSPATH || "foris-ws"
}`
: `${PROTOCOL}://${window.location.hostname}:9081`; : `${PROTOCOL}://${window.location.hostname}:9081`;
const WAITING_FOR_CONNECTION_TIMEOUT = 500; const WAITING_FOR_CONNECTION_TIMEOUT = 500;
export class WebSockets { class WebSockets {
constructor() { constructor() {
this.ws = new WebSocket(URL); this.ws = new WebSocket(URL);
this.ws.onerror = (e) => { this.ws.onerror = (e) => {
@ -122,3 +120,5 @@ export class WebSockets {
this.ws.close(); this.ws.close();
} }
} }
export default WebSockets;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/) * Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
* *
* This is free software, licensed under the GNU General Public License v3. * This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information. * See /LICENSE for more information.
@ -7,7 +7,8 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
export function useWSForisModule( /* eslint-disable default-param-last */
function useWSForisModule(
ws, ws,
module, module,
action = "update_settings", action = "update_settings",
@ -41,3 +42,5 @@ export function useWSForisModule(
return [data]; return [data];
} }
export default useWSForisModule;

View File

@ -105,8 +105,5 @@ module.exports = {
}, },
], ],
}, },
devServer: {
publicPath: "/",
},
}, },
}; };