Commit d8ba0b51 authored by Bogdan Bodnar's avatar Bogdan Bodnar

Merge branch 'notifications-settings' into 'dev'

Notifications settings

Closes #17

See merge request !2
parents 6c6d8ee4 dec8c6a3
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
.PHONY: all install run run-js test test-web clean .PHONY: all install run run-js test test-web clean
SHELL=/bin/bash SHELL=/bin/bash
PYTHON=python3.7 PYTHON=python3.6
FLASK=flask FLASK=flask
VENV_NAME?=venv VENV_NAME?=venv
...@@ -45,6 +45,10 @@ install-js: js/package.json ...@@ -45,6 +45,10 @@ install-js: js/package.json
run: run:
${FLASK} run --host="0.0.0.0" --port=81 ${FLASK} run --host="0.0.0.0" --port=81
run-ws:
foris-ws --host "0.0.0.0" --port 9081 -a filesystem -d mqtt --mqtt-host localhost --mqtt-port 11883 \
--mqtt-passwd-file '/etc/fosquitto/credentials.plain';
watch-js: watch-js:
cd ${JS_DIR};\ cd ${JS_DIR};\
npx watchify ./src/app.js -o ../reforis/static/js/app.min.js \ npx watchify ./src/app.js -o ../reforis/static/js/app.min.js \
......
...@@ -8,11 +8,11 @@ ...@@ -8,11 +8,11 @@
import React from 'react'; import React from 'react';
import {render} from 'react-dom'; import {render} from 'react-dom';
import NotificationsDropdown from './notifications/NotificationsDropdown/NotificationsDropdown';
import NotificationsCenter from './notifications/NotificationsCenter/NotificationsCenter';
import WiFi from './wifi/WiFi'; import WiFi from './wifi/WiFi';
import WAN from './wan/WAN'; import WAN from './wan/WAN';
import LAN from './lan/LAN'; import LAN from './lan/LAN';
import NotificationsDropdown from './notifications/NotificationsDropdown';
import NotificationsCenter from './notifications/NotificationsCenter';
import ConnectionTest from './connectionTest/ConnectionTest'; import ConnectionTest from './connectionTest/ConnectionTest';
import webSockets from './webSockets'; import webSockets from './webSockets';
......
/*
* 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 Input from './Input';
import PropTypes from 'prop-types';
const EmailInput = Input('email');
EmailInput.propTypes = {
label: PropTypes.string.isRequired,
error: PropTypes.string,
helpText: PropTypes.string,
value: PropTypes.string,
};
export default EmailInput;
...@@ -5,7 +5,7 @@ exports[`<Checkbox/> Render checkbox 1`] = ` ...@@ -5,7 +5,7 @@ exports[`<Checkbox/> Render checkbox 1`] = `
class="form-group row" class="form-group row"
> >
<div <div
class="form-label col-sm-2" class="form-label col-sm-3"
> >
<label <label
class="form-label" class="form-label"
...@@ -15,7 +15,7 @@ exports[`<Checkbox/> Render checkbox 1`] = ` ...@@ -15,7 +15,7 @@ exports[`<Checkbox/> Render checkbox 1`] = `
</label> </label>
</div> </div>
<div <div
class="form-check col-sm-9" class="form-check col-sm-8"
> >
<input <input
checked="" checked=""
...@@ -36,7 +36,7 @@ exports[`<Checkbox/> Render uncheked checkbox 1`] = ` ...@@ -36,7 +36,7 @@ exports[`<Checkbox/> Render uncheked checkbox 1`] = `
class="form-group row" class="form-group row"
> >
<div <div
class="form-label col-sm-2" class="form-label col-sm-3"
> >
<label <label
class="form-label" class="form-label"
...@@ -46,7 +46,7 @@ exports[`<Checkbox/> Render uncheked checkbox 1`] = ` ...@@ -46,7 +46,7 @@ exports[`<Checkbox/> Render uncheked checkbox 1`] = `
</label> </label>
</div> </div>
<div <div
class="form-check col-sm-9" class="form-check col-sm-8"
> >
<input <input
id="2" id="2"
......
...@@ -5,13 +5,13 @@ exports[`<PasswordInput/> Render number input 1`] = ` ...@@ -5,13 +5,13 @@ exports[`<PasswordInput/> Render number input 1`] = `
class="form-group row" class="form-group row"
> >
<label <label
class="form-control-label col-sm-2" class="form-control-label col-sm-3"
for="1" for="1"
> >
Test label Test label
</label> </label>
<div <div
class="col-sm-9" class="col-sm-8"
> >
<input <input
class="form-control " class="form-control "
......
...@@ -5,13 +5,13 @@ exports[`<PasswordInput/> Render password input 1`] = ` ...@@ -5,13 +5,13 @@ exports[`<PasswordInput/> Render password input 1`] = `
class="form-group row" class="form-group row"
> >
<label <label
class="form-control-label col-sm-2" class="form-control-label col-sm-3"
for="1" for="1"
> >
Test label Test label
</label> </label>
<div <div
class="col-sm-9" class="col-sm-8"
> >
<input <input
class="form-control " class="form-control "
......
...@@ -6,7 +6,7 @@ exports[`<RadioSet/> Render radio set 1`] = ` ...@@ -6,7 +6,7 @@ exports[`<RadioSet/> Render radio set 1`] = `
id="1" id="1"
> >
<div <div
class="form-label col-sm-2" class="form-label col-sm-3"
> >
<label <label
class="form-label" class="form-label"
...@@ -16,7 +16,7 @@ exports[`<RadioSet/> Render radio set 1`] = ` ...@@ -16,7 +16,7 @@ exports[`<RadioSet/> Render radio set 1`] = `
</label> </label>
</div> </div>
<div <div
class="col-sm-9" class="col-sm-8"
> >
<div <div
class="form-check form-check-inline" class="form-check form-check-inline"
......
...@@ -5,13 +5,13 @@ exports[`<Select/> Render select 1`] = ` ...@@ -5,13 +5,13 @@ exports[`<Select/> Render select 1`] = `
class="form-group row" class="form-group row"
> >
<label <label
class="form-control-label col-sm-2" class="form-control-label col-sm-3"
for="1" for="1"
> >
Test label Test label
</label> </label>
<div <div
class="col-sm-9" class="col-sm-8"
> >
<select <select
class="form-control" class="form-control"
......
...@@ -5,13 +5,13 @@ exports[`<TextInput/> Render text input 1`] = ` ...@@ -5,13 +5,13 @@ exports[`<TextInput/> Render text input 1`] = `
class="form-group row" class="form-group row"
> >
<label <label
class="form-control-label col-sm-2" class="form-control-label col-sm-3"
for="1" for="1"
> >
Test label Test label
</label> </label>
<div <div
class="col-sm-9" class="col-sm-8"
> >
<input <input
class="form-control " class="form-control "
......
...@@ -5,5 +5,5 @@ ...@@ -5,5 +5,5 @@
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
export const LABEL_SIZE = 2; export const LABEL_SIZE = 3;
export const FIELD_SIZE = 9; export const FIELD_SIZE = 8;
...@@ -10,6 +10,7 @@ import API from './utils'; ...@@ -10,6 +10,7 @@ import API from './utils';
const API_URL = '/api'; const API_URL = '/api';
const ENDPOINTS = [ const ENDPOINTS = [
{name: 'notifications', url: '/notifications', methods: ['get', 'post']}, {name: 'notifications', url: '/notifications', methods: ['get', 'post']},
{name: 'router_notifications', url: '/notifications-settings', methods: ['get', 'post']},
{name: 'wifi', url: '/wifi', methods: ['get', 'post']}, {name: 'wifi', url: '/wifi', methods: ['get', 'post']},
{name: 'wan', url: '/wan', methods: ['get', 'post']}, {name: 'wan', url: '/wan', methods: ['get', 'post']},
{name: 'lan', url: '/lan', methods: ['get', 'post']}, {name: 'lan', url: '/lan', methods: ['get', 'post']},
......
...@@ -20,7 +20,7 @@ ForisForm.propTypes = { ...@@ -20,7 +20,7 @@ ForisForm.propTypes = {
children: propTypes.node.isRequired, children: propTypes.node.isRequired,
}; };
export default function ForisForm({ws, module, prepData, prepDataToSubmit, validator, children}) { export default function ForisForm({ws, module, prepData, prepDataToSubmit, validator, anotherWSLogic, children}) {
const [ const [
formData, formData,
formErrors, formErrors,
...@@ -30,7 +30,7 @@ export default function ForisForm({ws, module, prepData, prepDataToSubmit, valid ...@@ -30,7 +30,7 @@ export default function ForisForm({ws, module, prepData, prepDataToSubmit, valid
setFormValue, setFormValue,
onSubmit, onSubmit,
] = useForisForm(ws, module, prepData, prepDataToSubmit, validator); ] = useForisForm(ws, module, prepData, prepDataToSubmit, validator, anotherWSLogic);
if (JSON.stringify(formData) === '{}') if (JSON.stringify(formData) === '{}')
return null; return null;
......
...@@ -56,12 +56,14 @@ function getChangedValue(target) { ...@@ -56,12 +56,14 @@ function getChangedValue(target) {
let value = target.value; let value = target.value;
if (target.type === 'checkbox') if (target.type === 'checkbox')
value = target.checked; value = target.checked;
else if (target.type === 'number') else if (target.type === 'number') {
value = parseInt(value); const parsedValue = parseInt(value);
value = isNaN(parsedValue) ? value : parsedValue;
}
return value return value
} }
function useForisFormWS(ws, loadFormData, setFormState) { function useForisFormWS(ws, module, loadFormData, setFormState) {
const [remindsToNWRestart, setRemindsToNWRestart] = useState(null); const [remindsToNWRestart, setRemindsToNWRestart] = useState(null);
useEffect(() => { useEffect(() => {
...@@ -81,7 +83,7 @@ function useForisFormWS(ws, loadFormData, setFormState) { ...@@ -81,7 +83,7 @@ function useForisFormWS(ws, loadFormData, setFormState) {
return remindsToNWRestart return remindsToNWRestart
} }
export function useForisForm(ws, module, prepData, prepDataToSubmit, validator) { export function useForisForm(ws, module, prepData, prepDataToSubmit, validator, anotherWSLogic) {
const [ const [
formData, formData,
formErrors, formErrors,
...@@ -97,10 +99,17 @@ export function useForisForm(ws, module, prepData, prepDataToSubmit, validator) ...@@ -97,10 +99,17 @@ export function useForisForm(ws, module, prepData, prepDataToSubmit, validator)
useEffect(() => loadFormData(), []); useEffect(() => loadFormData(), []);
useEffect(() => setFormState(isReady ? FORM_STATES.READY : FORM_STATES.LOAD), [isReady,]); useEffect(() => setFormState(isReady ? FORM_STATES.READY : FORM_STATES.LOAD), [isReady,]);
const remindsToNWRestart = useForisFormWS(ws, loadFormData, setFormState); const remindsToNWRestart = useForisFormWS(ws, module, loadFormData, setFormState);
const postData = useAPIPostData(module); const postData = useAPIPostData(module);
// It's useful when the module has different update logic (see notifications email setting.)
// If there will be more module with the same logic then it can be split into a few hooks.
useEffect(() => {
if (anotherWSLogic)
anotherWSLogic(setFormState, loadFormData)
}, []);
function onSubmit(e) { function onSubmit(e) {
e.preventDefault(); e.preventDefault();
setFormState(FORM_STATES.UPDATE); setFormState(FORM_STATES.UPDATE);
......
...@@ -12,6 +12,7 @@ export const ERROR_MESSAGES = { ...@@ -12,6 +12,7 @@ export const ERROR_MESSAGES = {
domain: _('This is not a valid domain name.'), domain: _('This is not a valid domain name.'),
DUID: _('This is not a valid DUID.'), DUID: _('This is not a valid DUID.'),
MAC: _('This is not a valid MAC address.'), MAC: _('This is not a valid MAC address.'),
MultipleEmails: _("Doesn't contain a list of emails separated by commas."),
}; };
const REs = { const REs = {
...@@ -21,6 +22,7 @@ const REs = { ...@@ -21,6 +22,7 @@ const REs = {
domain: /^([a-zA-Z0-9-]{1,63}\.?)*$/, domain: /^([a-zA-Z0-9-]{1,63}\.?)*$/,
DUID: /^([0-9a-fA-F]{2}){4}([0-9a-fA-F]{2})*$/, DUID: /^([0-9a-fA-F]{2}){4}([0-9a-fA-F]{2})*$/,
MAC: /^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$/, MAC: /^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$/,
MultipleEmails: /^([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+ *)( *, *[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+ *)*$/,
}; };
...@@ -36,4 +38,5 @@ module.exports = { ...@@ -36,4 +38,5 @@ module.exports = {
validateDomain: createValidator('domain'), validateDomain: createValidator('domain'),
validateDUID: createValidator('DUID'), validateDUID: createValidator('DUID'),
validateMAC: createValidator('MAC'), validateMAC: createValidator('MAC'),
validateMultipleEmails: createValidator('MultipleEmails'),
}; };
\ No newline at end of file
...@@ -9,13 +9,13 @@ exports[`<LAN/> Snapshot managed with enabled DHCP. 1`] = ` ...@@ -9,13 +9,13 @@ exports[`<LAN/> Snapshot managed with enabled DHCP. 1`] = `
class="form-group row" class="form-group row"
> >
<label <label
class="form-control-label col-sm-2" class="form-control-label col-sm-3"
for="62" for="62"
> >
LAN mode LAN mode
</label> </label>
<div <div
class="col-sm-9" class="col-sm-8"
> >
<select <select
class="form-control" class="form-control"
...@@ -43,13 +43,13 @@ exports[`<LAN/> Snapshot managed with enabled DHCP. 1`] = ` ...@@ -43,13 +43,13 @@ exports[`<LAN/> Snapshot managed with enabled DHCP. 1`] = `
class="form-group row" class="form-group row"
> >
<label <label
class="form-control-label col-sm-2" class="form-control-label col-sm-3"
for="75" for="75"
> >
Router IP address Router IP address
</label> </label>
<div <div
class="col-sm-9" class="col-sm-8"
> >
<input <input
class="form-control " class="form-control "
...@@ -72,13 +72,13 @@ exports[`<LAN/> Snapshot managed with enabled DHCP. 1`] = ` ...@@ -72,13 +72,13 @@ exports[`<LAN/> Snapshot managed with enabled DHCP. 1`] = `
class="form-group row" class="form-group row"
> >
<label <label
class="form-control-label col-sm-2" class="form-control-label col-sm-3"
for="76" for="76"
> >
Network mask Network mask
</label> </label>
<div <div
class="col-sm-9" class="col-sm-8"
> >
<input <input
class="form-control " class="form-control "
...@@ -99,7 +99,7 @@ exports[`<LAN/> Snapshot managed with enabled DHCP. 1`] = ` ...@@ -99,7 +99,7 @@ exports[`<LAN/> Snapshot managed with enabled DHCP. 1`] = `
class="form-group row" class="form-group row"
> >
<div <div
class="form-label col-sm-2" class="form-label col-sm-3"
> >
<label <label
class="form-label" class="form-label"
...@@ -109,7 +109,7 @@ exports[`<LAN/> Snapshot managed with enabled DHCP. 1`] = ` ...@@ -109,7 +109,7 @@ exports[`<LAN/> Snapshot managed with enabled DHCP. 1`] = `
</label> </label>
</div> </div>
<div <div
class="form-check col-sm-9" class="form-check col-sm-8"
> >
<input <input
id="77" id="77"
...@@ -126,13 +126,13 @@ exports[`<LAN/> Snapshot managed with enabled DHCP. 1`] = ` ...@@ -126,13 +126,13 @@ exports[`<LAN/> Snapshot managed with enabled DHCP. 1`] = `
class="form-group row" class="form-group row"
> >
<label <label
class="form-control-label col-sm-2" class="form-control-label col-sm-3"
for="82" for="82"
> >
DHCP start DHCP start
</label> </label>
<div <div
class="col-sm-9" class="col-sm-8"
> >
<input <input
class="form-control " class="form-control "
...@@ -154,13 +154,13 @@ exports[`<LAN/> Snapshot managed with enabled DHCP. 1`] = ` ...@@ -154,13 +154,13 @@ exports[`<LAN/> Snapshot managed with enabled DHCP. 1`] = `
class="form-group row" class="form-group row"
> >
<label <label
class="form-control-label col-sm-2" class="form-control-label col-sm-3"
for="83" for="83"
> >
DHCP max leases DHCP max leases
</label> </label>
<div <div
class="col-sm-9" class="col-sm-8"
> >
<input <input
class="form-control " class="form-control "
...@@ -182,13 +182,13 @@ exports[`<LAN/> Snapshot managed with enabled DHCP. 1`] = ` ...@@ -182,13 +182,13 @@ exports[`<LAN/> Snapshot managed with enabled DHCP. 1`] = `
class="form-group row" class="form-group row"
> >
<label <label
class="form-control-label col-sm-2" class="form-control-label col-sm-3"
for="84" for="84"
> >
Lease time (hours) Lease time (hours)
</label> </label>
<div <div
class="col-sm-9" class="col-sm-8"
> >
<input <input
class="form-control " class="form-control "
...@@ -225,13 +225,13 @@ exports[`<LAN/> Snapshot managed. 1`] = ` ...@@ -225,13 +225,13 @@ exports[`<LAN/> Snapshot managed. 1`] = `
class="form-group row" class="form-group row"
> >
<label <label
class="form-control-label col-sm-2" class="form-control-label col-sm-3"
for="46" for="46"
> >
LAN mode LAN mode
</label> </label>
<div <div
class="col-sm-9" class="col-sm-8"
> >
<select <select
class="form-control" class="form-control"
...@@ -259,13 +259,13 @@ exports[`<LAN/> Snapshot managed. 1`] = ` ...@@ -259,13 +259,13 @@ exports[`<LAN/> Snapshot managed. 1`] = `
class="form-group row" class="form-group row"
> >
<label <label
class="form-control-label col-sm-2" class="form-control-label col-sm-3"
for="59" for="59"
> >
Router IP address Router IP address
</label> </label>
<div <div
class="col-sm-9" class="col-sm-8"
> >
<input <input
class="form-control " class="form-control "
...@@ -288,13 +288,13 @@ exports[`<LAN/> Snapshot managed. 1`] = ` ...@@ -288,13 +288,13 @@ exports[`<LAN/> Snapshot managed. 1`] = `
class="form-group row" class="form-group row"
> >
<label <label
class="form-control-label col-sm-2" class="form-control-label col-sm-3"
for="60" for="60"
> >
Network mask Network mask
</label> </label>
<div <div
class="col-sm-9" class="col-sm-8"
> >
<input <input
class="form-control " class="form-control "
...@@ -315,7 +315,7 @@ exports[`<LAN/> Snapshot managed. 1`] = ` ...@@ -315,7 +315,7 @@ exports[`<LAN/> Snapshot managed. 1`] = `
class="form-group row" class="form-group row"
> >
<div <div
class="form-label col-sm-2" class="form-label col-sm-3"
> >
<label <label
class="form-label" class="form-label"
...@@ -325,7 +325,7 @@ exports[`<LAN/> Snapshot managed. 1`] = ` ...@@ -325,7 +325,7 @@ exports[`<LAN/> Snapshot managed. 1`] = `
</label> </label>
</div> </div>
<div <div
class="form-check col-sm-9" class="form-check col-sm-8"
> >
<input <input
id="61" id="61"
...@@ -357,13 +357,13 @@ exports[`<LAN/> Snapshot unmanaged (dhcp). 1`] = ` ...@@ -357,13 +357,13 @@ exports[`<LAN/> Snapshot unmanaged (dhcp). 1`] = `
class="form-group row" class="form-group row"
> >
<label <label
class="form-control-label col-sm-2" class="form-control-label col-sm-3"
for="1" for="1"
> >
LAN mode LAN mode
</label> </label>
<div <div
class="col-sm-9" class="col-sm-8"
> >
<select <select
class="form-control" class="form-control"
...@@ -391,13 +391,13 @@ exports[`<LAN/> Snapshot unmanaged (dhcp). 1`] = ` ...@@ -391,13 +391,13 @@ exports[`<LAN/> Snapshot unmanaged (dhcp). 1`] = `
class="form-group row" class="form-group row"
> >
<label <label
class="form-control-label col-sm-2" class="form-control-label col-sm-3"
for="2" for="2"
> >
IPv4 protocol IPv4 protocol
</label> </label>
<div <div
class="col-sm-9" class="col-sm-8"
> >
<select <select
class="form-control" class="form-control"
...@@ -428,13 +428,13 @@ exports[`<LAN/> Snapshot unmanaged (dhcp). 1`] = ` ...@@ -428,13 +428,13 @@ exports[`<LAN/> Snapshot unmanaged (dhcp). 1`] = `
class="form-group row" class="form-group row"
> >
<label <label
class="form-control-label col-sm-2" class="form-control-label col-sm-3"