mirror of
https://gitlab.nic.cz/turris/reforis/foris-js.git
synced 2025-06-17 13:56:15 +02:00
Compare commits
2 Commits
84097fa8e0
...
improve-in
Author | SHA1 | Date | |
---|---|---|---|
40309b4b4d | |||
8c929baeb5 |
@ -1,3 +1,8 @@
|
||||
module.exports = {
|
||||
extends: "eslint-config-reforis",
|
||||
extends: ["eslint-config-reforis", "prettier"],
|
||||
plugins: ["prettier"],
|
||||
rules: {
|
||||
"prettier/prettier": ["error"],
|
||||
"import/prefer-default-export": "off",
|
||||
},
|
||||
};
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -51,3 +51,4 @@ coverage.xml
|
||||
dist/
|
||||
foris-*.tgz
|
||||
styleguide/
|
||||
testUtils
|
||||
|
@ -1,4 +1,4 @@
|
||||
image: registry.nic.cz/turris/reforis/reforis/reforis-image
|
||||
image: node:10-alpine
|
||||
|
||||
stages:
|
||||
- test
|
||||
@ -6,7 +6,7 @@ stages:
|
||||
- publish
|
||||
|
||||
before_script:
|
||||
- apt-get update && apt-get install -y make
|
||||
- apk add make
|
||||
- npm install
|
||||
|
||||
test:
|
||||
|
11
.prettierrc
Normal file
11
.prettierrc
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"singleQuote": false,
|
||||
"printWidth": 80,
|
||||
"proseWrap": "always",
|
||||
"tabWidth": 4,
|
||||
"useTabs": false,
|
||||
"trailingComma": "es5",
|
||||
"bracketSpacing": true,
|
||||
"jsxBracketSameLine": false,
|
||||
"semi": true
|
||||
}
|
85
Makefile
85
Makefile
@ -1,31 +1,20 @@
|
||||
# Copyright (C) 2019-2022 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
# See /LICENSE for more information.
|
||||
|
||||
PROJECT="Foris JS"
|
||||
# Retrieve Foris JS version from package.json
|
||||
VERSION= $(shell sed -En "s/.*version['\"]: ['\"](.+)['\"].*/\1/p" package.json)
|
||||
COPYRIGHT_HOLDER="CZ.NIC, z.s.p.o. (https://www.nic.cz/)"
|
||||
MSGID_BUGS_ADDRESS="tech.support@turris.cz"
|
||||
.PHONY: all install-js watch-js build-js collect-files pack publish-beta publish-latest lint test test-js-update-snapshots create-messages update-messages docs docs-watch clean
|
||||
|
||||
DEV_PYTHON=python3
|
||||
VENV_NAME?=venv
|
||||
JS_DIR=js
|
||||
VENV_BIN=$(shell pwd)/$(VENV_NAME)/bin
|
||||
|
||||
.PHONY: all
|
||||
all:
|
||||
@echo "make install-js"
|
||||
@echo " Install npm dependencies."
|
||||
@echo "make lint"
|
||||
@echo " Run linter on the project."
|
||||
@echo "make test"
|
||||
@echo " Run tests on the project."
|
||||
@echo "make test-js-watch"
|
||||
@echo " Run tests on the project in watch mode."
|
||||
@echo "make test-js-update-snapshots"
|
||||
@echo " Update snapshots."
|
||||
@echo " Install dependencies"
|
||||
@echo "make watch-js"
|
||||
@echo " Compile JS in watch mode."
|
||||
@echo "make build-js"
|
||||
@echo " Compile JS."
|
||||
@echo "make lint-js"
|
||||
@echo " Run linter"
|
||||
@echo "make test-js"
|
||||
@echo " Run tests"
|
||||
@echo "make create-messages"
|
||||
@echo " Create locale messages (.pot)."
|
||||
@echo "make update-messages"
|
||||
@ -37,93 +26,43 @@ all:
|
||||
@echo "make clean"
|
||||
@echo " Remove python artifacts and virtualenv."
|
||||
|
||||
|
||||
# Preparation
|
||||
|
||||
.PHONY: venv
|
||||
venv: $(VENV_NAME)/bin/activate
|
||||
$(VENV_NAME)/bin/activate:
|
||||
test -d $(VENV_NAME) || $(DEV_PYTHON) -m virtualenv -p $(DEV_PYTHON) $(VENV_NAME)
|
||||
$(VENV_BIN)/$(DEV_PYTHON) -m pip install -r requirements.txt
|
||||
touch $(VENV_NAME)/bin/activate
|
||||
|
||||
|
||||
# Installation
|
||||
|
||||
.PHONY: install-js
|
||||
install-js: package.json
|
||||
npm install --save-dev
|
||||
|
||||
|
||||
# Publishing
|
||||
|
||||
.PHONY: collect-files
|
||||
collect-files:
|
||||
sh scripts/collect_files.sh
|
||||
|
||||
.PHONY: pack
|
||||
pack: collect-files
|
||||
cd dist && npm pack
|
||||
|
||||
.PHONY: publish-beta
|
||||
publish-beta: collect-files
|
||||
sh scripts/publish.sh beta
|
||||
|
||||
.PHONY: publish-latest
|
||||
publish-latest: collect-files
|
||||
sh scripts/publish.sh latest
|
||||
|
||||
|
||||
# Linting
|
||||
|
||||
.PHONY: lint
|
||||
lint:
|
||||
npm run lint
|
||||
|
||||
.PHONY: lint-js-fix
|
||||
lint-js-fix:
|
||||
npm run lint:fix
|
||||
|
||||
|
||||
# Testing
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
npm test
|
||||
|
||||
.PHONY: test-js-watch
|
||||
test-js-watch:
|
||||
cd $(JS_DIR); npm test -- --watch
|
||||
|
||||
.PHONY: test-js-update-snapshots
|
||||
test-js-update-snapshots:
|
||||
npm test -- -u
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
.PHONY: create-messages
|
||||
create-messages: venv
|
||||
$(VENV_BIN)/pybabel extract -F babel.cfg -o ./translations/forisjs.pot . --project=$(PROJECT) --version=$(VERSION) --copyright-holder=$(COPYRIGHT_HOLDER) --msgid-bugs-address=$(MSGID_BUGS_ADDRESS)
|
||||
|
||||
.PHONY: update-messages
|
||||
$(VENV_BIN)/pybabel extract -F babel.cfg -o ./translations/forisjs.pot .
|
||||
update-messages: venv
|
||||
$(VENV_BIN)/pybabel update -i ./translations/forisjs.pot -d ./translations -D forisjs --update-header-comment
|
||||
$(VENV_BIN)/pybabel update -i ./translations/forisjs.pot -d ./translations -D forisjs
|
||||
|
||||
|
||||
# Documentation
|
||||
|
||||
.PHONY: docs
|
||||
docs:
|
||||
npm run-script docs
|
||||
|
||||
.PHONY: docs-watch
|
||||
docs-watch:
|
||||
npm run-script docs:watch
|
||||
|
||||
|
||||
# Other
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf node_modules dist
|
||||
|
@ -1,36 +0,0 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import Styled from "rsg-components/Styled";
|
||||
import logo from "./logo.svg";
|
||||
|
||||
const styles = ({ fontFamily }) => ({
|
||||
logo: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
margin: 0,
|
||||
fontFamily: fontFamily.base,
|
||||
fontSize: 18,
|
||||
fontWeight: "normal",
|
||||
},
|
||||
image: {
|
||||
height: "1.3em",
|
||||
marginLeft: "-0.2em",
|
||||
marginRight: "0.2em",
|
||||
},
|
||||
});
|
||||
|
||||
export function LogoRenderer({ classes, children }) {
|
||||
return (
|
||||
<h1 className={classes.logo}>
|
||||
<img className={classes.image} src={logo} alt="React logo" />
|
||||
{children}
|
||||
</h1>
|
||||
);
|
||||
}
|
||||
|
||||
LogoRenderer.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
children: PropTypes.node,
|
||||
};
|
||||
|
||||
export default Styled(styles)(LogoRenderer);
|
@ -1,3 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000">
|
||||
<path d="M288.258 240.0394L717.5586-.44c.803 62.277-1.8207 124.502-1.4996 186.7266 1.8208 7.6343-7.2288 10.1966-12.102 13.4908L286.4375 432.1518l1.8206-192.1124zm2.284 277.645L711 278.3176l-.8416 192.7742L457.357 614.514l-1.842 289.03-167.7097 95.8926 2.7365-481.753z"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 349 B |
@ -1,15 +1,15 @@
|
||||
Sooner or later, you will face with situation when you want/need to make some
|
||||
changes in the library. Then the most important tool for you it's the
|
||||
Sooner or later you will face with situation when you want/need to make some
|
||||
changes in the library. Then the most important tool for you it's
|
||||
[`npm link`](https://docs.npmjs.com/cli/link).
|
||||
|
||||
Please, notice that it will not work if you link the library just from the root
|
||||
of the repo. It happens due to the location of sources `./src`. You need to pack
|
||||
the library first, `make pack` and then link it from the `./dist` directory.
|
||||
Please, notice that it will not work if you link library just from root of the
|
||||
repo. It happens due to location of sources `./src`. You need to pack library
|
||||
first `make pack` and then link it from `./dist` directory.
|
||||
|
||||
Yeah, it's not such a comfortable solution for development. But it can be fixed
|
||||
by writing a small script similar to making a pack but by linking every file and
|
||||
directory from `./src` to the same directory and linking then from it. Notice
|
||||
that you need to link a `package.json` and a `package-lock.json` as well.
|
||||
Yeah it's not such comfortable solution for development. But it can fixed by
|
||||
writing small script similar as `make pack` but with linking every file and
|
||||
directory from `./src` to the some directory and linking then from it. Notice
|
||||
that you need to link `package.json` and `package-lock.json` as well.
|
||||
|
||||
So step by step:
|
||||
|
||||
|
@ -1,4 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" fill="white">
|
||||
<path d="M49.5 171.722222222222h400v133.333333333333h-200v22.222222222223h-88.888888888889v-22.222222222223H49.5V171.722222222222zm22.222222222222 111.111111111111h44.444444444445v-66.666666666667h22.222222222222v66.666666666667h22.222222222222v-88.888888888889H71.722222222222v88.888888888889zm111.111111111111-88.888888888889v111.111111111111h44.444444444445v-22.222222222222h44.444444444444v-88.888888888889h-88.888888888889zm44.444444444445 22.222222222222H249.5v44.444444444445h-22.222222222222v-44.444444444445zm66.666666666666-22.222222222222v88.888888888889h44.444444444445v-66.666666666667h22.222222222222v66.666666666667h22.222222222222v-66.666666666667h22.222222222222v66.666666666667h22.222222222223v-88.888888888889H293.944444444444z" fill="#cb3837" />
|
||||
<path d="M71.722222222222 282.833333333333h44.444444444444v-66.666666666667h22.222222222223v66.666666666667h22.222222222222v-88.888888888889H71.722222222222zm111.111111111111-88.888888888889v111.111111111111h44.444444444444v-22.222222222222h44.444444444445v-88.888888888889h-88.888888888889zM249.5 260.611111111111h-22.222222222223v-44.444444444445H249.5v44.444444444445zm44.444444444444-66.666666666667v88.888888888889h44.444444444444v-66.666666666667h22.222222222223v66.666666666667h22.222222222222v-66.666666666667h22.222222222222v66.666666666667h22.222222222222v-88.888888888889z" />
|
||||
</svg>
|
Before Width: | Height: | Size: 1.4 KiB |
6
docs/intro.md
Normal file
6
docs/intro.md
Normal file
@ -0,0 +1,6 @@
|
||||
Foris JS library is set of components and utils for Foris JS application and
|
||||
plugins.
|
||||
|
||||
Please notice that all of these components or utils are used in reForis and
|
||||
plugins. If you like to study by example I would recommend to full-text search
|
||||
these repos.
|
@ -1,37 +0,0 @@
|
||||
Welcome! This is the official documentation for Foris JS.
|
||||
|
||||
## What Foris JS is
|
||||
|
||||
Foris JS library is a set of components and utils for reForis application and
|
||||
plugins.
|
||||
|
||||
Please notice that all of these components or utils are used in reForis and
|
||||
plugins. If you want to study them by example, I recommend you to full-text
|
||||
search those repositories.
|
||||
|
||||
# Installation
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Please make sure that [Node.js](https://nodejs.org/en/) is installed on your
|
||||
system.
|
||||
|
||||
The current Long Term Support (LTS) release is an ideal starting point, see
|
||||
[here](https://github.com/nodejs/Release#release-schedule).
|
||||
|
||||
## Installation
|
||||
|
||||
To install the latest release:
|
||||
|
||||
```plain
|
||||
npm install foris
|
||||
```
|
||||
|
||||
To install a specific version:
|
||||
|
||||
```plain
|
||||
npm install foris@version
|
||||
```
|
||||
|
||||
<a target="_blank" href="https://www.npmjs.com/package/foris">Check
|
||||
on<img width="100px" src="./docs/forisjs-npm.svg"></a>
|
@ -19,7 +19,6 @@ module.exports = {
|
||||
collectCoverageFrom: ["src/**/*.{js,jsx}"],
|
||||
coverageDirectory: "coverage",
|
||||
testPathIgnorePatterns: ["/node_modules/", "/__fixtures__/", "/dist/"],
|
||||
testEnvironment: "jsdom",
|
||||
verbose: false,
|
||||
setupFilesAfterEnv: [
|
||||
"@testing-library/react/cleanup-after-each",
|
||||
|
44349
package-lock.json
generated
44349
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
59
package.json
59
package.json
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "foris",
|
||||
"version": "6.0.0",
|
||||
"description": "Foris JS library is a set of components and utils for reForis application and plugins.",
|
||||
"version": "5.1.11",
|
||||
"description": "Set of components and utils for Foris and its plugins.",
|
||||
"author": "CZ.NIC, z.s.p.o.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -14,48 +14,49 @@
|
||||
"license": "GPL-3.0",
|
||||
"main": "./src/index.js",
|
||||
"dependencies": {
|
||||
"axios": "^1.7.2",
|
||||
"immutability-helper": "^3.1.1",
|
||||
"moment": "^2.30.1",
|
||||
"qrcode.react": "^3.1.0",
|
||||
"react-datetime": "^3.2.0",
|
||||
"react-uid": "^2.3.3"
|
||||
"axios": "^0.21.1",
|
||||
"immutability-helper": "3.0.1",
|
||||
"moment": "^2.24.0",
|
||||
"qrcode.react": "^0.9.3",
|
||||
"react-datetime": "^3.0.4",
|
||||
"react-uid": "^2.2.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bootstrap": "^5.3.3",
|
||||
"prop-types": "15.8.1",
|
||||
"bootstrap": "4.4.1",
|
||||
"prop-types": "15.7.2",
|
||||
"react": "16.9.0",
|
||||
"react-dom": "16.9.0",
|
||||
"react-router-dom": "^5.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.24.7",
|
||||
"@babel/core": "^7.24.7",
|
||||
"@babel/plugin-transform-runtime": "^7.24.7",
|
||||
"@babel/preset-env": "^7.24.7",
|
||||
"@babel/preset-react": "^7.24.7",
|
||||
"@fortawesome/fontawesome-free": "^6.5.2",
|
||||
"@babel/cli": "^7.12.10",
|
||||
"@babel/core": "^7.9.0",
|
||||
"@babel/plugin-transform-runtime": "^7.9.0",
|
||||
"@babel/preset-env": "^7.9.0",
|
||||
"@babel/preset-react": "^7.9.4",
|
||||
"@fortawesome/fontawesome-free": "^5.13.0",
|
||||
"@testing-library/react": "^8.0.9",
|
||||
"babel-loader": "^8.1.0",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"bootstrap": "^5.3.3",
|
||||
"css-loader": "^5.2.4",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-reforis": "^2.1.1",
|
||||
"bootstrap": "^4.5.0",
|
||||
"css-loader": "^3.5.3",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-config-prettier": "^6.11.0",
|
||||
"eslint-config-reforis": "^1.0.0",
|
||||
"eslint-plugin-prettier": "^3.1.4",
|
||||
"file-loader": "^6.0.0",
|
||||
"jest": "^29.7.0",
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
"jest-mock-axios": "^4.7.3",
|
||||
"moment-timezone": "^0.5.45",
|
||||
"prettier": "^3.3.1",
|
||||
"prop-types": "15.8.1",
|
||||
"jest": "^25.2.0",
|
||||
"jest-mock-axios": "^3.2.0",
|
||||
"moment-timezone": "^0.5.28",
|
||||
"prettier": "2.0.5",
|
||||
"prop-types": "15.7.2",
|
||||
"react": "16.9.0",
|
||||
"react-dom": "16.9.0",
|
||||
"react-router-dom": "^5.1.2",
|
||||
"react-styleguidist": "^12.0.1",
|
||||
"snapshot-diff": "^0.10.0",
|
||||
"react-styleguidist": "^11.1.5",
|
||||
"snapshot-diff": "^0.7.0",
|
||||
"style-loader": "^1.2.1",
|
||||
"webpack": "^5.91.0"
|
||||
"webpack": "^5.15.0"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint src",
|
||||
|
@ -1 +0,0 @@
|
||||
module.exports = require("eslint-config-reforis/prettier.config");
|
@ -6,7 +6,8 @@ then
|
||||
exit 1
|
||||
else
|
||||
cd dist
|
||||
echo "//registry.npmjs.org/:_authToken=$(echo "$NPM_TOKEN")" > .npmrc
|
||||
# Need to replace "_" with "-" as GitLab CI won't accept secret vars with "-"
|
||||
echo "//registry.npmjs.org/:_authToken=$(echo "$NPM_TOKEN" | tr _ -)" > .npmrc
|
||||
echo "unsafe-perm = true" >> ~/.npmrc
|
||||
if test "$1" = "beta"
|
||||
then
|
||||
|
@ -1,16 +1,15 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React, { useState, useContext, useCallback, useMemo } from "react";
|
||||
|
||||
import React, { useState, useContext, useCallback } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import Alert, { ALERT_TYPES } from "../../bootstrap/Alert";
|
||||
import Portal from "../../utils/Portal";
|
||||
import { Alert, ALERT_TYPES } from "../bootstrap/Alert";
|
||||
import { Portal } from "../utils/Portal";
|
||||
|
||||
AlertContextProvider.propTypes = {
|
||||
children: PropTypes.oneOfType([
|
||||
@ -31,10 +30,6 @@ function AlertContextProvider({ children }) {
|
||||
);
|
||||
|
||||
const dismissAlert = useCallback(() => setAlert(null), [setAlert]);
|
||||
const contextValue = useMemo(
|
||||
() => [setAlertWrapper, dismissAlert],
|
||||
[setAlertWrapper, dismissAlert]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -45,7 +40,7 @@ function AlertContextProvider({ children }) {
|
||||
</Alert>
|
||||
</Portal>
|
||||
)}
|
||||
<AlertContext.Provider value={contextValue}>
|
||||
<AlertContext.Provider value={[setAlertWrapper, dismissAlert]}>
|
||||
{children}
|
||||
</AlertContext.Provider>
|
||||
</>
|
@ -48,7 +48,7 @@ describe("AlertContext", () => {
|
||||
// Alert is present
|
||||
expect(getByText(componentContainer, "Alert content")).toBeDefined();
|
||||
|
||||
fireEvent.click(componentContainer.querySelector(".btn-close"));
|
||||
fireEvent.click(componentContainer.querySelector(".close"));
|
||||
// Alert is gone
|
||||
expect(queryByText(componentContainer, "Alert content")).toBeNull();
|
||||
});
|
@ -6,13 +6,14 @@ exports[`AlertContext should render alert 1`] = `
|
||||
id="alert-container"
|
||||
>
|
||||
<div
|
||||
class="alert alert-danger alert-dismissible"
|
||||
class="alert alert-dismissible alert-danger"
|
||||
>
|
||||
<button
|
||||
aria-label="Close"
|
||||
class="btn-close"
|
||||
class="close"
|
||||
type="button"
|
||||
/>
|
||||
>
|
||||
×
|
||||
</button>
|
||||
Alert content
|
||||
</div>
|
||||
</div>
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2021 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
* 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.
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
import { useCallback, useEffect, useReducer, useState } from "react";
|
||||
|
||||
import { ForisURLs } from "../utils/forisUrls";
|
||||
import {
|
||||
API_ACTIONS,
|
||||
API_METHODS,
|
||||
@ -83,8 +84,8 @@ function APIReducer(state, action) {
|
||||
data: action.payload,
|
||||
};
|
||||
case API_ACTIONS.FAILURE:
|
||||
if (action.status === 401) {
|
||||
window.location.reload();
|
||||
if (action.status === 403) {
|
||||
window.location.assign(ForisURLs.login);
|
||||
}
|
||||
|
||||
// Not an API error - should be rethrown.
|
||||
@ -111,8 +112,9 @@ const useAPIPatch = createAPIHook("PATCH");
|
||||
const useAPIPut = createAPIHook("PUT");
|
||||
const useAPIDelete = createAPIHook("DELETE");
|
||||
|
||||
/* eslint-disable default-param-last */
|
||||
function useAPIPolling(endpoint, delay = 1000, until) {
|
||||
export { useAPIGet, useAPIPost, useAPIPatch, useAPIPut, useAPIDelete };
|
||||
|
||||
export function useAPIPolling(endpoint, delay = 1000, until) {
|
||||
// delay ms
|
||||
const [state, setState] = useState({ state: API_STATE.INIT });
|
||||
const [getResponse, get] = useAPIGet(endpoint);
|
||||
@ -132,12 +134,3 @@ function useAPIPolling(endpoint, delay = 1000, until) {
|
||||
|
||||
return [state];
|
||||
}
|
||||
|
||||
export {
|
||||
useAPIGet,
|
||||
useAPIPost,
|
||||
useAPIPatch,
|
||||
useAPIPut,
|
||||
useAPIDelete,
|
||||
useAPIPolling,
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2021 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
* 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.
|
||||
@ -11,7 +11,6 @@ export const HEADERS = {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
"X-CSRFToken": getCookie("_csrf_token"),
|
||||
"X-Requested-With": "json",
|
||||
};
|
||||
|
||||
export const TIMEOUT = 30500;
|
||||
@ -57,7 +56,7 @@ function getCookie(name) {
|
||||
|
||||
export function getErrorPayload(error) {
|
||||
if (error.response) {
|
||||
if (error.response.status === 401) {
|
||||
if (error.response.status === 403) {
|
||||
return _("The session is expired. Please log in again.");
|
||||
}
|
||||
return getJSONErrorMessage(error);
|
||||
|
@ -1,12 +1,11 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
export const ALERT_TYPES = Object.freeze({
|
||||
@ -36,24 +35,21 @@ Alert.defaultProps = {
|
||||
type: ALERT_TYPES.DANGER,
|
||||
};
|
||||
|
||||
function Alert({ type, onDismiss, children }) {
|
||||
export function Alert({ type, onDismiss, children }) {
|
||||
return (
|
||||
<div
|
||||
className={`alert alert-${type} ${
|
||||
className={`alert ${
|
||||
onDismiss ? "alert-dismissible" : ""
|
||||
}`.trim()}
|
||||
} alert-${type}`}
|
||||
>
|
||||
{onDismiss && (
|
||||
<button
|
||||
type="button"
|
||||
className="btn-close"
|
||||
onClick={onDismiss}
|
||||
aria-label={_("Close")}
|
||||
/>
|
||||
{onDismiss ? (
|
||||
<button type="button" className="close" onClick={onDismiss}>
|
||||
×
|
||||
</button>
|
||||
) : (
|
||||
false
|
||||
)}
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Alert;
|
||||
|
@ -1,12 +1,11 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
Button.propTypes = {
|
||||
@ -25,28 +24,31 @@ Button.propTypes = {
|
||||
]).isRequired,
|
||||
};
|
||||
|
||||
function Button({ className, loading, forisFormSize, children, ...props }) {
|
||||
let buttonClass = className ? `btn ${className}` : "btn btn-primary";
|
||||
export function Button({
|
||||
className,
|
||||
loading,
|
||||
forisFormSize,
|
||||
children,
|
||||
...props
|
||||
}) {
|
||||
let buttonClass = className ? `btn ${className}` : "btn btn-primary ";
|
||||
if (forisFormSize) {
|
||||
buttonClass = `${buttonClass} col-12 col-md-3 col-lg-2`;
|
||||
buttonClass = `${buttonClass} col-sm-12 col-md-3 col-lg-2`;
|
||||
}
|
||||
|
||||
const span = loading ? (
|
||||
<span
|
||||
className="spinner-border spinner-border-sm"
|
||||
role="status"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className={`${buttonClass} d-inline-flex justify-content-center align-items-center`}
|
||||
{...props}
|
||||
>
|
||||
{loading && (
|
||||
<span
|
||||
className="spinner-border spinner-border-sm me-1"
|
||||
role="status"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
)}
|
||||
<span>{children}</span>
|
||||
<button type="button" className={buttonClass} {...props}>
|
||||
{span}
|
||||
{span ? " " : null}
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
export default Button;
|
||||
|
@ -1,12 +1,11 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
import { useUID } from "react-uid";
|
||||
|
||||
@ -23,28 +22,27 @@ CheckBox.defaultProps = {
|
||||
disabled: false,
|
||||
};
|
||||
|
||||
function CheckBox({ label, helpText, disabled, ...props }) {
|
||||
export function CheckBox({ label, helpText, disabled, ...props }) {
|
||||
const uid = useUID();
|
||||
|
||||
return (
|
||||
<div className="mb-3 form-check">
|
||||
<input
|
||||
className="form-check-input"
|
||||
type="checkbox"
|
||||
id={uid}
|
||||
disabled={disabled}
|
||||
{...props}
|
||||
/>
|
||||
<label className="form-check-label" htmlFor={uid}>
|
||||
{label}
|
||||
</label>
|
||||
{helpText && (
|
||||
<div className="form-text">
|
||||
<small>{helpText}</small>
|
||||
</div>
|
||||
)}
|
||||
<div className="form-group">
|
||||
<div className="custom-control custom-checkbox ">
|
||||
<input
|
||||
className="custom-control-input"
|
||||
type="checkbox"
|
||||
id={uid}
|
||||
disabled={disabled}
|
||||
{...props}
|
||||
/>
|
||||
<label className="custom-control-label" htmlFor={uid}>
|
||||
{label}
|
||||
{helpText && (
|
||||
<small className="form-text text-muted">
|
||||
{helpText}
|
||||
</small>
|
||||
)}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default CheckBox;
|
||||
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React, { useState, useRef } from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import Input from "./Input";
|
||||
|
||||
CopyInput.propTypes = {
|
||||
/** Field label. */
|
||||
label: PropTypes.string.isRequired,
|
||||
/** Field value. */
|
||||
value: PropTypes.string,
|
||||
/** Help text message. */
|
||||
helpText: PropTypes.string,
|
||||
/** Disable input field */
|
||||
disabled: PropTypes.bool,
|
||||
/** Readonly input field */
|
||||
readOnly: PropTypes.bool,
|
||||
};
|
||||
|
||||
function CopyInput({ value, ...props }) {
|
||||
const inputTextRef = useRef();
|
||||
const [isCopied, setIsCopied] = useState(false);
|
||||
|
||||
const handleCopyClick = async () => {
|
||||
// Clipboard API works only in a secure (HTTPS) context.
|
||||
if (navigator.clipboard) {
|
||||
await navigator.clipboard.writeText(value);
|
||||
} else {
|
||||
// Fallback to the "classic" copy to clipboard implementation.
|
||||
inputTextRef.current.focus();
|
||||
inputTextRef.current.select();
|
||||
document.execCommand("copy");
|
||||
inputTextRef.current.blur();
|
||||
}
|
||||
|
||||
setIsCopied(true);
|
||||
setTimeout(() => {
|
||||
setIsCopied(false);
|
||||
}, 1500);
|
||||
};
|
||||
|
||||
return (
|
||||
<Input type="text" value={value} ref={inputTextRef} {...props}>
|
||||
<div className="input-group-append">
|
||||
<button
|
||||
className="btn btn-outline-secondary"
|
||||
type="button"
|
||||
onClick={handleCopyClick}
|
||||
>
|
||||
<span>{isCopied ? _("Copied!") : _("Copy")}</span>
|
||||
</button>
|
||||
</div>
|
||||
</Input>
|
||||
);
|
||||
}
|
||||
|
||||
export default CopyInput;
|
@ -1,17 +0,0 @@
|
||||
CopyInput Bootstrap component contains input with a label, predefined sizes, and
|
||||
structure for use in ForisForm and the "Copy" button (copy to clipboard). It can
|
||||
be used with `readOnly` and `disabled` parameters, please see an example.
|
||||
|
||||
All additional `props` are passed to the `<input type="text">` HTML component.
|
||||
|
||||
```js
|
||||
import React, { useState } from "react";
|
||||
const [value, setValue] = useState("Text to appear in clipboard.");
|
||||
|
||||
<CopyInput
|
||||
label="Copy me"
|
||||
value={value}
|
||||
helpText="Read the small text!"
|
||||
readOnly
|
||||
/>;
|
||||
```
|
@ -1,19 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
import moment from "moment/moment";
|
||||
import PropTypes from "prop-types";
|
||||
import Datetime from "react-datetime";
|
||||
import moment from "moment/moment";
|
||||
import "react-datetime/css/react-datetime.css";
|
||||
import "./DataTimeInput.css";
|
||||
|
||||
import Input from "./Input";
|
||||
import { Input } from "./Input";
|
||||
|
||||
DataTimeInput.propTypes = {
|
||||
/** Field label. */
|
||||
@ -38,7 +37,7 @@ DataTimeInput.propTypes = {
|
||||
const DEFAULT_DATE_FORMAT = "YYYY-MM-DD";
|
||||
const DEFAULT_TIME_FORMAT = "HH:mm:ss";
|
||||
|
||||
function DataTimeInput({
|
||||
export function DataTimeInput({
|
||||
value,
|
||||
onChange,
|
||||
isValidDate,
|
||||
@ -47,13 +46,13 @@ function DataTimeInput({
|
||||
children,
|
||||
...props
|
||||
}) {
|
||||
const renderInput = (datetimeProps) => {
|
||||
function renderInput(datetimeProps) {
|
||||
return (
|
||||
<Input {...props} {...datetimeProps}>
|
||||
{children}
|
||||
</Input>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<Datetime
|
||||
@ -71,5 +70,3 @@ function DataTimeInput({
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default DataTimeInput;
|
||||
|
@ -1,12 +1,11 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
DownloadButton.propTypes = {
|
||||
@ -22,17 +21,10 @@ DownloadButton.defaultProps = {
|
||||
className: "btn-primary",
|
||||
};
|
||||
|
||||
function DownloadButton({ href, className, children, ...props }) {
|
||||
export function DownloadButton({ href, className, children }) {
|
||||
return (
|
||||
<a
|
||||
href={href}
|
||||
className={`btn ${className}`.trim()}
|
||||
{...props}
|
||||
download
|
||||
>
|
||||
<a href={href} className={`btn ${className}`.trim()} download>
|
||||
{children}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
export default DownloadButton;
|
||||
|
@ -6,14 +6,11 @@
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import Input from "./Input";
|
||||
import { Input } from "./Input";
|
||||
|
||||
function EmailInput({ ...props }) {
|
||||
return <Input type="email" {...props} />;
|
||||
}
|
||||
export const EmailInput = ({ ...props }) => <Input type="email" {...props} />;
|
||||
|
||||
EmailInput.propTypes = {
|
||||
/** Field label. */
|
||||
@ -25,5 +22,3 @@ EmailInput.propTypes = {
|
||||
/** Email value. */
|
||||
value: PropTypes.string,
|
||||
};
|
||||
|
||||
export default EmailInput;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* 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.
|
||||
@ -8,8 +8,7 @@
|
||||
import React from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import Input from "./Input";
|
||||
import { Input } from "./Input";
|
||||
|
||||
FileInput.propTypes = {
|
||||
/** Field label. */
|
||||
@ -24,7 +23,7 @@ FileInput.propTypes = {
|
||||
multiple: PropTypes.bool,
|
||||
};
|
||||
|
||||
function FileInput({ ...props }) {
|
||||
export function FileInput({ ...props }) {
|
||||
return (
|
||||
<Input
|
||||
type="file"
|
||||
@ -35,5 +34,3 @@ function FileInput({ ...props }) {
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default FileInput;
|
||||
|
@ -1,67 +1,13 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2022 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2019-2021 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React, { forwardRef } from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
import React, { useState } from "react";
|
||||
import { useUID } from "react-uid";
|
||||
|
||||
/** Base bootstrap input component. */
|
||||
const Input = forwardRef(
|
||||
(
|
||||
{
|
||||
type,
|
||||
label,
|
||||
helpText,
|
||||
error,
|
||||
className,
|
||||
children,
|
||||
labelClassName,
|
||||
groupClassName,
|
||||
...props
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const uid = useUID();
|
||||
|
||||
const inputClassName = `${className || ""} ${
|
||||
error ? "is-invalid" : ""
|
||||
}`.trim();
|
||||
|
||||
return (
|
||||
<div className="mb-3">
|
||||
<label
|
||||
className={`form-label ${labelClassName || ""}`.trim()}
|
||||
htmlFor={uid}
|
||||
>
|
||||
{label}
|
||||
</label>
|
||||
<div className={`input-group ${groupClassName || ""}`.trim()}>
|
||||
<input
|
||||
className={`form-control ${inputClassName}`.trim()}
|
||||
type={type}
|
||||
id={uid}
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
{children}
|
||||
</div>
|
||||
{error && <div className="invalid-feedback">{error}</div>}
|
||||
{helpText && (
|
||||
<div className="form-text">
|
||||
<small>{helpText}</small>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
Input.displayName = "Input";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
Input.propTypes = {
|
||||
type: PropTypes.string.isRequired,
|
||||
@ -77,4 +23,45 @@ Input.propTypes = {
|
||||
groupClassName: PropTypes.string,
|
||||
};
|
||||
|
||||
export default Input;
|
||||
/** Base bootstrap input component. */
|
||||
export function Input({
|
||||
type,
|
||||
label,
|
||||
helpText,
|
||||
error,
|
||||
className,
|
||||
children,
|
||||
labelClassName,
|
||||
groupClassName,
|
||||
...props
|
||||
}) {
|
||||
const uid = useUID();
|
||||
const [initialErrorFeedbackState, setErrorFeedbackState] = useState(false);
|
||||
const errorFeedbackIsVisible = !!(initialErrorFeedbackState && error);
|
||||
const inputClassName = `form-control ${className || ""} ${
|
||||
errorFeedbackIsVisible ? "is-invalid" : ""
|
||||
}`.trim();
|
||||
return (
|
||||
<div className="form-group">
|
||||
<label className={labelClassName} htmlFor={uid}>
|
||||
{label}
|
||||
</label>
|
||||
<div className={`input-group ${groupClassName || ""}`.trim()}>
|
||||
<input
|
||||
className={inputClassName}
|
||||
type={type}
|
||||
id={uid}
|
||||
onFocus={() => setErrorFeedbackState(true)}
|
||||
{...props}
|
||||
/>
|
||||
{children}
|
||||
</div>
|
||||
{errorFeedbackIsVisible && (
|
||||
<div className="invalid-feedback">{error}</div>
|
||||
)}
|
||||
{helpText && (
|
||||
<small className="form-text text-muted">{helpText}</small>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,16 +1,15 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React, { useRef, useEffect } from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { Portal } from "../utils/Portal";
|
||||
import { useClickOutside } from "../utils/hooks";
|
||||
import Portal from "../utils/Portal";
|
||||
import "./Modal.css";
|
||||
|
||||
Modal.propTypes = {
|
||||
@ -93,10 +92,11 @@ export function ModalHeader({ setShown, title }) {
|
||||
<h5 className="modal-title">{title}</h5>
|
||||
<button
|
||||
type="button"
|
||||
className="btn-close"
|
||||
className="close"
|
||||
onClick={() => setShown(false)}
|
||||
aria-label={_("Close")}
|
||||
/>
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,16 +1,15 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import Input from "./Input";
|
||||
import { useConditionalTimeout } from "../utils/hooks";
|
||||
import { Input } from "./Input";
|
||||
import "./NumberInput.css";
|
||||
|
||||
NumberInput.propTypes = {
|
||||
@ -24,7 +23,7 @@ NumberInput.propTypes = {
|
||||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
/** Function called when value changes. */
|
||||
onChange: PropTypes.func.isRequired,
|
||||
/** Additional description displayed to the right of input value. */
|
||||
/** Additional description dispaled to the right of input value. */
|
||||
inlineText: PropTypes.string,
|
||||
};
|
||||
|
||||
@ -32,7 +31,7 @@ NumberInput.defaultProps = {
|
||||
value: 0,
|
||||
};
|
||||
|
||||
function NumberInput({ onChange, inlineText, value, ...props }) {
|
||||
export function NumberInput({ onChange, inlineText, value, ...props }) {
|
||||
function updateValue(initialValue, difference) {
|
||||
onChange({ target: { value: initialValue + difference } });
|
||||
}
|
||||
@ -50,29 +49,27 @@ function NumberInput({ onChange, inlineText, value, ...props }) {
|
||||
|
||||
return (
|
||||
<Input type="number" onChange={onChange} value={value} {...props}>
|
||||
{inlineText && (
|
||||
<span className="input-group-text">{inlineText}</span>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-outline-secondary"
|
||||
onMouseDown={() => enableIncrease(true)}
|
||||
onMouseUp={() => enableIncrease(false)}
|
||||
aria-label="Increase"
|
||||
>
|
||||
<i className="fas fa-plus" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-outline-secondary"
|
||||
onMouseDown={() => enableDecrease(true)}
|
||||
onMouseUp={() => enableDecrease(false)}
|
||||
aria-label="Decrease"
|
||||
>
|
||||
<i className="fas fa-minus" />
|
||||
</button>
|
||||
<div className="input-group-append">
|
||||
{inlineText && <p className="input-group-text">{inlineText}</p>}
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-outline-secondary"
|
||||
onMouseDown={() => enableIncrease(true)}
|
||||
onMouseUp={() => enableIncrease(false)}
|
||||
aria-label="Increase"
|
||||
>
|
||||
<i className="fas fa-plus" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-outline-secondary"
|
||||
onMouseDown={() => enableDecrease(true)}
|
||||
onMouseUp={() => enableDecrease(false)}
|
||||
aria-label="Decrease"
|
||||
>
|
||||
<i className="fas fa-minus" />
|
||||
</button>
|
||||
</div>
|
||||
</Input>
|
||||
);
|
||||
}
|
||||
|
||||
export default NumberInput;
|
||||
|
@ -1,15 +1,14 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React, { useState } from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import Input from "./Input";
|
||||
import { Input } from "./Input";
|
||||
|
||||
PasswordInput.propTypes = {
|
||||
/** Field label. */
|
||||
@ -22,35 +21,34 @@ PasswordInput.propTypes = {
|
||||
helpText: PropTypes.string,
|
||||
/** Use show/hide password button. */
|
||||
withEye: PropTypes.bool,
|
||||
/** Use new-password in autocomplete attribute. */
|
||||
newPass: PropTypes.bool,
|
||||
};
|
||||
|
||||
function PasswordInput({ withEye, newPass, ...props }) {
|
||||
export function PasswordInput({ withEye, ...props }) {
|
||||
const [isHidden, setHidden] = useState(true);
|
||||
|
||||
return (
|
||||
<Input
|
||||
type={withEye && !isHidden ? "text" : "password"}
|
||||
autoComplete={newPass ? "new-password" : "current-password"}
|
||||
autoComplete={isHidden ? "new-password" : null}
|
||||
{...props}
|
||||
>
|
||||
{withEye && (
|
||||
<button
|
||||
type="button"
|
||||
className="input-group-text"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setHidden((shouldBeHidden) => !shouldBeHidden);
|
||||
}}
|
||||
>
|
||||
<i
|
||||
className={`fa ${isHidden ? "fa-eye" : "fa-eye-slash"}`}
|
||||
/>
|
||||
</button>
|
||||
)}
|
||||
{withEye ? (
|
||||
<div className="input-group-append">
|
||||
<button
|
||||
type="button"
|
||||
className="input-group-text"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setHidden((shouldBeHidden) => !shouldBeHidden);
|
||||
}}
|
||||
>
|
||||
<i
|
||||
className={`fa ${
|
||||
isHidden ? "fa-eye" : "fa-eye-slash"
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
) : null}
|
||||
</Input>
|
||||
);
|
||||
}
|
||||
|
||||
export default PasswordInput;
|
||||
|
@ -1,12 +1,11 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
import { useUID } from "react-uid";
|
||||
|
||||
@ -18,7 +17,7 @@ RadioSet.propTypes = {
|
||||
/** Choices . */
|
||||
choices: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
/** Choice label . */
|
||||
/** Choice lable . */
|
||||
label: PropTypes.oneOfType([
|
||||
PropTypes.string,
|
||||
PropTypes.element,
|
||||
@ -37,7 +36,15 @@ RadioSet.propTypes = {
|
||||
inline: PropTypes.bool,
|
||||
};
|
||||
|
||||
function RadioSet({ name, label, choices, value, helpText, inline, ...props }) {
|
||||
export function RadioSet({
|
||||
name,
|
||||
label,
|
||||
choices,
|
||||
value,
|
||||
helpText,
|
||||
inline,
|
||||
...props
|
||||
}) {
|
||||
const uid = useUID();
|
||||
const radios = choices.map((choice, key) => {
|
||||
const id = `${name}-${key}`;
|
||||
@ -57,7 +64,7 @@ function RadioSet({ name, label, choices, value, helpText, inline, ...props }) {
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="mb-3">
|
||||
<div className="form-group">
|
||||
{label && (
|
||||
<label htmlFor={uid} className="d-block">
|
||||
{label}
|
||||
@ -65,9 +72,7 @@ function RadioSet({ name, label, choices, value, helpText, inline, ...props }) {
|
||||
)}
|
||||
{radios}
|
||||
{helpText && (
|
||||
<div className="form-text">
|
||||
<small>{helpText}</small>
|
||||
</div>
|
||||
<small className="form-text text-muted">{helpText}</small>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
@ -87,25 +92,27 @@ Radio.propTypes = {
|
||||
|
||||
export function Radio({ label, id, helpText, inline, ...props }) {
|
||||
return (
|
||||
<div
|
||||
className={`mb-2 ${inline ? "form-check form-check-inline" : ""}`.trim()}
|
||||
>
|
||||
<input
|
||||
id={id}
|
||||
className="form-check-input me-2"
|
||||
type="radio"
|
||||
{...props}
|
||||
/>
|
||||
<label className="form-check-label" htmlFor={id}>
|
||||
{label}
|
||||
<>
|
||||
<div
|
||||
className={`custom-control custom-radio ${
|
||||
inline ? "custom-control-inline" : ""
|
||||
}`.trim()}
|
||||
>
|
||||
<input
|
||||
id={id}
|
||||
className="custom-control-input"
|
||||
type="radio"
|
||||
{...props}
|
||||
/>
|
||||
<label className="custom-control-label" htmlFor={id}>
|
||||
{label}
|
||||
</label>
|
||||
{helpText && (
|
||||
<div className="form-text">
|
||||
<small>{helpText}</small>
|
||||
</div>
|
||||
<small className="form-text text-muted mt-0 mb-3">
|
||||
{helpText}
|
||||
</small>
|
||||
)}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default RadioSet;
|
||||
|
@ -1,12 +1,11 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
import { useUID } from "react-uid";
|
||||
|
||||
@ -21,30 +20,25 @@ Select.propTypes = {
|
||||
helpText: PropTypes.string,
|
||||
};
|
||||
|
||||
function Select({ label, choices, helpText, ...props }) {
|
||||
export function Select({ label, choices, helpText, ...props }) {
|
||||
const uid = useUID();
|
||||
|
||||
const options = Object.keys(choices).map((choice) => (
|
||||
<option key={choice} value={choice}>
|
||||
{choices[choice]}
|
||||
</option>
|
||||
));
|
||||
|
||||
const options = Object.keys(choices)
|
||||
.sort((a, b) => a - b || a.toString().localeCompare(b.toString()))
|
||||
.map((key) => (
|
||||
<option key={key} value={key}>
|
||||
{choices[key]}
|
||||
</option>
|
||||
));
|
||||
return (
|
||||
<div className="mb-3">
|
||||
<label className="form-label" htmlFor={uid}>
|
||||
{label}
|
||||
</label>
|
||||
<select className="form-select" id={uid} {...props}>
|
||||
<div className="form-group">
|
||||
<label htmlFor={uid}>{label}</label>
|
||||
<select className="custom-select" id={uid} {...props}>
|
||||
{options}
|
||||
</select>
|
||||
{helpText && (
|
||||
<div className="form-text">
|
||||
<small>{helpText}</small>
|
||||
</div>
|
||||
)}
|
||||
{helpText ? (
|
||||
<small className="form-text text-muted">{helpText}</small>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Select;
|
||||
|
@ -1,11 +1,3 @@
|
||||
.spinner-fs-wrapper {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 1101; /* increase z-index by 1 to ensure it's on top of spinner-fs-background */
|
||||
}
|
||||
|
||||
.spinner-wrapper .spinner-border {
|
||||
width: 4rem;
|
||||
height: 4rem;
|
||||
@ -15,8 +7,10 @@
|
||||
.spinner-fs-background {
|
||||
background-color: rgba(2, 2, 2, 0.5);
|
||||
color: rgb(230, 230, 230);
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -37,7 +31,3 @@
|
||||
.spinner-fs-wrapper .spinner-text {
|
||||
margin: 1rem;
|
||||
}
|
||||
|
||||
.spinner-border-sm {
|
||||
min-width: 16px;
|
||||
}
|
||||
|
@ -6,7 +6,6 @@
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import "./Spinner.css";
|
||||
@ -17,7 +16,7 @@ Spinner.propTypes = {
|
||||
PropTypes.arrayOf(PropTypes.node),
|
||||
PropTypes.node,
|
||||
]),
|
||||
/** Render component with full-screen mode (using appropriate `.css` styles) */
|
||||
/** Render component with full-screen mode (using apropriate `.css` styles) */
|
||||
fullScreen: PropTypes.bool.isRequired,
|
||||
className: PropTypes.string,
|
||||
};
|
||||
|
@ -1,12 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (c) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
import { useUID } from "react-uid";
|
||||
|
||||
@ -21,32 +20,30 @@ Switch.propTypes = {
|
||||
switchHeading: PropTypes.bool,
|
||||
};
|
||||
|
||||
function Switch({ label, helpText, switchHeading, ...props }) {
|
||||
export function Switch({ label, helpText, switchHeading, ...props }) {
|
||||
const uid = useUID();
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`form-check form-switch mb-3 ${
|
||||
switchHeading ? "d-flex align-items-center" : null
|
||||
}`.trim()}
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
className={`form-check-input ${switchHeading ? "me-2" : ""}`.trim()}
|
||||
role="switch"
|
||||
id={uid}
|
||||
{...props}
|
||||
/>
|
||||
<label className="form-check-label" htmlFor={uid}>
|
||||
{label}
|
||||
</label>
|
||||
{helpText && (
|
||||
<div className="form-text">
|
||||
<small>{helpText}</small>
|
||||
</div>
|
||||
)}
|
||||
<div className={`form-group ${switchHeading ? "switch" : ""}`.trim()}>
|
||||
<div
|
||||
className={`custom-control custom-switch ${
|
||||
!helpText ? "custom-control-inline" : ""
|
||||
} ${switchHeading ? "switch-heading" : ""}`.trim()}
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
className="custom-control-input"
|
||||
id={uid}
|
||||
{...props}
|
||||
/>
|
||||
<label className="custom-control-label" htmlFor={uid}>
|
||||
{label}
|
||||
</label>
|
||||
{helpText && (
|
||||
<small className="form-text text-muted mt-0 mb-3">
|
||||
{helpText}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Switch;
|
||||
|
@ -1,5 +0,0 @@
|
||||
Switch example:
|
||||
|
||||
```js
|
||||
<Switch label="Enable Switch" helpText="Toggle that switch!" />
|
||||
```
|
@ -1,19 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import Input from "./Input";
|
||||
import { Input } from "./Input";
|
||||
|
||||
function TextInput({ ...props }) {
|
||||
return <Input type="text" {...props} />;
|
||||
}
|
||||
export const TextInput = ({ ...props }) => <Input type="text" {...props} />;
|
||||
|
||||
TextInput.propTypes = {
|
||||
/** Field label. */
|
||||
@ -23,5 +20,3 @@ TextInput.propTypes = {
|
||||
/** Help text message. */
|
||||
helpText: PropTypes.string,
|
||||
};
|
||||
|
||||
export default TextInput;
|
||||
|
@ -9,7 +9,7 @@ import React from "react";
|
||||
|
||||
import { render } from "customTestRender";
|
||||
|
||||
import Button from "../Button";
|
||||
import { Button } from "../Button";
|
||||
|
||||
describe("<Button />", () => {
|
||||
it("Render button correctly", () => {
|
||||
|
@ -9,7 +9,7 @@ import React from "react";
|
||||
|
||||
import { render } from "customTestRender";
|
||||
|
||||
import CheckBox from "../CheckBox";
|
||||
import { CheckBox } from "../CheckBox";
|
||||
|
||||
describe("<Checkbox/>", () => {
|
||||
it("Render checkbox", () => {
|
||||
|
@ -9,7 +9,7 @@ import React from "react";
|
||||
|
||||
import { render } from "customTestRender";
|
||||
|
||||
import DownloadButton from "../DownloadButton";
|
||||
import { DownloadButton } from "../DownloadButton";
|
||||
|
||||
describe("<DownloadButton />", () => {
|
||||
it("should have download attribute", () => {
|
||||
|
@ -9,7 +9,7 @@ import React from "react";
|
||||
|
||||
import { render, fireEvent, getByLabelText, wait } from "customTestRender";
|
||||
|
||||
import NumberInput from "../NumberInput";
|
||||
import { NumberInput } from "../NumberInput";
|
||||
|
||||
describe("<NumberInput/>", () => {
|
||||
const onChangeMock = jest.fn();
|
||||
|
@ -9,7 +9,7 @@ import React from "react";
|
||||
|
||||
import { render } from "customTestRender";
|
||||
|
||||
import PasswordInput from "../PasswordInput";
|
||||
import { PasswordInput } from "../PasswordInput";
|
||||
|
||||
describe("<PasswordInput/>", () => {
|
||||
it("Render password input", () => {
|
||||
|
@ -9,7 +9,7 @@ import React from "react";
|
||||
|
||||
import { render } from "customTestRender";
|
||||
|
||||
import RadioSet from "../RadioSet";
|
||||
import { RadioSet } from "../RadioSet";
|
||||
|
||||
const TEST_CHOICES = [
|
||||
{
|
||||
|
@ -14,7 +14,7 @@ import {
|
||||
render,
|
||||
} from "customTestRender";
|
||||
|
||||
import Select from "../Select";
|
||||
import { Select } from "../Select";
|
||||
|
||||
const TEST_CHOICES = {
|
||||
1: "one",
|
||||
|
@ -9,7 +9,7 @@ import React from "react";
|
||||
|
||||
import { render } from "customTestRender";
|
||||
|
||||
import Switch from "../Switch";
|
||||
import { Switch } from "../Switch";
|
||||
|
||||
describe("<Switch/>", () => {
|
||||
it("Render switch", () => {
|
||||
|
@ -9,7 +9,7 @@ import React from "react";
|
||||
|
||||
import { render } from "customTestRender";
|
||||
|
||||
import TextInput from "../TextInput";
|
||||
import { TextInput } from "../TextInput";
|
||||
|
||||
describe("<TextInput/>", () => {
|
||||
it("Render text input", () => {
|
||||
|
@ -2,38 +2,33 @@
|
||||
|
||||
exports[`<Button /> Render button correctly 1`] = `
|
||||
<button
|
||||
class="btn btn-primary d-inline-flex justify-content-center align-items-center"
|
||||
class="btn btn-primary "
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Test Button
|
||||
</span>
|
||||
Test Button
|
||||
</button>
|
||||
`;
|
||||
|
||||
exports[`<Button /> Render button with custom classes 1`] = `
|
||||
<button
|
||||
class="btn one two three d-inline-flex justify-content-center align-items-center"
|
||||
class="btn one two three"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Test Button
|
||||
</span>
|
||||
Test Button
|
||||
</button>
|
||||
`;
|
||||
|
||||
exports[`<Button /> Render button with spinner 1`] = `
|
||||
<button
|
||||
class="btn btn-primary d-inline-flex justify-content-center align-items-center"
|
||||
class="btn btn-primary "
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="spinner-border spinner-border-sm me-1"
|
||||
class="spinner-border spinner-border-sm"
|
||||
role="status"
|
||||
/>
|
||||
<span>
|
||||
Test Button
|
||||
</span>
|
||||
|
||||
Test Button
|
||||
</button>
|
||||
`;
|
||||
|
@ -2,51 +2,55 @@
|
||||
|
||||
exports[`<Checkbox/> Render checkbox 1`] = `
|
||||
<div
|
||||
class="mb-3 form-check"
|
||||
class="form-group"
|
||||
>
|
||||
<input
|
||||
checked=""
|
||||
class="form-check-input"
|
||||
id="1"
|
||||
type="checkbox"
|
||||
/>
|
||||
<label
|
||||
class="form-check-label"
|
||||
for="1"
|
||||
>
|
||||
Test label
|
||||
</label>
|
||||
<div
|
||||
class="form-text"
|
||||
class="custom-control custom-checkbox "
|
||||
>
|
||||
<small>
|
||||
Some help text
|
||||
</small>
|
||||
<input
|
||||
checked=""
|
||||
class="custom-control-input"
|
||||
id="1"
|
||||
type="checkbox"
|
||||
/>
|
||||
<label
|
||||
class="custom-control-label"
|
||||
for="1"
|
||||
>
|
||||
Test label
|
||||
<small
|
||||
class="form-text text-muted"
|
||||
>
|
||||
Some help text
|
||||
</small>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`<Checkbox/> Render uncheked checkbox 1`] = `
|
||||
<div
|
||||
class="mb-3 form-check"
|
||||
class="form-group"
|
||||
>
|
||||
<input
|
||||
class="form-check-input"
|
||||
id="1"
|
||||
type="checkbox"
|
||||
/>
|
||||
<label
|
||||
class="form-check-label"
|
||||
for="1"
|
||||
>
|
||||
Test label
|
||||
</label>
|
||||
<div
|
||||
class="form-text"
|
||||
class="custom-control custom-checkbox "
|
||||
>
|
||||
<small>
|
||||
Some help text
|
||||
</small>
|
||||
<input
|
||||
class="custom-control-input"
|
||||
id="1"
|
||||
type="checkbox"
|
||||
/>
|
||||
<label
|
||||
class="custom-control-label"
|
||||
for="1"
|
||||
>
|
||||
Test label
|
||||
<small
|
||||
class="form-text text-muted"
|
||||
>
|
||||
Some help text
|
||||
</small>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -2,10 +2,9 @@
|
||||
|
||||
exports[`<NumberInput/> Render number input 1`] = `
|
||||
<div
|
||||
class="mb-3"
|
||||
class="form-group"
|
||||
>
|
||||
<label
|
||||
class="form-label"
|
||||
for="1"
|
||||
>
|
||||
Test label
|
||||
@ -19,31 +18,33 @@ exports[`<NumberInput/> Render number input 1`] = `
|
||||
type="number"
|
||||
value="1"
|
||||
/>
|
||||
<button
|
||||
aria-label="Increase"
|
||||
class="btn btn-outline-secondary"
|
||||
type="button"
|
||||
<div
|
||||
class="input-group-append"
|
||||
>
|
||||
<i
|
||||
class="fas fa-plus"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Decrease"
|
||||
class="btn btn-outline-secondary"
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
class="fas fa-minus"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Increase"
|
||||
class="btn btn-outline-secondary"
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
class="fas fa-plus"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Decrease"
|
||||
class="btn btn-outline-secondary"
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
class="fas fa-minus"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="form-text"
|
||||
<small
|
||||
class="form-text text-muted"
|
||||
>
|
||||
<small>
|
||||
Some help text
|
||||
</small>
|
||||
</div>
|
||||
Some help text
|
||||
</small>
|
||||
</div>
|
||||
`;
|
||||
|
@ -2,10 +2,9 @@
|
||||
|
||||
exports[`<PasswordInput/> Render password input 1`] = `
|
||||
<div
|
||||
class="mb-3"
|
||||
class="form-group"
|
||||
>
|
||||
<label
|
||||
class="form-label"
|
||||
for="1"
|
||||
>
|
||||
Test label
|
||||
@ -14,19 +13,17 @@ exports[`<PasswordInput/> Render password input 1`] = `
|
||||
class="input-group"
|
||||
>
|
||||
<input
|
||||
autocomplete="current-password"
|
||||
autocomplete="new-password"
|
||||
class="form-control"
|
||||
id="1"
|
||||
type="password"
|
||||
value="Some password"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="form-text"
|
||||
<small
|
||||
class="form-text text-muted"
|
||||
>
|
||||
<small>
|
||||
Some help text
|
||||
</small>
|
||||
</div>
|
||||
Some help text
|
||||
</small>
|
||||
</div>
|
||||
`;
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
exports[`<RadioSet/> Render radio set 1`] = `
|
||||
<div
|
||||
class="mb-3"
|
||||
class="form-group"
|
||||
>
|
||||
<label
|
||||
class="d-block"
|
||||
@ -11,63 +11,61 @@ exports[`<RadioSet/> Render radio set 1`] = `
|
||||
Radios set label
|
||||
</label>
|
||||
<div
|
||||
class="mb-2"
|
||||
class="custom-control custom-radio"
|
||||
>
|
||||
<input
|
||||
checked=""
|
||||
class="form-check-input me-2"
|
||||
class="custom-control-input"
|
||||
id="test_name-0"
|
||||
name="test_name"
|
||||
type="radio"
|
||||
value="value"
|
||||
/>
|
||||
<label
|
||||
class="form-check-label"
|
||||
class="custom-control-label"
|
||||
for="test_name-0"
|
||||
>
|
||||
label
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="mb-2"
|
||||
class="custom-control custom-radio"
|
||||
>
|
||||
<input
|
||||
class="form-check-input me-2"
|
||||
class="custom-control-input"
|
||||
id="test_name-1"
|
||||
name="test_name"
|
||||
type="radio"
|
||||
value="another value"
|
||||
/>
|
||||
<label
|
||||
class="form-check-label"
|
||||
class="custom-control-label"
|
||||
for="test_name-1"
|
||||
>
|
||||
another label
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="mb-2"
|
||||
class="custom-control custom-radio"
|
||||
>
|
||||
<input
|
||||
class="form-check-input me-2"
|
||||
class="custom-control-input"
|
||||
id="test_name-2"
|
||||
name="test_name"
|
||||
type="radio"
|
||||
value="another on value"
|
||||
/>
|
||||
<label
|
||||
class="form-check-label"
|
||||
class="custom-control-label"
|
||||
for="test_name-2"
|
||||
>
|
||||
another one label
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="form-text"
|
||||
<small
|
||||
class="form-text text-muted"
|
||||
>
|
||||
<small>
|
||||
Some help text
|
||||
</small>
|
||||
</div>
|
||||
Some help text
|
||||
</small>
|
||||
</div>
|
||||
`;
|
||||
|
@ -3,16 +3,15 @@
|
||||
exports[`<Select/> Test with snapshot. 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="mb-3"
|
||||
class="form-group"
|
||||
>
|
||||
<label
|
||||
class="form-label"
|
||||
for="1"
|
||||
>
|
||||
Test label
|
||||
</label>
|
||||
<select
|
||||
class="form-select"
|
||||
class="custom-select"
|
||||
id="1"
|
||||
>
|
||||
<option
|
||||
@ -31,13 +30,11 @@ exports[`<Select/> Test with snapshot. 1`] = `
|
||||
three
|
||||
</option>
|
||||
</select>
|
||||
<div
|
||||
class="form-text"
|
||||
<small
|
||||
class="form-text text-muted"
|
||||
>
|
||||
<small>
|
||||
Help text
|
||||
</small>
|
||||
</div>
|
||||
Help text
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -2,25 +2,26 @@
|
||||
|
||||
exports[`<Switch/> Render switch 1`] = `
|
||||
<div
|
||||
class="form-check form-switch mb-3 null"
|
||||
class="form-group"
|
||||
>
|
||||
<input
|
||||
checked=""
|
||||
class="form-check-input"
|
||||
id="1"
|
||||
role="switch"
|
||||
type="checkbox"
|
||||
/>
|
||||
<label
|
||||
class="form-check-label"
|
||||
for="1"
|
||||
>
|
||||
Test label
|
||||
</label>
|
||||
<div
|
||||
class="form-text"
|
||||
class="custom-control custom-switch"
|
||||
>
|
||||
<small>
|
||||
<input
|
||||
checked=""
|
||||
class="custom-control-input"
|
||||
id="1"
|
||||
type="checkbox"
|
||||
/>
|
||||
<label
|
||||
class="custom-control-label"
|
||||
for="1"
|
||||
>
|
||||
Test label
|
||||
</label>
|
||||
<small
|
||||
class="form-text text-muted mt-0 mb-3"
|
||||
>
|
||||
Some help text
|
||||
</small>
|
||||
</div>
|
||||
@ -29,24 +30,25 @@ exports[`<Switch/> Render switch 1`] = `
|
||||
|
||||
exports[`<Switch/> Render uncheked switch 1`] = `
|
||||
<div
|
||||
class="form-check form-switch mb-3 null"
|
||||
class="form-group"
|
||||
>
|
||||
<input
|
||||
class="form-check-input"
|
||||
id="1"
|
||||
role="switch"
|
||||
type="checkbox"
|
||||
/>
|
||||
<label
|
||||
class="form-check-label"
|
||||
for="1"
|
||||
>
|
||||
Test label
|
||||
</label>
|
||||
<div
|
||||
class="form-text"
|
||||
class="custom-control custom-switch"
|
||||
>
|
||||
<small>
|
||||
<input
|
||||
class="custom-control-input"
|
||||
id="1"
|
||||
type="checkbox"
|
||||
/>
|
||||
<label
|
||||
class="custom-control-label"
|
||||
for="1"
|
||||
>
|
||||
Test label
|
||||
</label>
|
||||
<small
|
||||
class="form-text text-muted mt-0 mb-3"
|
||||
>
|
||||
Some help text
|
||||
</small>
|
||||
</div>
|
||||
|
@ -2,10 +2,9 @@
|
||||
|
||||
exports[`<TextInput/> Render text input 1`] = `
|
||||
<div
|
||||
class="mb-3"
|
||||
class="form-group"
|
||||
>
|
||||
<label
|
||||
class="form-label"
|
||||
for="1"
|
||||
>
|
||||
Test label
|
||||
@ -20,12 +19,10 @@ exports[`<TextInput/> Render text input 1`] = `
|
||||
value="Some text"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="form-text"
|
||||
<small
|
||||
class="form-text text-muted"
|
||||
>
|
||||
<small>
|
||||
Some help text
|
||||
</small>
|
||||
</div>
|
||||
Some help text
|
||||
</small>
|
||||
</div>
|
||||
`;
|
||||
|
@ -1,12 +1,11 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2019-2021 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.
|
||||
*/
|
||||
|
||||
/** Bootstrap column size for form fields */
|
||||
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 { formFieldsSize, buttonFormFieldsSize };
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export const formFieldsSize = "card p-4 col-sm-12 col-lg-12 p-0 mb-4";
|
||||
export const buttonFormFieldsSize = "col-sm-12 col-lg-12 p-0 mb-3";
|
||||
|
@ -1,22 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React, { useState, useEffect } from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { useAPIPost } from "../api/hooks";
|
||||
import { API_STATE } from "../api/utils";
|
||||
import Button from "../bootstrap/Button";
|
||||
import { Modal, ModalHeader, ModalBody, ModalFooter } from "../bootstrap/Modal";
|
||||
import { useAlert } from "../context/alertContext/AlertContext";
|
||||
import { ForisURLs } from "../utils/forisUrls";
|
||||
|
||||
function RebootButton(props) {
|
||||
import { Button } from "../bootstrap/Button";
|
||||
import { Modal, ModalHeader, ModalBody, ModalFooter } from "../bootstrap/Modal";
|
||||
import { useAlert } from "../alertContext/AlertContext";
|
||||
|
||||
export function RebootButton(props) {
|
||||
const [triggered, setTriggered] = useState(false);
|
||||
const [modalShown, setModalShown] = useState(false);
|
||||
const [triggerRebootStatus, triggerReboot] = useAPIPost(ForisURLs.reboot);
|
||||
@ -28,11 +28,11 @@ function RebootButton(props) {
|
||||
}
|
||||
});
|
||||
|
||||
const rebootHandler = () => {
|
||||
function rebootHandler() {
|
||||
setTriggered(true);
|
||||
triggerReboot();
|
||||
setModalShown(false);
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -76,5 +76,3 @@ function RebootModal({ shown, setShown, onReboot }) {
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
export default RebootButton;
|
||||
|
@ -1,27 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2019-2021 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React, { useEffect, useState } from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { Button } from "../../bootstrap/Button";
|
||||
import { useAlert } from "../../alertContext/AlertContext";
|
||||
import { ALERT_TYPES } from "../../bootstrap/Alert";
|
||||
import { useAPIPost } from "../../api/hooks";
|
||||
import { API_STATE } from "../../api/utils";
|
||||
import { ALERT_TYPES } from "../../bootstrap/Alert";
|
||||
import Button from "../../bootstrap/Button";
|
||||
import { formFieldsSize } from "../../bootstrap/constants";
|
||||
import { useAlert } from "../../context/alertContext/AlertContext";
|
||||
|
||||
ResetWiFiSettings.propTypes = {
|
||||
ws: PropTypes.object.isRequired,
|
||||
endpoint: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
function ResetWiFiSettings({ ws, endpoint }) {
|
||||
export default function ResetWiFiSettings({ ws, endpoint }) {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
@ -45,23 +44,24 @@ function ResetWiFiSettings({ ws, endpoint }) {
|
||||
}
|
||||
}, [postResetResponse, setAlert]);
|
||||
|
||||
const onReset = () => {
|
||||
function onReset() {
|
||||
dismissAlert();
|
||||
setIsLoading(true);
|
||||
postReset();
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={formFieldsSize}>
|
||||
<h2>{_("Reset Wi-Fi Settings")}</h2>
|
||||
<p>
|
||||
{_(
|
||||
"If a number of wireless cards doesn't match, you may try to reset the Wi-Fi settings. Note that this will remove the current Wi-Fi configuration and restore the default values."
|
||||
)}
|
||||
{_(`
|
||||
If a number of wireless cards doesn't match, you may try to reset the Wi-Fi settings. Note that this will remove the
|
||||
current Wi-Fi configuration and restore the default values.
|
||||
`)}
|
||||
</p>
|
||||
<div className="text-end">
|
||||
<div className="text-right">
|
||||
<Button
|
||||
className="btn-primary"
|
||||
className="btn-warning"
|
||||
forisFormSize
|
||||
loading={isLoading}
|
||||
disabled={isLoading}
|
||||
@ -73,5 +73,3 @@ function ResetWiFiSettings({ ws, endpoint }) {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ResetWiFiSettings;
|
||||
|
@ -1,22 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2022 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { HELP_TEXTS, HTMODES, HWMODES, ENCRYPTIONMODES } from "./constants";
|
||||
import WifiGuestForm from "./WiFiGuestForm";
|
||||
import { Switch } from "../../bootstrap/Switch";
|
||||
import { CheckBox } from "../../bootstrap/CheckBox";
|
||||
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 PasswordInput from "../../bootstrap/PasswordInput";
|
||||
import RadioSet from "../../bootstrap/RadioSet";
|
||||
import Select from "../../bootstrap/Select";
|
||||
import Switch from "../../bootstrap/Switch";
|
||||
import TextInput from "../../bootstrap/TextInput";
|
||||
import WifiGuestForm from "./WiFiGuestForm";
|
||||
import { HELP_TEXTS, HTMODES, HWMODES } from "./constants";
|
||||
|
||||
WiFiForm.propTypes = {
|
||||
formData: PropTypes.shape({ devices: PropTypes.arrayOf(PropTypes.object) })
|
||||
@ -64,9 +63,6 @@ DeviceForm.propTypes = {
|
||||
htmode: PropTypes.string.isRequired,
|
||||
channel: PropTypes.string.isRequired,
|
||||
guest_wifi: PropTypes.object.isRequired,
|
||||
encryption: PropTypes.string.isRequired,
|
||||
available_bands: PropTypes.array.isRequired,
|
||||
ieee80211w_disabled: PropTypes.bool,
|
||||
}),
|
||||
formErrors: PropTypes.object.isRequired,
|
||||
setFormValue: PropTypes.func.isRequired,
|
||||
@ -90,11 +86,10 @@ function DeviceForm({
|
||||
...props
|
||||
}) {
|
||||
const deviceID = formData.id;
|
||||
const bnds = formData.available_bands;
|
||||
return (
|
||||
<>
|
||||
<Switch
|
||||
label={<h2 className="mb-0">{_(`Wi-Fi ${deviceID + 1}`)}</h2>}
|
||||
label={<h2>{_(`Wi-Fi ${deviceID + 1}`)}</h2>}
|
||||
checked={formData.enabled}
|
||||
onChange={setFormValue((value) => ({
|
||||
devices: {
|
||||
@ -104,7 +99,7 @@ function DeviceForm({
|
||||
switchHeading
|
||||
{...props}
|
||||
/>
|
||||
{formData.enabled && (
|
||||
{formData.enabled ? (
|
||||
<>
|
||||
<TextInput
|
||||
label="SSID"
|
||||
@ -121,10 +116,12 @@ function DeviceForm({
|
||||
}))}
|
||||
{...props}
|
||||
>
|
||||
<WiFiQRCode
|
||||
SSID={formData.SSID}
|
||||
password={formData.password}
|
||||
/>
|
||||
<div className="input-group-append">
|
||||
<WiFiQRCode
|
||||
SSID={formData.SSID}
|
||||
password={formData.password}
|
||||
/>
|
||||
</div>
|
||||
</TextInput>
|
||||
|
||||
<PasswordInput
|
||||
@ -142,7 +139,7 @@ function DeviceForm({
|
||||
{...props}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
<CheckBox
|
||||
label={_("Hide SSID")}
|
||||
helpText={HELP_TEXTS.hidden}
|
||||
checked={formData.hidden}
|
||||
@ -161,29 +158,19 @@ function DeviceForm({
|
||||
value={formData.hwmode}
|
||||
helpText={HELP_TEXTS.hwmode}
|
||||
inline
|
||||
onChange={setFormValue((value) => {
|
||||
// Get the last item in an array of available HT modes
|
||||
const [best2] = bnds[0].available_htmodes.slice(-1);
|
||||
const [best5] = bnds[1].available_htmodes.slice(-1);
|
||||
return {
|
||||
devices: {
|
||||
[deviceIndex]: {
|
||||
hwmode: { $set: value },
|
||||
channel: { $set: "0" },
|
||||
htmode: {
|
||||
$set:
|
||||
// Set HT mode depending on checked frequency
|
||||
value === "11a" ? best5 : best2,
|
||||
},
|
||||
},
|
||||
onChange={setFormValue((value) => ({
|
||||
devices: {
|
||||
[deviceIndex]: {
|
||||
hwmode: { $set: value },
|
||||
channel: { $set: "0" },
|
||||
},
|
||||
};
|
||||
})}
|
||||
},
|
||||
}))}
|
||||
{...props}
|
||||
/>
|
||||
|
||||
<Select
|
||||
label={_("802.11n/ac/ax mode")}
|
||||
label={_("802.11n/ac mode")}
|
||||
choices={getHtmodeChoices(formData)}
|
||||
value={formData.htmode}
|
||||
helpText={HELP_TEXTS.htmode}
|
||||
@ -207,38 +194,6 @@ function DeviceForm({
|
||||
{...props}
|
||||
/>
|
||||
|
||||
<Select
|
||||
label={_("Encryption")}
|
||||
choices={getEncryptionChoices(formData)}
|
||||
helpText={HELP_TEXTS.wpa3}
|
||||
value={formData.encryption}
|
||||
onChange={setFormValue((value) => ({
|
||||
devices: {
|
||||
[deviceIndex]: { encryption: { $set: value } },
|
||||
},
|
||||
}))}
|
||||
{...props}
|
||||
/>
|
||||
|
||||
{(formData.encryption === "WPA3" ||
|
||||
formData.encryption === "WPA2/3") && (
|
||||
<Switch
|
||||
label={_("Disable Management Frame Protection")}
|
||||
helpText={_(
|
||||
"In case you have trouble connecting to WiFi Access Point, try disabling Management Frame Protection."
|
||||
)}
|
||||
checked={formData.ieee80211w_disabled}
|
||||
onChange={setFormValue((value) => ({
|
||||
devices: {
|
||||
[deviceIndex]: {
|
||||
ieee80211w_disabled: { $set: value },
|
||||
},
|
||||
},
|
||||
}))}
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
|
||||
{hasGuestNetwork && (
|
||||
<WifiGuestForm
|
||||
formData={{
|
||||
@ -251,8 +206,8 @@ function DeviceForm({
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{divider && <hr />}
|
||||
) : null}
|
||||
{divider ? <hr /> : null}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@ -269,8 +224,8 @@ function getChannelChoices(device) {
|
||||
channelChoices[availableChannel.number.toString()] = `
|
||||
${availableChannel.number}
|
||||
(${availableChannel.frequency} MHz ${
|
||||
availableChannel.radar ? " ,DFS" : ""
|
||||
})
|
||||
availableChannel.radar ? " ,DFS" : ""
|
||||
})
|
||||
`;
|
||||
});
|
||||
});
|
||||
@ -297,10 +252,3 @@ function getHwmodeChoices(device) {
|
||||
value: availableBand.hwmode,
|
||||
}));
|
||||
}
|
||||
|
||||
function getEncryptionChoices(device) {
|
||||
if (device.encryption === "custom") {
|
||||
ENCRYPTIONMODES.custom = _("Custom");
|
||||
}
|
||||
return ENCRYPTIONMODES;
|
||||
}
|
||||
|
@ -1,19 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { HELP_TEXTS } from "./constants";
|
||||
import { TextInput } from "../../bootstrap/TextInput";
|
||||
import { Switch } from "../../bootstrap/Switch";
|
||||
import { PasswordInput } from "../../bootstrap/PasswordInput";
|
||||
import WiFiQRCode from "./WiFiQRCode";
|
||||
import PasswordInput from "../../bootstrap/PasswordInput";
|
||||
import Switch from "../../bootstrap/Switch";
|
||||
import TextInput from "../../bootstrap/TextInput";
|
||||
import { HELP_TEXTS } from "./constants";
|
||||
|
||||
WifiGuestForm.propTypes = {
|
||||
formData: PropTypes.shape({
|
||||
|
@ -6,19 +6,18 @@
|
||||
*/
|
||||
|
||||
import React, { useState } from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
import QRCode from "qrcode.react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { createAndDownloadPdf, toQRCodeContent } from "./qrCodeHelpers";
|
||||
import Button from "../../bootstrap/Button";
|
||||
import { ForisURLs } from "../../utils/forisUrls";
|
||||
import { Button } from "../../bootstrap/Button";
|
||||
import {
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
} from "../../bootstrap/Modal";
|
||||
import { ForisURLs } from "../../utils/forisUrls";
|
||||
import { createAndDownloadPdf, toQRCodeContent } from "./qrCodeHelpers";
|
||||
|
||||
WiFiQRCode.propTypes = {
|
||||
SSID: PropTypes.string.isRequired,
|
||||
@ -88,7 +87,7 @@ function QRCodeModal({ shown, setShown, SSID, password }) {
|
||||
createAndDownloadPdf(SSID, password);
|
||||
}}
|
||||
>
|
||||
<i className="fas fa-file-download me-2" />
|
||||
<i className="fas fa-arrow-down mr-2" />
|
||||
{_("Download PDF")}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
|
@ -1,17 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import ResetWiFiSettings from "./ResetWiFiSettings";
|
||||
import { ForisForm } from "../../form/components/ForisForm";
|
||||
import WiFiForm from "./WiFiForm";
|
||||
import ForisForm from "../../form/components/ForisForm";
|
||||
import ResetWiFiSettings from "./ResetWiFiSettings";
|
||||
|
||||
WiFiSettings.propTypes = {
|
||||
ws: PropTypes.object.isRequired,
|
||||
@ -20,7 +19,7 @@ WiFiSettings.propTypes = {
|
||||
hasGuestNetwork: PropTypes.bool,
|
||||
};
|
||||
|
||||
function WiFiSettings({ ws, endpoint, resetEndpoint, hasGuestNetwork }) {
|
||||
export function WiFiSettings({ ws, endpoint, resetEndpoint, hasGuestNetwork }) {
|
||||
return (
|
||||
<>
|
||||
<ForisForm
|
||||
@ -60,10 +59,6 @@ function prepDataToSubmit(formData) {
|
||||
|
||||
if (!device.guest_wifi.enabled)
|
||||
formData.devices[idx].guest_wifi = { enabled: false };
|
||||
|
||||
if (device.encryption === "WPA2") {
|
||||
delete formData.devices[idx].ieee80211w_disabled;
|
||||
}
|
||||
});
|
||||
return formData;
|
||||
}
|
||||
@ -87,10 +82,6 @@ export function validator(formData) {
|
||||
|
||||
if (device.password.length < 8)
|
||||
errors.password = _("Password must contain at least 8 symbols");
|
||||
if (device.password.length >= 64)
|
||||
errors.password = _(
|
||||
"Password must not contain more than 63 symbols"
|
||||
);
|
||||
|
||||
if (!device.guest_wifi.enabled) return errors;
|
||||
|
||||
@ -106,10 +97,6 @@ export function validator(formData) {
|
||||
guest_wifi_errors.password = _(
|
||||
"Password must contain at least 8 symbols"
|
||||
);
|
||||
if (device.guest_wifi.password.length >= 64)
|
||||
guest_wifi_errors.password = _(
|
||||
"Password must not contain more than 63 symbols"
|
||||
);
|
||||
|
||||
if (guest_wifi_errors.SSID || guest_wifi_errors.password) {
|
||||
errors.guest_wifi = guest_wifi_errors;
|
||||
@ -118,5 +105,3 @@ export function validator(formData) {
|
||||
});
|
||||
return JSON.stringify(formErrors).match(/\[[{},?]+\]/) ? null : formErrors;
|
||||
}
|
||||
|
||||
export default WiFiSettings;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2021 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
* 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.
|
||||
@ -9,7 +9,7 @@ import React from "react";
|
||||
import { render, fireEvent, wait } from "customTestRender";
|
||||
|
||||
import mockAxios from "jest-mock-axios";
|
||||
import WebSockets from "webSockets/WebSockets";
|
||||
import { WebSockets } from "webSockets/WebSockets";
|
||||
import { mockJSONError } from "testUtils/network";
|
||||
import { mockSetAlert } from "testUtils/alertContextMock";
|
||||
import { ALERT_TYPES } from "../../../bootstrap/Alert";
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2021 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
* 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.
|
||||
@ -10,7 +10,7 @@ import diffSnapshot from "snapshot-diff";
|
||||
import mockAxios from "jest-mock-axios";
|
||||
|
||||
import { fireEvent, render, wait } from "customTestRender";
|
||||
import WebSockets from "webSockets/WebSockets";
|
||||
import { WebSockets } from "webSockets/WebSockets";
|
||||
import { mockJSONError } from "testUtils/network";
|
||||
|
||||
import {
|
||||
@ -19,14 +19,13 @@ import {
|
||||
twoDevices,
|
||||
threeDevices,
|
||||
} from "./__fixtures__/wifiSettings";
|
||||
import WiFiSettings, { validator, byteCount } from "../WiFiSettings";
|
||||
import { WiFiSettings, validator, byteCount } from "../WiFiSettings";
|
||||
|
||||
describe("<WiFiSettings/>", () => {
|
||||
let firstRender;
|
||||
let getAllByText;
|
||||
let getAllByLabelText;
|
||||
let getByText;
|
||||
let getByLabelText;
|
||||
let asFragment;
|
||||
const endpoint = "/reforis/api/wifi";
|
||||
|
||||
@ -42,7 +41,6 @@ describe("<WiFiSettings/>", () => {
|
||||
asFragment = renderRes.asFragment;
|
||||
getAllByText = renderRes.getAllByText;
|
||||
getAllByLabelText = renderRes.getAllByLabelText;
|
||||
getByLabelText = renderRes.getByLabelText;
|
||||
getByText = renderRes.getByText;
|
||||
mockAxios.mockResponse({ data: wifiSettingsFixture() });
|
||||
await wait(() => renderRes.getByText("Wi-Fi 1"));
|
||||
@ -53,6 +51,7 @@ describe("<WiFiSettings/>", () => {
|
||||
const webSockets = new WebSockets();
|
||||
const { getByText } = render(
|
||||
<WiFiSettings
|
||||
ws={webSockets}
|
||||
ws={webSockets}
|
||||
endpoint={endpoint}
|
||||
resetEndpoint="foo"
|
||||
@ -117,11 +116,10 @@ describe("<WiFiSettings/>", () => {
|
||||
enabled: true,
|
||||
guest_wifi: { enabled: false },
|
||||
hidden: false,
|
||||
htmode: "HT80",
|
||||
htmode: "HT40",
|
||||
hwmode: "11a",
|
||||
id: 0,
|
||||
password: "TestPass",
|
||||
encryption: "WPA3",
|
||||
},
|
||||
{ enabled: false, id: 1 },
|
||||
],
|
||||
@ -147,11 +145,10 @@ describe("<WiFiSettings/>", () => {
|
||||
enabled: true,
|
||||
guest_wifi: { enabled: false },
|
||||
hidden: false,
|
||||
htmode: "VHT80",
|
||||
htmode: "HT40",
|
||||
hwmode: "11g",
|
||||
id: 0,
|
||||
password: "TestPass",
|
||||
encryption: "WPA3",
|
||||
},
|
||||
{ enabled: false, id: 1 },
|
||||
],
|
||||
@ -184,11 +181,10 @@ describe("<WiFiSettings/>", () => {
|
||||
password: "test_password",
|
||||
},
|
||||
hidden: false,
|
||||
htmode: "HT80",
|
||||
htmode: "HT40",
|
||||
hwmode: "11a",
|
||||
id: 0,
|
||||
password: "TestPass",
|
||||
encryption: "WPA3",
|
||||
},
|
||||
{ enabled: false, id: 1 },
|
||||
],
|
||||
@ -221,24 +217,4 @@ describe("<WiFiSettings/>", () => {
|
||||
it("ByteCount function", () => {
|
||||
expect(byteCount("abc")).toEqual(3);
|
||||
});
|
||||
|
||||
it("Should validate password length", () => {
|
||||
const shortErrorFeedback = /Password must contain/i;
|
||||
const longErrorFeedback = /Password must not contain/i;
|
||||
|
||||
fireEvent.click(getByText("Wi-Fi 1"));
|
||||
|
||||
const passwordInput = getByLabelText("Password");
|
||||
|
||||
const changePassword = (value) =>
|
||||
fireEvent.change(passwordInput, { target: { value } });
|
||||
|
||||
changePassword("12");
|
||||
expect(getByText(shortErrorFeedback)).toBeDefined();
|
||||
|
||||
changePassword(
|
||||
"longpasswordlongpasswordlongpasswordlongpasswordlongpasswordlong"
|
||||
);
|
||||
expect(getByText(longErrorFeedback)).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2021 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
* 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.
|
||||
@ -226,11 +226,10 @@ export function wifiSettingsFixture() {
|
||||
password: "",
|
||||
},
|
||||
hidden: false,
|
||||
htmode: "HT80",
|
||||
htmode: "HT40",
|
||||
hwmode: "11a",
|
||||
id: 0,
|
||||
password: "TestPass",
|
||||
encryption: "WPA3",
|
||||
},
|
||||
{
|
||||
SSID: "Turris",
|
||||
@ -309,7 +308,6 @@ export function wifiSettingsFixture() {
|
||||
hwmode: "11g",
|
||||
id: 1,
|
||||
password: "TestPass",
|
||||
encryption: "WPA3",
|
||||
},
|
||||
],
|
||||
};
|
||||
@ -326,7 +324,6 @@ const oneDevice = {
|
||||
hwmode: "11a",
|
||||
id: 0,
|
||||
password: "TestPass",
|
||||
encryption: "WPA3",
|
||||
},
|
||||
],
|
||||
};
|
||||
@ -343,7 +340,6 @@ const twoDevices = {
|
||||
hwmode: "11a",
|
||||
id: 0,
|
||||
password: "TestPass",
|
||||
encryption: "WPA3",
|
||||
},
|
||||
{
|
||||
SSID: "Turris2",
|
||||
@ -353,9 +349,8 @@ const twoDevices = {
|
||||
hidden: false,
|
||||
htmode: "HT40",
|
||||
hwmode: "11a",
|
||||
id: 1,
|
||||
id: 0,
|
||||
password: "TestPass",
|
||||
encryption: "WPA3",
|
||||
},
|
||||
],
|
||||
};
|
||||
@ -372,7 +367,6 @@ const threeDevices = {
|
||||
hwmode: "11a",
|
||||
id: 0,
|
||||
password: "TestPass",
|
||||
encryption: "WPA3",
|
||||
},
|
||||
{
|
||||
SSID: "Turris2",
|
||||
@ -382,9 +376,8 @@ const threeDevices = {
|
||||
hidden: false,
|
||||
htmode: "HT40",
|
||||
hwmode: "11a",
|
||||
id: 1,
|
||||
id: 0,
|
||||
password: "TestPass",
|
||||
encryption: "WPA3",
|
||||
},
|
||||
{
|
||||
SSID: "Turris3",
|
||||
@ -394,9 +387,8 @@ const threeDevices = {
|
||||
hidden: false,
|
||||
htmode: "HT40",
|
||||
hwmode: "11a",
|
||||
id: 2,
|
||||
id: 0,
|
||||
password: "",
|
||||
encryption: "WPA3",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2022 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* 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.
|
||||
@ -13,40 +13,33 @@ export const HTMODES = {
|
||||
VHT40: _("802.11ac - 40 MHz wide channel"),
|
||||
VHT80: _("802.11ac - 80 MHz wide channel"),
|
||||
VHT160: _("802.11ac - 160 MHz wide channel"),
|
||||
HE20: _("802.11ax - 20 MHz wide channel"),
|
||||
HE40: _("802.11ax - 40 MHz wide channel"),
|
||||
HE80: _("802.11ax - 80 MHz wide channel"),
|
||||
HE160: _("802.11ax - 160 MHz wide channel"),
|
||||
};
|
||||
export const HWMODES = {
|
||||
"11g": "2.4",
|
||||
"11a": "5",
|
||||
};
|
||||
export const ENCRYPTIONMODES = {
|
||||
WPA3: _("WPA3 only"),
|
||||
"WPA2/3": _("WPA3 with WPA2 as fallback (default)"),
|
||||
WPA2: _("WPA2 only"),
|
||||
};
|
||||
export const HELP_TEXTS = {
|
||||
ssid: _(
|
||||
"SSID which contains non-standard characters could cause problems on some devices."
|
||||
),
|
||||
password: _(
|
||||
"WPA2/3 pre-shared key, that is required to connect to the network."
|
||||
`SSID which contains non-standard characters could cause problems on some devices.`
|
||||
),
|
||||
password: _(`
|
||||
WPA2 pre-shared key, that is required to connect to the network.
|
||||
`),
|
||||
hidden: _(
|
||||
"If set, network is not visible when scanning for available networks."
|
||||
),
|
||||
hwmode: _(
|
||||
"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."
|
||||
),
|
||||
htmode: _(
|
||||
"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."
|
||||
),
|
||||
guest_wifi_enabled: _(
|
||||
"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."
|
||||
),
|
||||
wpa3: _(
|
||||
"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."
|
||||
),
|
||||
hwmode: _(`
|
||||
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.`),
|
||||
htmode: _(`
|
||||
Change this to adjust 802.11n/ac 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.
|
||||
`),
|
||||
guest_wifi_enabled: _(`
|
||||
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.
|
||||
`),
|
||||
};
|
||||
|
@ -18,7 +18,7 @@ import mockAxios from "jest-mock-axios";
|
||||
import { mockJSONError } from "testUtils/network";
|
||||
import { mockSetAlert } from "testUtils/alertContextMock";
|
||||
|
||||
import RebootButton from "../RebootButton";
|
||||
import { RebootButton } from "../RebootButton";
|
||||
|
||||
describe("<RebootButton/>", () => {
|
||||
let componentContainer;
|
||||
|
@ -25,10 +25,15 @@ exports[`<RebootButton/> Render modal. 1`] = `
|
||||
Warning!
|
||||
</h5>
|
||||
<button
|
||||
aria-label="Close"
|
||||
class="btn-close"
|
||||
class="close"
|
||||
type="button"
|
||||
/>
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
>
|
||||
×
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="modal-body"
|
||||
@ -41,20 +46,16 @@ exports[`<RebootButton/> Render modal. 1`] = `
|
||||
class="modal-footer"
|
||||
>
|
||||
<button
|
||||
class="btn btn-primary d-inline-flex justify-content-center align-items-center"
|
||||
class="btn btn-primary "
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Cancel
|
||||
</span>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-danger d-inline-flex justify-content-center align-items-center"
|
||||
class="btn btn-danger"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Confirm reboot
|
||||
</span>
|
||||
Confirm reboot
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -62,12 +63,10 @@ exports[`<RebootButton/> Render modal. 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
class="btn btn-danger d-inline-flex justify-content-center align-items-center"
|
||||
class="btn btn-danger"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reboot
|
||||
</span>
|
||||
Reboot
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
@ -78,12 +77,10 @@ exports[`<RebootButton/> Render. 1`] = `
|
||||
id="modal-container"
|
||||
/>
|
||||
<button
|
||||
class="btn btn-danger d-inline-flex justify-content-center align-items-center"
|
||||
class="btn btn-danger"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reboot
|
||||
</span>
|
||||
Reboot
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React, { useContext, useEffect, useMemo } from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { useAPIGet } from "../../api/hooks";
|
||||
import { Spinner } from "../../bootstrap/Spinner";
|
||||
import { ForisURLs } from "../../utils/forisUrls";
|
||||
|
||||
CustomizationContextProvider.propTypes = {
|
||||
children: PropTypes.oneOfType([
|
||||
PropTypes.arrayOf(PropTypes.node),
|
||||
PropTypes.node,
|
||||
]),
|
||||
};
|
||||
|
||||
function CustomizationContextProvider({ children }) {
|
||||
const { CustomizationContext } = window;
|
||||
const [getCustomizationResponse, getCustomization] = useAPIGet(
|
||||
ForisURLs.about
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
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") {
|
||||
return <Spinner fullScreen />;
|
||||
}
|
||||
|
||||
return (
|
||||
<CustomizationContext.Provider value={contextValue}>
|
||||
{children}
|
||||
</CustomizationContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
function useCustomizationContext() {
|
||||
const { CustomizationContext } = window;
|
||||
return useContext(CustomizationContext);
|
||||
}
|
||||
|
||||
export { CustomizationContextProvider, useCustomizationContext };
|
@ -1,3 +0,0 @@
|
||||
It provides customization context to the children. `CustomizationContext` allows
|
||||
using `useCustomizationContext` in components to check if the reForis UI is
|
||||
customized or not for specific devices.
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2022 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
import { render, wait, getByText } from "customTestRender";
|
||||
import mockAxios from "jest-mock-axios";
|
||||
|
||||
import {
|
||||
useCustomizationContext,
|
||||
CustomizationContextProvider,
|
||||
} from "../CustomizationContext";
|
||||
|
||||
const CUSTOM = "Description / component for customized reForis (Shield)";
|
||||
const ORIGINAL = "Description / component for original reForis (other devices)";
|
||||
|
||||
const CustomizationTest = () => {
|
||||
const { isCustomized } = useCustomizationContext();
|
||||
|
||||
return <p>{isCustomized ? CUSTOM : ORIGINAL}</p>;
|
||||
};
|
||||
|
||||
describe("CustomizationContext", () => {
|
||||
let componentContainer;
|
||||
beforeEach(() => {
|
||||
const { container } = render(
|
||||
<CustomizationContextProvider>
|
||||
<CustomizationTest />
|
||||
</CustomizationContextProvider>
|
||||
);
|
||||
componentContainer = container;
|
||||
});
|
||||
|
||||
it("should render component without customization", async () => {
|
||||
mockAxios.mockResponse({ data: {} });
|
||||
|
||||
await wait(() => getByText(componentContainer, ORIGINAL));
|
||||
|
||||
expect(componentContainer).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should render customized component", async () => {
|
||||
mockAxios.mockResponse({ data: { customization: "shield" } });
|
||||
|
||||
await wait(() => getByText(componentContainer, CUSTOM));
|
||||
|
||||
expect(componentContainer).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -1,17 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`CustomizationContext should render component without customization 1`] = `
|
||||
<div>
|
||||
<p>
|
||||
Description / component for original reForis (other devices)
|
||||
</p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`CustomizationContext should render customized component 1`] = `
|
||||
<div>
|
||||
<p>
|
||||
Description / component for customized reForis (Shield)
|
||||
</p>
|
||||
</div>
|
||||
`;
|
@ -3,18 +3,17 @@
|
||||
exports[`<SubmitButton/> Render load 1`] = `
|
||||
<div>
|
||||
<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-sm-12 col-md-3 col-lg-2"
|
||||
disabled=""
|
||||
type="submit"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="spinner-border spinner-border-sm me-1"
|
||||
class="spinner-border spinner-border-sm"
|
||||
role="status"
|
||||
/>
|
||||
<span>
|
||||
Load settings
|
||||
</span>
|
||||
|
||||
Load settings
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
@ -22,12 +21,10 @@ exports[`<SubmitButton/> Render load 1`] = `
|
||||
exports[`<SubmitButton/> Render ready 1`] = `
|
||||
<div>
|
||||
<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-sm-12 col-md-3 col-lg-2"
|
||||
type="submit"
|
||||
>
|
||||
<span>
|
||||
Save
|
||||
</span>
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
@ -35,18 +32,17 @@ exports[`<SubmitButton/> Render ready 1`] = `
|
||||
exports[`<SubmitButton/> Render saving 1`] = `
|
||||
<div>
|
||||
<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-sm-12 col-md-3 col-lg-2"
|
||||
disabled=""
|
||||
type="submit"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="spinner-border spinner-border-sm me-1"
|
||||
class="spinner-border spinner-border-sm"
|
||||
role="status"
|
||||
/>
|
||||
<span>
|
||||
Updating
|
||||
</span>
|
||||
|
||||
Updating
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
@ -9,8 +9,8 @@ import React from "react";
|
||||
|
||||
import { act, fireEvent, render, waitForElement } from "customTestRender";
|
||||
import mockAxios from "jest-mock-axios";
|
||||
import WebSockets from "webSockets/WebSockets";
|
||||
import ForisForm from "../components/ForisForm";
|
||||
import { WebSockets } from "webSockets/WebSockets";
|
||||
import { ForisForm } from "../components/ForisForm";
|
||||
|
||||
// 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.
|
||||
|
@ -1,17 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2022 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import {
|
||||
validateDomain,
|
||||
validateDUID,
|
||||
validateIPv4Address,
|
||||
validateIPv6Address,
|
||||
validateIPv6Prefix,
|
||||
validateDomain,
|
||||
validateHostname,
|
||||
validateDUID,
|
||||
validateMAC,
|
||||
} from "utils/validations";
|
||||
|
||||
@ -69,15 +68,6 @@ describe("Validation functions", () => {
|
||||
expect(validateDomain(".")).not.toBe(undefined);
|
||||
});
|
||||
|
||||
it("validateHostname valid", () => {
|
||||
expect(validateHostname("new-android")).toBe(undefined);
|
||||
expect(validateHostname("local")).toBe(undefined);
|
||||
});
|
||||
it("validateHostname invalid", () => {
|
||||
expect(validateHostname("-android")).not.toBe(undefined);
|
||||
expect(validateHostname("local.")).not.toBe(undefined);
|
||||
});
|
||||
|
||||
it("validateDUID valid", () => {
|
||||
expect(validateDUID("abcdefAB")).toBe(undefined);
|
||||
expect(validateDUID("ABCDEF12")).toBe(undefined);
|
||||
|
@ -1,24 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React, { useEffect } from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
import { Prompt } from "react-router-dom";
|
||||
|
||||
import { STATES as SUBMIT_BUTTON_STATES, SubmitButton } from "./SubmitButton";
|
||||
import { useAPIPost } from "../../api/hooks";
|
||||
import { API_STATE } from "../../api/utils";
|
||||
import { ALERT_TYPES } from "../../bootstrap/Alert";
|
||||
import { API_STATE } from "../../api/utils";
|
||||
import { formFieldsSize } from "../../bootstrap/constants";
|
||||
import { Spinner } from "../../bootstrap/Spinner";
|
||||
import { useAlert } from "../../context/alertContext/AlertContext";
|
||||
import ErrorMessage from "../../utils/ErrorMessage";
|
||||
import { useAlert } from "../../alertContext/AlertContext";
|
||||
import { useAPIPost } from "../../api/hooks";
|
||||
|
||||
import { useForisModule, useForm } from "../hooks";
|
||||
import { STATES as SUBMIT_BUTTON_STATES, SubmitButton } from "./SubmitButton";
|
||||
import { ErrorMessage } from "../../utils/ErrorMessage";
|
||||
|
||||
ForisForm.propTypes = {
|
||||
/** 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.
|
||||
* See README for more information.
|
||||
* */
|
||||
function ForisForm({
|
||||
export function ForisForm({
|
||||
ws,
|
||||
forisConfig,
|
||||
prepData,
|
||||
@ -131,16 +131,16 @@ function ForisForm({
|
||||
return <Spinner />;
|
||||
}
|
||||
|
||||
const onSubmitHandler = (event) => {
|
||||
function onSubmitHandler(event) {
|
||||
event.preventDefault();
|
||||
resetFormData();
|
||||
dismissAlert();
|
||||
const copiedFormData = JSON.parse(JSON.stringify(formState.data));
|
||||
const preparedData = prepDataToSubmit(copiedFormData);
|
||||
post({ data: preparedData });
|
||||
};
|
||||
}
|
||||
|
||||
const getSubmitButtonState = () => {
|
||||
function getSubmitButtonState() {
|
||||
if (postState.state === API_STATE.SENDING) {
|
||||
return SUBMIT_BUTTON_STATES.SAVING;
|
||||
}
|
||||
@ -148,7 +148,7 @@ function ForisForm({
|
||||
return SUBMIT_BUTTON_STATES.LOAD;
|
||||
}
|
||||
return SUBMIT_BUTTON_STATES.READY;
|
||||
};
|
||||
}
|
||||
|
||||
const formIsDisabled =
|
||||
disabled ||
|
||||
@ -174,7 +174,7 @@ function ForisForm({
|
||||
)
|
||||
: onSubmitHandler;
|
||||
|
||||
const getMessageOnLeavingPage = () => {
|
||||
function getMessageOnLeavingPage() {
|
||||
if (
|
||||
JSON.stringify(formState.data) ===
|
||||
JSON.stringify(formState.initialData)
|
||||
@ -183,14 +183,14 @@ function ForisForm({
|
||||
return _(
|
||||
"Changes you made may not be saved. Are you sure you want to leave?"
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={formFieldsSize}>
|
||||
<Prompt message={getMessageOnLeavingPage} />
|
||||
<form onSubmit={onSubmit} ref={formReference}>
|
||||
{childrenWithFormProps}
|
||||
<div className="text-end">
|
||||
<div className="text-right">
|
||||
<SubmitButton
|
||||
state={getSubmitButtonState()}
|
||||
disabled={submitButtonIsDisabled}
|
||||
@ -200,5 +200,3 @@ function ForisForm({
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ForisForm;
|
||||
|
@ -6,10 +6,9 @@
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import Button from "../../bootstrap/Button";
|
||||
import { Button } from "../../bootstrap/Button";
|
||||
|
||||
export const STATES = {
|
||||
READY: 1,
|
||||
|
@ -1,16 +1,15 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import { useCallback, useEffect, useReducer } from "react";
|
||||
|
||||
import update from "immutability-helper";
|
||||
|
||||
import { useAPIGet } from "../api/hooks";
|
||||
import useWSForisModule from "../webSockets/hooks";
|
||||
import { useWSForisModule } from "../webSockets/hooks";
|
||||
|
||||
const FORM_ACTIONS = {
|
||||
updateValue: 1,
|
||||
|
64
src/index.js
64
src/index.js
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* 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.
|
||||
@ -17,32 +17,30 @@ export {
|
||||
export { API_STATE } from "./api/utils";
|
||||
|
||||
// Bootstrap
|
||||
export { default as Alert, ALERT_TYPES } from "./bootstrap/Alert";
|
||||
export { default as Button } from "./bootstrap/Button";
|
||||
export { default as CheckBox } from "./bootstrap/CheckBox";
|
||||
export { default as CopyInput } from "./bootstrap/CopyInput";
|
||||
export { default as DownloadButton } from "./bootstrap/DownloadButton";
|
||||
export { default as DataTimeInput } from "./bootstrap/DataTimeInput";
|
||||
export { default as EmailInput } from "./bootstrap/EmailInput";
|
||||
export { default as FileInput } from "./bootstrap/FileInput";
|
||||
export { default as Input } from "./bootstrap/Input";
|
||||
export { default as NumberInput } from "./bootstrap/NumberInput";
|
||||
export { default as PasswordInput } from "./bootstrap/PasswordInput";
|
||||
export { default as RadioSet, Radio } from "./bootstrap/RadioSet";
|
||||
export { default as Select } from "./bootstrap/Select";
|
||||
export { default as TextInput } from "./bootstrap/TextInput";
|
||||
export { Alert, ALERT_TYPES } from "./bootstrap/Alert";
|
||||
export { Button } from "./bootstrap/Button";
|
||||
export { CheckBox } from "./bootstrap/CheckBox";
|
||||
export { DownloadButton } from "./bootstrap/DownloadButton";
|
||||
export { DataTimeInput } from "./bootstrap/DataTimeInput";
|
||||
export { EmailInput } from "./bootstrap/EmailInput";
|
||||
export { FileInput } from "./bootstrap/FileInput";
|
||||
export { Input } from "./bootstrap/Input";
|
||||
export { NumberInput } from "./bootstrap/NumberInput";
|
||||
export { PasswordInput } from "./bootstrap/PasswordInput";
|
||||
export { Radio, RadioSet } from "./bootstrap/RadioSet";
|
||||
export { Select } from "./bootstrap/Select";
|
||||
export { TextInput } from "./bootstrap/TextInput";
|
||||
export { formFieldsSize, buttonFormFieldsSize } from "./bootstrap/constants";
|
||||
export { default as Switch } from "./bootstrap/Switch";
|
||||
export { Switch } from "./bootstrap/Switch";
|
||||
|
||||
export { Spinner, SpinnerElement } from "./bootstrap/Spinner";
|
||||
export { Modal, ModalBody, ModalFooter, ModalHeader } from "./bootstrap/Modal";
|
||||
|
||||
// Common
|
||||
export { default as RebootButton } from "./common/RebootButton";
|
||||
export { default as WiFiSettings } from "./common/WiFiSettings/WiFiSettings";
|
||||
export { default as ResetWiFiSettings } from "./common/WiFiSettings/ResetWiFiSettings";
|
||||
export { RebootButton } from "./common/RebootButton";
|
||||
export { WiFiSettings } from "./common/WiFiSettings/WiFiSettings";
|
||||
// Form
|
||||
export { default as ForisForm } from "./form/components/ForisForm";
|
||||
export { ForisForm } from "./form/components/ForisForm";
|
||||
export {
|
||||
SubmitButton,
|
||||
STATES as SUBMIT_BUTTON_STATES,
|
||||
@ -50,11 +48,11 @@ export {
|
||||
export { useForisModule, useForm } from "./form/hooks";
|
||||
|
||||
// WebSockets
|
||||
export { default as useWSForisModule } from "./webSockets/hooks";
|
||||
export { default as WebSockets } from "./webSockets/WebSockets";
|
||||
export { useWSForisModule } from "./webSockets/hooks";
|
||||
export { WebSockets } from "./webSockets/WebSockets";
|
||||
|
||||
// Utils
|
||||
export { default as Portal } from "./utils/Portal";
|
||||
export { Portal } from "./utils/Portal";
|
||||
export {
|
||||
undefinedIfEmpty,
|
||||
withoutUndefinedKeys,
|
||||
@ -68,11 +66,11 @@ export {
|
||||
withError,
|
||||
withErrorMessage,
|
||||
} from "./utils/conditionalHOCs";
|
||||
export { default as ErrorMessage } from "./utils/ErrorMessage";
|
||||
export { ErrorMessage } from "./utils/ErrorMessage";
|
||||
export { useClickOutside } from "./utils/hooks";
|
||||
export { default as toLocaleDateString } from "./utils/datetime";
|
||||
export { default as displayCard } from "./utils/displayCard";
|
||||
export { default as isPluginInstalled } from "./utils/isPluginInstalled";
|
||||
export { toLocaleDateString } from "./utils/datetime";
|
||||
export { displayCard } from "./utils/displayCard";
|
||||
export { isPluginInstalled } from "./utils/isPluginInstalled";
|
||||
|
||||
// Foris URL
|
||||
export { ForisURLs, REFORIS_URL_PREFIX } from "./utils/forisUrls";
|
||||
@ -83,20 +81,10 @@ export {
|
||||
validateIPv6Address,
|
||||
validateIPv6Prefix,
|
||||
validateDomain,
|
||||
validateHostname,
|
||||
validateDUID,
|
||||
validateMAC,
|
||||
validateMultipleEmails,
|
||||
} from "./utils/validations";
|
||||
|
||||
// Alert context
|
||||
export {
|
||||
AlertContextProvider,
|
||||
useAlert,
|
||||
} from "./context/alertContext/AlertContext";
|
||||
|
||||
// Customization context
|
||||
export {
|
||||
CustomizationContextProvider,
|
||||
useCustomizationContext,
|
||||
} from "./context/customizationContext/CustomizationContext";
|
||||
export { AlertContextProvider, useAlert } from "./alertContext/AlertContext";
|
||||
|
@ -14,7 +14,6 @@ import { render } from "@testing-library/react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { AlertContextMock } from "./alertContextMock";
|
||||
import { CustomizationContextMock } from "./cutomizationContextMock";
|
||||
|
||||
Wrapper.propTypes = {
|
||||
children: PropTypes.oneOfType([
|
||||
@ -25,13 +24,11 @@ Wrapper.propTypes = {
|
||||
|
||||
function Wrapper({ children }) {
|
||||
return (
|
||||
<CustomizationContextMock>
|
||||
<AlertContextMock>
|
||||
<StaticRouter>
|
||||
<UIDReset>{children}</UIDReset>
|
||||
</StaticRouter>
|
||||
</AlertContextMock>
|
||||
</CustomizationContextMock>
|
||||
<AlertContextMock>
|
||||
<StaticRouter>
|
||||
<UIDReset>{children}</UIDReset>
|
||||
</StaticRouter>
|
||||
</AlertContextMock>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2022 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
window.CustomizationContext = React.createContext();
|
||||
|
||||
const deviceDetails = {
|
||||
kernel: "5.x.x",
|
||||
model: "Turris Omnia",
|
||||
os_branch: {
|
||||
mode: "branch",
|
||||
value: "hbs",
|
||||
},
|
||||
os_version: "6.x.x",
|
||||
reforis_version: "1.x.x",
|
||||
serial: 123456789,
|
||||
};
|
||||
|
||||
const isCustomized = false;
|
||||
|
||||
function CustomizationContextMock({ children }) {
|
||||
return (
|
||||
<CustomizationContext.Provider value={{ deviceDetails, isCustomized }}>
|
||||
{children}
|
||||
</CustomizationContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export { CustomizationContextMock };
|
@ -1,12 +1,11 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
ErrorMessage.propTypes = {
|
||||
@ -17,8 +16,6 @@ ErrorMessage.defaultProps = {
|
||||
message: _("An error occurred while fetching data."),
|
||||
};
|
||||
|
||||
function ErrorMessage({ message }) {
|
||||
export function ErrorMessage({ message }) {
|
||||
return <p className="text-center text-danger">{message}</p>;
|
||||
}
|
||||
|
||||
export default ErrorMessage;
|
||||
|
@ -1,22 +1,14 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* This is free software, licensed under the GNU General Public License v3.
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
Portal.propTypes = {
|
||||
containerId: PropTypes.string.isRequired,
|
||||
children: PropTypes.node.isRequired,
|
||||
};
|
||||
|
||||
function Portal({ containerId, children }) {
|
||||
export function Portal({ containerId, children }) {
|
||||
const container = document.getElementById(containerId);
|
||||
if (container) return ReactDOM.createPortal(children, container);
|
||||
return null;
|
||||
}
|
||||
|
||||
export default Portal;
|
||||
|
@ -5,7 +5,7 @@
|
||||
* See /LICENSE for more information.
|
||||
*/
|
||||
|
||||
import toLocaleDateString from "../datetime";
|
||||
import { toLocaleDateString } from "../datetime";
|
||||
|
||||
describe("toLocaleDateString", () => {
|
||||
it("should work with different locale", () => {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* 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.
|
||||
@ -7,23 +7,16 @@
|
||||
|
||||
import React from "react";
|
||||
|
||||
import ErrorMessage from "./ErrorMessage";
|
||||
import { API_STATE } from "../api/utils";
|
||||
import { Spinner } from "../bootstrap/Spinner";
|
||||
import { API_STATE } from "../api/utils";
|
||||
import { ErrorMessage } from "./ErrorMessage";
|
||||
|
||||
function withEither(conditionalFn, Either) {
|
||||
return (Component) => {
|
||||
function WithEither(props) {
|
||||
if (conditionalFn(props)) {
|
||||
return <Either {...props} />;
|
||||
}
|
||||
return <Component {...props} />;
|
||||
return (Component) => (props) => {
|
||||
if (conditionalFn(props)) {
|
||||
return <Either {...props} />;
|
||||
}
|
||||
|
||||
// Setting displayName for better debugging
|
||||
WithEither.displayName = `WithEither(${Component.displayName || Component.name || "Component"})`;
|
||||
|
||||
return WithEither;
|
||||
return <Component {...props} />;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
import moment from "moment";
|
||||
|
||||
function toLocaleDateString(date, { inputFormat, outputFormat = "LLL" } = {}) {
|
||||
export function toLocaleDateString(
|
||||
date,
|
||||
{ inputFormat, outputFormat = "LLL" } = {}
|
||||
) {
|
||||
const parsedDate = inputFormat ? moment(date, inputFormat) : moment(date);
|
||||
return parsedDate.locale(ForisTranslations.locale).format(outputFormat);
|
||||
}
|
||||
|
||||
export default toLocaleDateString;
|
||||
|
@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
function displayCard({ package_lists: packages }, cardName) {
|
||||
export function displayCard({ package_lists: packages }, cardName) {
|
||||
const enabledPackagesNames = [];
|
||||
packages
|
||||
.filter((item) => item.enabled)
|
||||
@ -21,5 +21,3 @@ function displayCard({ package_lists: packages }, cardName) {
|
||||
});
|
||||
return enabledPackagesNames.includes(cardName);
|
||||
}
|
||||
|
||||
export default displayCard;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2021 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
* 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.
|
||||
@ -9,8 +9,8 @@ export const REFORIS_URL_PREFIX = "/reforis";
|
||||
export const REFORIS_API_URL_PREFIX = `${REFORIS_URL_PREFIX}/api`;
|
||||
|
||||
export const ForisURLs = {
|
||||
login: `/login?${REFORIS_URL_PREFIX}/`,
|
||||
logout: `/logout`,
|
||||
login: `${REFORIS_URL_PREFIX}/login`,
|
||||
logout: `${REFORIS_URL_PREFIX}/logout`,
|
||||
|
||||
static: `${REFORIS_URL_PREFIX}/static/reforis`,
|
||||
wifi: `${REFORIS_URL_PREFIX}/network-settings/wifi`,
|
||||
@ -18,12 +18,9 @@ export const ForisURLs = {
|
||||
packageManagement: {
|
||||
updateSettings: `${REFORIS_URL_PREFIX}/package-management/update-settings`,
|
||||
updates: `${REFORIS_URL_PREFIX}/package-management/updates`,
|
||||
packages: `${REFORIS_URL_PREFIX}/package-management/packages`,
|
||||
},
|
||||
|
||||
// Plugins
|
||||
storage: `${REFORIS_URL_PREFIX}/storage`,
|
||||
sentinelAgreement: `${REFORIS_URL_PREFIX}/sentinel/agreement`,
|
||||
|
||||
// Notifications links are used with <Link/> inside Router, thus url subdir is not required.
|
||||
overview: "/overview",
|
||||
@ -32,10 +29,9 @@ export const ForisURLs = {
|
||||
|
||||
approveUpdates: "/package-management/updates",
|
||||
languages: "/package-management/languages",
|
||||
maintenance: "/administration/maintenance",
|
||||
rebootPage: "/administration/reboot",
|
||||
luci: "/cgi-bin/luci",
|
||||
|
||||
// API
|
||||
about: `${REFORIS_API_URL_PREFIX}/about`,
|
||||
reboot: `${REFORIS_API_URL_PREFIX}/reboot`,
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* 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.
|
||||
|
@ -1,11 +1,9 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
const isPluginInstalled = (pluginName) =>
|
||||
export const isPluginInstalled = (pluginName) =>
|
||||
ForisPlugins.some((plugin) => plugin.name === pluginName);
|
||||
|
||||
export default isPluginInstalled;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2022 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* 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.
|
||||
@ -14,7 +14,6 @@ export const ERROR_MESSAGES = {
|
||||
IPv6: _("This is not a valid IPv6 address."),
|
||||
IPv6Prefix: _("This is not a valid IPv6 prefix."),
|
||||
domain: _("This is not a valid domain name."),
|
||||
hostname: _("This is not a valid hostname."),
|
||||
DUID: _("This is not a valid DUID."),
|
||||
MAC: _("This is not a valid MAC address."),
|
||||
MultipleEmails: _("Doesn't contain a list of emails separated by commas."),
|
||||
@ -23,15 +22,11 @@ export const ERROR_MESSAGES = {
|
||||
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]?)$/,
|
||||
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]))$/,
|
||||
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,
|
||||
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-Za-z0-9][A-Za-z0-9.-]{1,255}$/,
|
||||
DUID: /^([0-9a-fA-F]{2}){4}([0-9a-fA-F]{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) => {
|
||||
@ -45,7 +40,6 @@ const validateIPv4Address = createValidator("IPv4");
|
||||
const validateIPv6Address = createValidator("IPv6");
|
||||
const validateIPv6Prefix = createValidator("IPv6Prefix");
|
||||
const validateDomain = createValidator("domain");
|
||||
const validateHostname = createValidator("hostname");
|
||||
const validateDUID = createValidator("DUID");
|
||||
const validateMAC = createValidator("MAC");
|
||||
const validateMultipleEmails = createValidator("MultipleEmails");
|
||||
@ -55,7 +49,6 @@ export {
|
||||
validateIPv6Address,
|
||||
validateIPv6Prefix,
|
||||
validateDomain,
|
||||
validateHostname,
|
||||
validateDUID,
|
||||
validateMAC,
|
||||
validateMultipleEmails,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
* Copyright (C) 2020-2021 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.
|
||||
@ -10,16 +10,16 @@
|
||||
const PROTOCOL = window.location.protocol === "http:" ? "ws" : "wss";
|
||||
|
||||
const URL = process.env.LIGHTTPD
|
||||
? `${PROTOCOL}://${window.location.host}/${process.env.WSPATH || "foris-ws"}`
|
||||
: `${PROTOCOL}://${window.location.hostname}:9081`;
|
||||
? `${PROTOCOL}://${window.location.host}/foris-ws`
|
||||
: `${PROTOCOL}://${window.location.hostname}:${9081}`;
|
||||
|
||||
const WAITING_FOR_CONNECTION_TIMEOUT = 500;
|
||||
|
||||
class WebSockets {
|
||||
export class WebSockets {
|
||||
constructor() {
|
||||
this.ws = new WebSocket(URL);
|
||||
this.ws.onerror = (e) => {
|
||||
console.error("WS: Error:", e);
|
||||
console.error("WS: Error observed:", e);
|
||||
};
|
||||
this.ws.onmessage = (e) => {
|
||||
console.debug(`WS: Received Message: ${e.data}`);
|
||||
@ -120,5 +120,3 @@ class WebSockets {
|
||||
this.ws.close();
|
||||
}
|
||||
}
|
||||
|
||||
export default WebSockets;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* 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.
|
||||
@ -7,8 +7,7 @@
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
/* eslint-disable default-param-last */
|
||||
function useWSForisModule(
|
||||
export function useWSForisModule(
|
||||
ws,
|
||||
module,
|
||||
action = "update_settings",
|
||||
@ -42,5 +41,3 @@ function useWSForisModule(
|
||||
|
||||
return [data];
|
||||
}
|
||||
|
||||
export default useWSForisModule;
|
||||
|
@ -1,64 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2022 CZ.NIC z.s.p.o. (https://www.nic.cz/)
|
||||
* 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.
|
||||
*/
|
||||
|
||||
const path = require("path");
|
||||
const pjson = require("./package.json");
|
||||
|
||||
module.exports = {
|
||||
title: "Foris JS Docs",
|
||||
version: `v${pjson.version}`,
|
||||
theme: {
|
||||
color: {
|
||||
link: "#0075a3",
|
||||
linkHover: "#00a2e2",
|
||||
},
|
||||
},
|
||||
tocMode: "collapse",
|
||||
pagePerSection: true,
|
||||
title: "Foris JS docs",
|
||||
sections: [
|
||||
{
|
||||
name: "Introduction",
|
||||
content: "docs/introduction.md",
|
||||
name: "Foris JS",
|
||||
content: "docs/intro.md",
|
||||
},
|
||||
{
|
||||
name: "Development",
|
||||
name: "Development (Linking)",
|
||||
content: "docs/development.md",
|
||||
},
|
||||
{
|
||||
name: "Components",
|
||||
description: "Set of main components.",
|
||||
sections: [
|
||||
{
|
||||
name: "Foris forms",
|
||||
components: [
|
||||
"src/form/components/ForisForm.js",
|
||||
"src/form/components/alerts.js",
|
||||
"src/form/components/SubmitButton.js",
|
||||
],
|
||||
exampleMode: "expand",
|
||||
usageMode: "expand",
|
||||
},
|
||||
{
|
||||
name: "Alert Context",
|
||||
components: ["src/context/alertContext/AlertContext.js"],
|
||||
exampleMode: "expand",
|
||||
usageMode: "expand",
|
||||
},
|
||||
],
|
||||
sectionDepth: 1,
|
||||
},
|
||||
|
||||
{
|
||||
name: "Customization Context",
|
||||
name: "Foris forms",
|
||||
components: [
|
||||
"src/context/customizationContext/CustomizationContext.js",
|
||||
"src/form/components/ForisForm.js",
|
||||
"src/form/components/alerts.js",
|
||||
"src/form/components/SubmitButton.js",
|
||||
],
|
||||
exampleMode: "expand",
|
||||
usageMode: "expand",
|
||||
},
|
||||
{
|
||||
name: "Alert Context",
|
||||
components: ["src/alertContext/AlertContext.js"],
|
||||
exampleMode: "expand",
|
||||
usageMode: "expand",
|
||||
},
|
||||
{
|
||||
name: "Bootstrap components",
|
||||
description: "Set of bootstrap components.",
|
||||
@ -66,12 +41,8 @@ module.exports = {
|
||||
exampleMode: "expand",
|
||||
usageMode: "expand",
|
||||
ignore: ["src/bootstrap/constants.js"],
|
||||
sectionDepth: 0,
|
||||
},
|
||||
],
|
||||
template: {
|
||||
favicon: "/docs/components/logo.svg",
|
||||
},
|
||||
require: [
|
||||
"babel-polyfill",
|
||||
path.join(__dirname, "src/testUtils/mockGlobals"),
|
||||
@ -84,9 +55,6 @@ module.exports = {
|
||||
"node_modules/@fortawesome/fontawesome-free/css/all.min.css"
|
||||
),
|
||||
],
|
||||
styleguideComponents: {
|
||||
LogoRenderer: path.join(__dirname, "docs/components/Logo"),
|
||||
},
|
||||
webpackConfig: {
|
||||
module: {
|
||||
rules: [
|
||||
|
@ -1,14 +1,14 @@
|
||||
# Czech translations for Foris JS.
|
||||
# Copyright (C) 2022 CZ.NIC, z.s.p.o. (https://www.nic.cz/)
|
||||
# This file is distributed under the same license as the Foris JS project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
# Czech translations for PROJECT.
|
||||
# Copyright (C) 2019 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2019.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2022-12-02 15:54+0100\n"
|
||||
"PO-Revision-Date: 2023-11-23 16:03+0000\n"
|
||||
"POT-Creation-Date: 2021-01-28 11:42+0100\n"
|
||||
"PO-Revision-Date: 2021-02-17 14:50+0000\n"
|
||||
"Last-Translator: Lukas Jelinek <lukas.jelinek@nic.cz>\n"
|
||||
"Language-Team: Czech <https://hosted.weblate.org/projects/turris/foris-js/cs/"
|
||||
">\n"
|
||||
@ -17,33 +17,25 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 5.2.1-rc\n"
|
||||
"Generated-By: Babel 2.11.0\n"
|
||||
"X-Generator: Weblate 4.5\n"
|
||||
"Generated-By: Babel 2.9.0\n"
|
||||
|
||||
#: src/api/utils.js:61
|
||||
#: src/api/utils.js:60
|
||||
msgid "The session is expired. Please log in again."
|
||||
msgstr "Platnost relace skončila. Přihlaste se znovu."
|
||||
|
||||
#: src/api/utils.js:66
|
||||
#: src/api/utils.js:65
|
||||
msgid "Timeout error occurred."
|
||||
msgstr "Došlo k chybě kvůli překročení časového limitu."
|
||||
|
||||
#: src/api/utils.js:69
|
||||
#: src/api/utils.js:68
|
||||
msgid "No response received."
|
||||
msgstr "Neobdržena žádná odezva."
|
||||
|
||||
#: src/api/utils.js:79
|
||||
#: src/api/utils.js:78
|
||||
msgid "An unknown API error occurred."
|
||||
msgstr "Došlo k neznámé chybě v aplikačním programovém rozhraní."
|
||||
|
||||
#: src/bootstrap/CopyInput.js:55
|
||||
msgid "Copied!"
|
||||
msgstr "Zkopírováno!"
|
||||
|
||||
#: src/bootstrap/CopyInput.js:55
|
||||
msgid "Copy"
|
||||
msgstr "Kopírovat"
|
||||
|
||||
#: src/common/RebootButton.js:27
|
||||
msgid "Reboot request failed."
|
||||
msgstr "Vyžadován restart."
|
||||
@ -62,7 +54,7 @@ msgstr "Opravdu chcete router restartovat?"
|
||||
|
||||
#: src/common/RebootButton.js:71
|
||||
msgid "Cancel"
|
||||
msgstr "Zrušit"
|
||||
msgstr "Storno"
|
||||
|
||||
#: src/common/RebootButton.js:73
|
||||
msgid "Confirm reboot"
|
||||
@ -77,69 +69,40 @@ msgid "Wi-Fi settings are set to defaults."
|
||||
msgstr "Nastavení Wi-Fi jsou uvedena do výchozího stavu."
|
||||
|
||||
#: src/common/WiFiSettings/ResetWiFiSettings.js:55
|
||||
#: src/common/WiFiSettings/ResetWiFiSettings.js:69
|
||||
#: src/common/WiFiSettings/ResetWiFiSettings.js:70
|
||||
msgid "Reset Wi-Fi Settings"
|
||||
msgstr "Reset nastavení Wi-Fi"
|
||||
msgstr "Resetovat nastavení Wi-Fi"
|
||||
|
||||
#: src/common/WiFiSettings/ResetWiFiSettings.js:57
|
||||
msgid ""
|
||||
"\n"
|
||||
"If a number of wireless cards doesn't match, you may try to reset the Wi-"
|
||||
"Fi settings. Note that this will remove the current Wi-Fi configuration "
|
||||
"and restore the default values."
|
||||
"Fi settings. Note that this will remove the\n"
|
||||
"current Wi-Fi configuration and restore the default values.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"Pokud se počet bezdrátových karet neshoduje, můžete zkusit obnovit nastavení "
|
||||
"Wi-Fi. Je třeba upozornit, že se tím odstraní aktuální konfigurace Wi-Fi a "
|
||||
"obnoví se výchozí hodnoty."
|
||||
"\n"
|
||||
"Pokud počet karet pro Wi-Fi neodpovídá skutečnosti, můžete zkusit resetovat "
|
||||
"nastavení Wi-Fi. Nezapomeňte ale, že\n"
|
||||
"se tím odstraní aktuální konfigurace a vrátí se výchozí hodnoty.\n"
|
||||
" "
|
||||
|
||||
#: src/common/WiFiSettings/WiFiForm.js:95
|
||||
#: src/common/WiFiSettings/WiFiForm.js:92
|
||||
msgid "Wi-Fi ${deviceID + 1}"
|
||||
msgstr "Wi-Fi ${deviceID + 1}"
|
||||
|
||||
#: src/common/WiFiSettings/WiFiForm.js:132
|
||||
#: src/common/WiFiSettings/WiFiGuestForm.js:80
|
||||
msgid "Password"
|
||||
msgstr "Heslo"
|
||||
|
||||
#: src/common/WiFiSettings/WiFiForm.js:146
|
||||
msgid "Hide SSID"
|
||||
msgstr "Skrýt SSID"
|
||||
|
||||
#: src/common/WiFiSettings/WiFiForm.js:186
|
||||
msgid "802.11n/ac/ax mode"
|
||||
msgstr "Režim 802.11n/ac/ax"
|
||||
|
||||
#: src/common/WiFiSettings/WiFiForm.js:199
|
||||
msgid "Channel"
|
||||
msgstr "Kanál"
|
||||
|
||||
#: src/common/WiFiSettings/WiFiForm.js:211
|
||||
msgid "Encryption"
|
||||
msgstr "Šifrování"
|
||||
|
||||
#: src/common/WiFiSettings/WiFiForm.js:226
|
||||
msgid "Disable Management Frame Protection"
|
||||
msgstr "Vypnout Management Frame Protection"
|
||||
|
||||
#: src/common/WiFiSettings/WiFiForm.js:227
|
||||
msgid ""
|
||||
"In case you have trouble connecting to WiFi Access Point, try disabling "
|
||||
"Management Frame Protection."
|
||||
msgstr ""
|
||||
"Máte-li problémy při připojování k přístupovému bodu Wi-Fi, zkuste vypnout "
|
||||
"Management Frame Protection."
|
||||
|
||||
#: src/common/WiFiSettings/WiFiForm.js:262
|
||||
#: src/common/WiFiSettings/WiFiForm.js:217
|
||||
msgid "auto"
|
||||
msgstr "automaticky"
|
||||
|
||||
#: src/common/WiFiSettings/WiFiForm.js:303
|
||||
msgid "Custom"
|
||||
msgstr "Uživatelsky určené"
|
||||
|
||||
#: src/common/WiFiSettings/WiFiGuestForm.js:42
|
||||
msgid "Enable Guest Wi-Fi"
|
||||
msgstr "Zapnout Wi-Fi pro hosty"
|
||||
|
||||
#: src/common/WiFiSettings/WiFiGuestForm.js:80
|
||||
msgid "Password"
|
||||
msgstr "Heslo"
|
||||
|
||||
#: src/common/WiFiSettings/WiFiQRCode.js:71
|
||||
msgid "Wi-Fi QR Code"
|
||||
msgstr "Wi-Fi QR kód"
|
||||
@ -148,31 +111,26 @@ msgstr "Wi-Fi QR kód"
|
||||
msgid "Download PDF"
|
||||
msgstr "Stáhnout PDF"
|
||||
|
||||
#: src/common/WiFiSettings/WiFiSettings.js:82
|
||||
#: src/common/WiFiSettings/WiFiSettings.js:98
|
||||
#: src/common/WiFiSettings/WiFiSettings.js:78
|
||||
#: src/common/WiFiSettings/WiFiSettings.js:90
|
||||
msgid "SSID can't be longer than 32 symbols"
|
||||
msgstr "SSID nemůže být delší než 32 znaků"
|
||||
|
||||
#: src/common/WiFiSettings/WiFiSettings.js:83
|
||||
#: src/common/WiFiSettings/WiFiSettings.js:100
|
||||
#: src/common/WiFiSettings/WiFiSettings.js:79
|
||||
#: src/common/WiFiSettings/WiFiSettings.js:92
|
||||
msgid "SSID can't be empty"
|
||||
msgstr "SSID je třeba vyplnit"
|
||||
|
||||
#: src/common/WiFiSettings/WiFiSettings.js:85
|
||||
#: src/common/WiFiSettings/WiFiSettings.js:102
|
||||
#: src/common/WiFiSettings/WiFiSettings.js:81
|
||||
#: src/common/WiFiSettings/WiFiSettings.js:94
|
||||
msgid "SSID can't be longer than 32 bytes"
|
||||
msgstr "SSID nemůže být delší než 32 bajtů"
|
||||
|
||||
#: src/common/WiFiSettings/WiFiSettings.js:88
|
||||
#: src/common/WiFiSettings/WiFiSettings.js:105
|
||||
#: src/common/WiFiSettings/WiFiSettings.js:84
|
||||
#: src/common/WiFiSettings/WiFiSettings.js:97
|
||||
msgid "Password must contain at least 8 symbols"
|
||||
msgstr "Je třeba, aby heslo obsahovalo alespoň 8 znaků"
|
||||
|
||||
#: src/common/WiFiSettings/WiFiSettings.js:90
|
||||
#: src/common/WiFiSettings/WiFiSettings.js:109
|
||||
msgid "Password must not contain more than 63 symbols"
|
||||
msgstr "Heslo nesmí obsahovat více než 63 znaků"
|
||||
|
||||
#: src/common/WiFiSettings/constants.js:9
|
||||
msgid "Disabled"
|
||||
msgstr "Vypnuto"
|
||||
@ -201,35 +159,7 @@ msgstr "802.11ac – kanál šíře 80 MHz"
|
||||
msgid "802.11ac - 160 MHz wide channel"
|
||||
msgstr "802.11ac – kanál šíře 160 MHz"
|
||||
|
||||
#: src/common/WiFiSettings/constants.js:16
|
||||
msgid "802.11ax - 20 MHz wide channel"
|
||||
msgstr "802.11ax – kanál šíře 20 MHz"
|
||||
|
||||
#: src/common/WiFiSettings/constants.js:17
|
||||
msgid "802.11ax - 40 MHz wide channel"
|
||||
msgstr "802.11ax – kanál šíře 40 MHz"
|
||||
|
||||
#: src/common/WiFiSettings/constants.js:18
|
||||
msgid "802.11ax - 80 MHz wide channel"
|
||||
msgstr "802.11ax – kanál šíře 80 MHz"
|
||||
|
||||
#: src/common/WiFiSettings/constants.js:19
|
||||
msgid "802.11ax - 160 MHz wide channel"
|
||||
msgstr "802.11ax – kanál šíře 160 MHz"
|
||||
|
||||
#: src/common/WiFiSettings/constants.js:26
|
||||
msgid "WPA3 only"
|
||||
msgstr "pouze WPA3"
|
||||
|
||||
#: src/common/WiFiSettings/constants.js:27
|
||||
msgid "WPA3 with WPA2 as fallback (default)"
|
||||
msgstr "WPA3, nouzově WPA2 (výchozí)"
|
||||
|
||||
#: src/common/WiFiSettings/constants.js:28
|
||||
msgid "WPA2 only"
|
||||
msgstr "pouze WPA2"
|
||||
|
||||
#: src/common/WiFiSettings/constants.js:31
|
||||
#: src/common/WiFiSettings/constants.js:22
|
||||
msgid ""
|
||||
"SSID which contains non-standard characters could cause problems on some "
|
||||
"devices."
|
||||
@ -237,63 +167,76 @@ msgstr ""
|
||||
"SSID obsahující nestandardní znaky může na některých zařízení způsobovat "
|
||||
"problémy."
|
||||
|
||||
#: src/common/WiFiSettings/constants.js:34
|
||||
msgid "WPA2/3 pre-shared key, that is required to connect to the network."
|
||||
msgstr "Předsdílený klíč WPA2/3, který je vyžadován pro připojení se k síti."
|
||||
#: src/common/WiFiSettings/constants.js:25
|
||||
msgid ""
|
||||
"\n"
|
||||
" WPA2 pre-shared key, that is required to connect to the network.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" WPA2 předsdílený klíč, který je vyžadován pro připojení se k "
|
||||
"síti.\n"
|
||||
" "
|
||||
|
||||
#: src/common/WiFiSettings/constants.js:37
|
||||
#: src/common/WiFiSettings/constants.js:28
|
||||
msgid "If set, network is not visible when scanning for available networks."
|
||||
msgstr ""
|
||||
"Při zapnutí této volby se síť nebude zobrazovat zařízením když budou "
|
||||
"vyhledávat dostupné sítě."
|
||||
|
||||
#: src/common/WiFiSettings/constants.js:31
|
||||
msgid ""
|
||||
"\n"
|
||||
" The 2.4 GHz band is more widely supported by clients, but tends "
|
||||
"to have more interference. The 5 GHz band is a\n"
|
||||
" newer standard and may not be supported by all your devices. It "
|
||||
"usually has less interference, but the signal\n"
|
||||
" does not carry so well indoors."
|
||||
msgstr ""
|
||||
"\n"
|
||||
" Pásmo 2,4 GHz je v klientských zařízeních podporováno nejčastěji,"
|
||||
" ale bývá více zarušené. Pásmo 5 GHz je\n"
|
||||
" novější standard a nemusí být podporováno všemi vámi používanými "
|
||||
"zařízeními. Obvykle bývá méně zarušené,\n"
|
||||
" ale signál se hůře šíři uvnitř budov."
|
||||
|
||||
#: src/common/WiFiSettings/constants.js:35
|
||||
msgid ""
|
||||
"\n"
|
||||
" Change this to adjust 802.11n/ac mode of operation. 802.11n with "
|
||||
"40 MHz wide channels can yield higher\n"
|
||||
" throughput but can cause more interference in the network. If you"
|
||||
" don't know what to choose, use the default\n"
|
||||
" option with 20 MHz wide channel.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" Změna tohoto upraví režim fungování 802.11n/ac. 802.11n s kanály "
|
||||
"o šíři 40 MHz kanály může pomoci k vyšší\n"
|
||||
" propustnosti, ale je náchylnější na rušení. Pokud nevíte co "
|
||||
"zvolit, použijte výchozí volbu s kanálem šíře\n"
|
||||
" 20 MHz.\n"
|
||||
" "
|
||||
|
||||
#: src/common/WiFiSettings/constants.js:40
|
||||
msgid ""
|
||||
"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."
|
||||
"\n"
|
||||
" Enables Wi-Fi for guests, which is separated from LAN network. "
|
||||
"Devices connected to this network are allowed to\n"
|
||||
" access the internet, but aren't allowed to access other devices "
|
||||
"and the configuration interface of the router.\n"
|
||||
" Parameters of the guest network can be set in the Guest network "
|
||||
"tab.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"Pásmo 2,4 GHz je v klientských zařízeních podporováno nejčastěji, bývá ale "
|
||||
"více zarušené. Pásmo 5 GHz je novější standard a nemusí být podporováno "
|
||||
"všemi vámi používanými zařízeními. Obvykle bývá méně zarušené, signál se ale "
|
||||
"hůře šíří uvnitř budov."
|
||||
|
||||
#: src/common/WiFiSettings/constants.js:43
|
||||
msgid ""
|
||||
"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."
|
||||
msgstr ""
|
||||
"Změna tohoto parametru upraví režim fungování 802.11n/ac. 802.11n s kanály o "
|
||||
"šíři 40 MHz může pomoci k vyšší propustnosti, je ale náchylnější na rušení. "
|
||||
"Pokud nevíte co zvolit, použijte výchozí volbu s kanálem šíře 20 MHz."
|
||||
|
||||
#: src/common/WiFiSettings/constants.js:46
|
||||
msgid ""
|
||||
"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."
|
||||
msgstr ""
|
||||
"Zapíná Wi-Fi pro hosty, která je oddělená od místní sítě (LAN). Zařízením "
|
||||
"připojeným k této síti je umožněn přístup do Internetu, ale už ne na ostatní "
|
||||
"zařízení a k rozhraní pro nastavování směrovače. Parametry sítě pro hosty je "
|
||||
"možné nastavit na panelu „Síť pro hosty“."
|
||||
|
||||
#: src/common/WiFiSettings/constants.js:49
|
||||
msgid ""
|
||||
"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."
|
||||
msgstr ""
|
||||
"Standard WPA3 je nová nejbezpečnější metoda, již se doporučuje používat se "
|
||||
"všemi zařízeními, která ji podporují. Starší zařízení bez podpory WPA3 "
|
||||
"potřebují starší WPA2. Zaznamenáte-li problémy s připojováním starších "
|
||||
"zařízení, zkuste zapnout WPA2."
|
||||
"\n"
|
||||
" Zapíná Wi-Fi pro hosty, která je oddělená od místní sítě (LAN). "
|
||||
"Zařízením připojeným k této síti je umožněn\n"
|
||||
" přístup do Internetu, ale už ne na ostatní zařízení a k rozhraní "
|
||||
"pro nastavování směrovače.\n"
|
||||
" Parametry sítě pro hosty je možné nastavit na panelu „Síť pro "
|
||||
"hosty“.\n"
|
||||
" "
|
||||
|
||||
#: src/form/components/ForisForm.js:121
|
||||
msgid "Settings saved successfully"
|
||||
@ -338,18 +281,14 @@ msgid "This is not a valid domain name."
|
||||
msgstr "Toto není platné doménové jméno."
|
||||
|
||||
#: src/utils/validations.js:17
|
||||
msgid "This is not a valid hostname."
|
||||
msgstr "Toto není platné doménové jméno."
|
||||
|
||||
#: src/utils/validations.js:18
|
||||
msgid "This is not a valid DUID."
|
||||
msgstr "Tohle není platné DUID."
|
||||
|
||||
#: src/utils/validations.js:19
|
||||
#: src/utils/validations.js:18
|
||||
msgid "This is not a valid MAC address."
|
||||
msgstr "Toto není platná MAC adresa."
|
||||
|
||||
#: src/utils/validations.js:20
|
||||
#: src/utils/validations.js:19
|
||||
msgid "Doesn't contain a list of emails separated by commas."
|
||||
msgstr "Neobsahuje seznam e-mailů oddělených čárkou."
|
||||
|
||||
@ -361,20 +300,3 @@ msgstr "Neobsahuje seznam e-mailů oddělených čárkou."
|
||||
|
||||
#~ msgid "Enable"
|
||||
#~ msgstr "Zapnout"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "\n"
|
||||
#~ "If a number of wireless cards "
|
||||
#~ "doesn't match, you may try to "
|
||||
#~ "reset the Wi-Fi settings. Note "
|
||||
#~ "that this will remove the\n"
|
||||
#~ "current Wi-Fi configuration and restore the default values.\n"
|
||||
#~ " "
|
||||
#~ msgstr ""
|
||||
#~ "\n"
|
||||
#~ "Pokud počet karet pro Wi-Fi "
|
||||
#~ "neodpovídá skutečnosti, můžete zkusit "
|
||||
#~ "resetovat nastavení Wi-Fi. Nezapomeňte "
|
||||
#~ "ale, že\n"
|
||||
#~ "se tím odstraní aktuální konfigurace a vrátí se výchozí hodnoty.\n"
|
||||
#~ " "
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user