Updated react UI and UX part.

This commit is contained in:
Alexander 2021-10-27 11:13:28 +03:00
commit 91e7d9ff4a
101 changed files with 1524 additions and 832 deletions

View file

@ -3,7 +3,7 @@ import { getAuthToken } from "src/utils/token";
const BASE_URL = window.location.origin; const BASE_URL = window.location.origin;
const webApiUri = '/api/v1/list/backup/index.php'; const webApiUri = '/api/v1/list/backup/index.php';
const scheduleBackupUri = '/schedule/backup/'; const scheduleBackupUri = '/api/v1/schedule/restore/';
const backupDetailsUri = '/api/v1/list/backup/index.php'; const backupDetailsUri = '/api/v1/list/backup/index.php';
const backupExclusionsUri = '/api/v1/list/backup/exclusions/index.php'; const backupExclusionsUri = '/api/v1/list/backup/exclusions/index.php';
const backupExclusionsInfoUri = '/api/v1/edit/backup/exclusions/index.php'; const backupExclusionsInfoUri = '/api/v1/edit/backup/exclusions/index.php';

View file

@ -19,13 +19,26 @@ export const getDNSRecordInfo = (domain, recordId) => {
return axios.get(`${BASE_URL}${updateDNSUri}?domain=${domain}&record_id=${recordId}`); return axios.get(`${BASE_URL}${updateDNSUri}?domain=${domain}&record_id=${recordId}`);
} }
export const bulkAction = (action, domainNameSystems) => { export const bulkDomainAction = (action, domains) => {
const formData = new FormData(); const formData = new FormData();
formData.append("action", action); formData.append("action", action);
formData.append("token", getAuthToken()); formData.append("token", getAuthToken());
domainNameSystems.forEach(domainNameSystem => { domains.forEach(record => {
formData.append("domain[]", domainNameSystem); formData.append("domain[]", record);
});
return axios.post(BASE_URL + '/api/v1/bulk/dns/', formData);
};
export const bulkAction = (action, records, domain) => {
const formData = new FormData();
formData.append("action", action);
formData.append("token", getAuthToken());
formData.append("domain", domain);
records.forEach(record => {
formData.append("record[]", record);
}); });
return axios.post(BASE_URL + '/api/v1/bulk/dns/', formData); return axios.post(BASE_URL + '/api/v1/bulk/dns/', formData);

View file

@ -2,7 +2,7 @@ import axios from "axios";
import { getAuthToken } from "src/utils/token"; import { getAuthToken } from "src/utils/token";
const BASE_URL = window.location.origin; const BASE_URL = window.location.origin;
const webApiUri = '/search/search.php'; const webApiUri = '/api/v1/search/';
export const getSearchResultsList = term => { export const getSearchResultsList = term => {
return axios.get(BASE_URL + webApiUri + '?q=' + term); return axios.get(BASE_URL + webApiUri + '?q=' + term);

View file

@ -0,0 +1,27 @@
import { REFRESH_COUNTERS } from './menuCounterTypes';
import { checkAuth } from 'src/services/session';
import { setAuthToken } from 'src/utils/token';
export const refreshCounters = () => (dispatch, getState) => {
return new Promise((resolve, reject) => {
checkAuth()
.then(res => {
const { data, token } = res.data;
if (token) setAuthToken(token);
dispatch({
type: REFRESH_COUNTERS,
value: {
user: data
}
});
resolve(token);
})
.catch(err => {
reject();
console.error(err);
});
});
}

View file

@ -0,0 +1 @@
export const REFRESH_COUNTERS = 'REFRESH_COUNTERS';

View file

@ -2,6 +2,7 @@ import { LOGIN, LOGOUT, LOGGED_OUT_AS, CHECK_AUTH, RESET_PASSWORD } from './sess
import { checkAuth, signIn, signInAs, signOut } from 'src/services/session'; import { checkAuth, signIn, signInAs, signOut } from 'src/services/session';
import { resetPassword } from 'src/ControlPanelService/ResetPassword'; import { resetPassword } from 'src/ControlPanelService/ResetPassword';
import { resetAuthToken, setAuthToken } from 'src/utils/token'; import { resetAuthToken, setAuthToken } from 'src/utils/token';
import { REFRESH_COUNTERS } from '../MenuCounters/menuCounterTypes';
const LOGOUT_RESPONSE = 'logged_out'; const LOGOUT_RESPONSE = 'logged_out';
const LOGOUT_AS_RESPONSE = 'logged_out_as'; const LOGOUT_AS_RESPONSE = 'logged_out_as';
@ -21,10 +22,15 @@ export const login = (user, password) => dispatch => {
session, session,
i18n: i18n || {}, i18n: i18n || {},
userName: user, userName: user,
user: data,
error error
}, },
}); });
dispatch({
type: REFRESH_COUNTERS,
value: {
user: data,
}
});
resolve(token); resolve(token);
}, (error) => { }, (error) => {
reject(error); reject(error);
@ -44,10 +50,15 @@ export const reset = ({ user = '', code = '', password = '', password_confirm =
panel, panel,
session, session,
userName: user, userName: user,
user: {},
error error
}, },
}); });
dispatch({
type: REFRESH_COUNTERS,
value: {
user: {},
}
});
resolve(token); resolve(token);
}, (error) => { }, (error) => {
reject(error); reject(error);
@ -65,7 +76,6 @@ export const loginAs = username => dispatch => {
type: LOGIN, type: LOGIN,
value: { value: {
userName: user, userName: user,
user: data,
i18n, i18n,
session, session,
panel, panel,
@ -73,6 +83,12 @@ export const loginAs = username => dispatch => {
error error
} }
}); });
dispatch({
type: REFRESH_COUNTERS,
value: {
user: data,
}
});
resolve(token); resolve(token);
}, (error) => { }, (error) => {
@ -94,7 +110,6 @@ export const logout = () => (dispatch, getState) => {
type: LOGOUT, type: LOGOUT,
value: { value: {
userName: '', userName: '',
user: {},
token: '', token: '',
panel: {}, panel: {},
session: {}, session: {},
@ -102,6 +117,12 @@ export const logout = () => (dispatch, getState) => {
error, error,
}, },
}); });
dispatch({
type: REFRESH_COUNTERS,
value: {
user: {},
}
});
resolve(); resolve();
} else if (logout_response === LOGOUT_AS_RESPONSE) { } else if (logout_response === LOGOUT_AS_RESPONSE) {
@ -109,7 +130,6 @@ export const logout = () => (dispatch, getState) => {
type: LOGGED_OUT_AS, type: LOGGED_OUT_AS,
value: { value: {
userName, userName,
user,
session, session,
panel, panel,
token: '', token: '',
@ -117,6 +137,12 @@ export const logout = () => (dispatch, getState) => {
error, error,
}, },
}); });
dispatch({
type: REFRESH_COUNTERS,
value: {
user,
}
});
resolve(); resolve();
} else { } else {
@ -135,11 +161,12 @@ export const checkAuthHandler = () => (dispatch, getState) => {
.then(res => { .then(res => {
const { user, data, session, panel, error, i18n, token } = res.data; const { user, data, session, panel, error, i18n, token } = res.data;
if (token) setAuthToken(token);
dispatch({ dispatch({
type: CHECK_AUTH, type: CHECK_AUTH,
value: { value: {
userName: user, userName: user,
user: data,
i18n, i18n,
session, session,
panel, panel,
@ -147,6 +174,12 @@ export const checkAuthHandler = () => (dispatch, getState) => {
error error
} }
}); });
dispatch({
type: REFRESH_COUNTERS,
value: {
user: data,
}
});
resolve(token); resolve(token);
}) })

View file

@ -57,7 +57,7 @@ const Backup = props => {
{data.UPDATED === 'no' && <div><a href={`/update/vesta/?pkg=${data.NAME}`}>{i18n.update} <FontAwesomeIcon icon="wrench" /></a></div>} {data.UPDATED === 'no' && <div><a href={`/update/vesta/?pkg=${data.NAME}`}>{i18n.update} <FontAwesomeIcon icon="wrench" /></a></div>}
<div> <div>
<a className="link-download" href={`/download/backup/?backup=${data.NAME}&token=${token}`}> <a className="link-download" href={`/api/v1/download/backup/?backup=${data.NAME}&token=${token}`}>
{i18n.download} {i18n.download}
{data.FOCUSED ? <span className="shortcut-button">D</span> : <FontAwesomeIcon icon={faFileDownload} />} {data.FOCUSED ? <span className="shortcut-button">D</span> : <FontAwesomeIcon icon={faFileDownload} />}
</a> </a>

View file

@ -11,6 +11,7 @@ import { useDispatch, useSelector } from 'react-redux';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import './style.scss'; import './style.scss';
import HtmlParser from 'react-html-parser';
const EditBackupExclusions = () => { const EditBackupExclusions = () => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -90,7 +91,7 @@ const EditBackupExclusions = () => {
</div> </div>
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -32,7 +32,7 @@ $errorColor: #BE5ABF;
div.error, div.error,
div.success { div.success {
width: fit-content !important; width: max-content !important;
span { span {
font-weight: bold; font-weight: bold;
@ -40,6 +40,7 @@ $errorColor: #BE5ABF;
svg { svg {
font-size: 13px; font-size: 13px;
margin-right: 10px;
} }
} }
@ -151,10 +152,24 @@ $errorColor: #BE5ABF;
} }
} }
textarea { input:-webkit-autofill,
&:focus { input:-webkit-autofill:hover,
background: #D7F9FF; input:-webkit-autofill:focus,
} input:-webkit-autofill:active {
background-color: $primaryLight;
border-color: $primaryActive;
filter: none;
box-shadow: none;
}
input:autofill,
input:autofill:hover,
input:autofill:focus,
input:autofill:active {
background-color: $primaryLight;
border-color: $primaryActive;
filter: none;
box-shadow: none;
} }
button { button {
@ -180,7 +195,7 @@ $errorColor: #BE5ABF;
&:active { &:active {
box-shadow: unset; box-shadow: unset;
border-color: $primaryActive; border-color: $primaryActive;
background: #D7F9FF; background: #d7dcef9e;
} }
} }

View file

@ -7,11 +7,7 @@ const TextInputWithExtraButton = props => {
}); });
useEffect(() => { useEffect(() => {
if (props.value !== 'unlimited') { setState({ ...state, value: props.value });
setState({ ...state, value: state.previousValue });
} else {
setState({ ...state, value: props.value });
}
}, [props.value]); }, [props.value]);
useEffect(() => { useEffect(() => {

View file

@ -27,7 +27,7 @@ const TextInputWithTextOnTheRight = ({ id, title, name, defaultValue = '', optio
onChange={event => setInputValue(event.target.value)} onChange={event => setInputValue(event.target.value)}
disabled={disabled} disabled={disabled}
name={name} /> name={name} />
<span><i>{`admin_${inputValue}`}</i></span> <span><i>{`${inputValue}`}</i></span>
</div> </div>
</div> </div>
); );

View file

@ -12,6 +12,8 @@ import { useDispatch, useSelector } from 'react-redux';
import './AddCronJob.scss'; import './AddCronJob.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
import HtmlParser from 'react-html-parser';
const AddCronJob = props => { const AddCronJob = props => {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
@ -46,18 +48,17 @@ const AddCronJob = props => {
if (Object.keys(newCronJob).length !== 0 && newCronJob.constructor === Object) { if (Object.keys(newCronJob).length !== 0 && newCronJob.constructor === Object) {
setState({ ...state, loading: true }); setState({ ...state, loading: true });
addCronJob(newCronJob) addCronJob(newCronJob)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
const { error_msg, ok_msg } = result.data; const { error_msg: errorMessage, ok_msg: okMessage } = result.data;
if (error_msg) { if (errorMessage) {
setState({ ...state, errorMessage: error_msg, okMessage: '', loading: false }); setState({ ...state, errorMessage, okMessage, loading: false });
} else if (ok_msg) {
setState({ ...state, errorMessage: '', okMessage: ok_msg, loading: false });
} else { } else {
setState({ ...state, loading: false }) dispatch(refreshCounters()).then(() => {
setState({ ...state, okMessage, errorMessage: '', loading: false });
});
} }
} }
}) })
@ -100,7 +101,7 @@ const AddCronJob = props => {
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''}
<span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -25,11 +25,11 @@ const CronJob = props => {
const handleSuspend = () => { const handleSuspend = () => {
let suspendedStatus = data.SUSPENDED === 'yes' ? 'unsuspend' : 'suspend' === 'yes' ? 'unsuspend' : 'suspend'; let suspendedStatus = data.SUSPENDED === 'yes' ? 'unsuspend' : 'suspend' === 'yes' ? 'unsuspend' : 'suspend';
props.handleModal(data.suspend_conf, `/${suspendedStatus}/cron/index.php?job=${data.NAME}`); props.handleModal(data.suspend_conf, `/api/v1/${suspendedStatus}/cron/index.php?job=${data.NAME}`);
} }
const handleDelete = () => { const handleDelete = () => {
props.handleModal(data.delete_conf, `/delete/cron/index.php?job=${data.NAME}`); props.handleModal(data.delete_conf, `/api/v1/delete/cron/index.php?job=${data.NAME}`);
} }
return ( return (

View file

@ -13,6 +13,9 @@ import QS from 'qs';
import './EditCronJob.scss'; import './EditCronJob.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { checkAuthHandler } from 'src/actions/Session/sessionActions';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
import HtmlParser from 'react-html-parser';
const EditMail = props => { const EditMail = props => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -79,14 +82,14 @@ const EditMail = props => {
updateCronJob(updatedJob, state.data.job) updateCronJob(updatedJob, state.data.job)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
const { error_msg, ok_msg } = result.data; const { error_msg: errorMessage, ok_msg: okMessage } = result.data;
if (error_msg) { if (errorMessage) {
setState({ ...state, errorMessage: error_msg, okMessage: '', loading: false }); setState({ ...state, errorMessage, okMessage, loading: false });
} else if (ok_msg) {
setState({ ...state, errorMessage: '', okMessage: ok_msg, loading: false });
} else { } else {
setState({ ...state, loading: false }); dispatch(refreshCounters()).then(() => {
setState({ ...state, okMessage, errorMessage: '', loading: false });
});
} }
} }
}) })
@ -128,7 +131,7 @@ const EditMail = props => {
</div> </div>
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -5,7 +5,6 @@ import SelectInput from 'src/components/ControlPanel/AddItemLayout/Form/SelectIn
import TextInput from 'src/components/ControlPanel/AddItemLayout/Form/TextInput/TextInput'; import TextInput from 'src/components/ControlPanel/AddItemLayout/Form/TextInput/TextInput';
import AddItemLayout from '../../ControlPanel/AddItemLayout/AddItemLayout'; import AddItemLayout from '../../ControlPanel/AddItemLayout/AddItemLayout';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { addMail } from '../../../ControlPanelService/Mail';
import { addDomainNameSystemRecord } from '../../../ControlPanelService/Dns'; import { addDomainNameSystemRecord } from '../../../ControlPanelService/Dns';
import Toolbar from '../../MainNav/Toolbar/Toolbar'; import Toolbar from '../../MainNav/Toolbar/Toolbar';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
@ -14,6 +13,8 @@ import { useDispatch, useSelector } from 'react-redux';
import './AddDNSRecord.scss' import './AddDNSRecord.scss'
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
import HtmlParser from 'react-html-parser';
export default function AddDNSRecord(props) { export default function AddDNSRecord(props) {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
@ -61,16 +62,18 @@ export default function AddDNSRecord(props) {
newDnsRecord['v_domain'] = props.domain; newDnsRecord['v_domain'] = props.domain;
if (Object.keys(newDnsRecord).length !== 0 && newDnsRecord.constructor === Object) { if (Object.keys(newDnsRecord).length !== 0 && newDnsRecord.constructor === Object) {
setState({ loading: true }); setState({ ...state, loading: true });
addDomainNameSystemRecord(newDnsRecord) addDomainNameSystemRecord(newDnsRecord)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
const { error_msg, ok_msg } = result.data; const { error_msg: errorMessage, ok_msg: okMessage } = result.data;
if (error_msg) { if (errorMessage) {
setState({ ...state, errorMessage: error_msg, okMessage: '', loading: false }); setState({ ...state, errorMessage, okMessage, loading: false });
} else if (ok_msg) { } else {
setState({ ...state, errorMessage: '', okMessage: ok_msg, loading: false }); dispatch(refreshCounters()).then(() => {
setState({ ...state, okMessage, errorMessage: '', loading: false });
});
} }
} }
}) })
@ -94,7 +97,7 @@ export default function AddDNSRecord(props) {
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''}
<span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -7,7 +7,6 @@ import { useSelector } from 'react-redux';
export default function DnsRecord({ data, domain, handleModal, ...props }) { export default function DnsRecord({ data, domain, handleModal, ...props }) {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token");
const toggleFav = (starred) => { const toggleFav = (starred) => {
if (starred) { if (starred) {
@ -25,6 +24,10 @@ export default function DnsRecord({ data, domain, handleModal, ...props }) {
handleModal(data.delete_conf, `/api/v1/delete/dns/?domain=${domain}&record_id=${data.ID}`); handleModal(data.delete_conf, `/api/v1/delete/dns/?domain=${domain}&record_id=${data.ID}`);
} }
const handleSuspend = () => {
handleModal(data.suspend_conf, `/api/v1/${data.suspend_action}/dns/?domain=${domain}&record_id=${data.ID}`);
}
return ( return (
<ListItem <ListItem
id={data.NAME} id={data.NAME}
@ -62,6 +65,15 @@ export default function DnsRecord({ data, domain, handleModal, ...props }) {
</Link> </Link>
</div> </div>
<div>
<button
className="link-gray"
onClick={handleSuspend}>
{data.suspend_action}
{data.FOCUSED ? <span className="shortcut-button">S</span> : <FontAwesomeIcon icon={data.SUSPENDED === 'yes' ? 'unlock' : 'lock'} />}
</button>
</div>
<div> <div>
<button className="link-delete" onClick={() => handleDelete()}> <button className="link-delete" onClick={() => handleDelete()}>
{i18n.Delete} {i18n.Delete}

View file

@ -11,6 +11,9 @@ import { useHistory } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import QS from 'qs'; import QS from 'qs';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { checkAuthHandler } from 'src/actions/Session/sessionActions';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
import HtmlParser from 'react-html-parser';
export default function EditDNSRecord(props) { export default function EditDNSRecord(props) {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -81,14 +84,14 @@ export default function EditDNSRecord(props) {
updateDNS(updatedRecord, props.domain, props.record_id) updateDNS(updatedRecord, props.domain, props.record_id)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
const { error_msg, ok_msg } = result.data; const { error_msg: errorMessage, ok_msg: okMessage } = result.data;
if (error_msg) { if (errorMessage) {
setState({ ...state, errorMessage: error_msg, okMessage: '', loading: false }); setState({ ...state, errorMessage, okMessage, loading: false });
} else if (ok_msg) {
setState({ ...state, errorMessage: '', okMessage: ok_msg, loading: false });
} else { } else {
setState({ ...state, loading: false }); dispatch(refreshCounters()).then(() => {
setState({ ...state, okMessage, errorMessage: '', loading: false });
});
} }
} }
}) })
@ -111,7 +114,7 @@ export default function EditDNSRecord(props) {
</div> </div>
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react'; import React, { memo, useEffect, useState } from 'react';
import { addActiveElement, removeFocusedElement } from "../../../actions/MainNavigation/mainNavigationActions"; import { addActiveElement, removeFocusedElement } from "../../../actions/MainNavigation/mainNavigationActions";
import { dbCharsets, addDatabase, getDbOptionalInfo } from '../../../ControlPanelService/Db'; import { dbCharsets, addDatabase, getDbOptionalInfo } from '../../../ControlPanelService/Db';
@ -9,11 +9,12 @@ import Toolbar from '../../MainNav/Toolbar/Toolbar';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import Spinner from '../../Spinner/Spinner'; import Spinner from '../../Spinner/Spinner';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import './AddDatabase.scss'
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
import HtmlParser from 'react-html-parser';
import './AddDatabase.scss'
const AddDatabase = props => { const AddDatabase = memo(props => {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const dispatch = useDispatch(); const dispatch = useDispatch();
@ -91,23 +92,22 @@ const AddDatabase = props => {
newDatabase[name] = value; newDatabase[name] = value;
} }
newDatabase['v_database'] = `${state.user}_${state.databaseInputValue}`; newDatabase['v_database'] = state.databaseInputValue;
newDatabase['v_dbuser'] = `${state.user}_${state.databaseUserInputValue}`; newDatabase['v_dbuser'] = state.databaseUserInputValue;
if (Object.keys(newDatabase).length !== 0 && newDatabase.constructor === Object) { if (Object.keys(newDatabase).length !== 0 && newDatabase.constructor === Object) {
setState({ ...state, loading: true }); setState({ ...state, loading: true });
addDatabase(newDatabase) addDatabase(newDatabase)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
const { error_msg, ok_msg } = result.data; const { error_msg: errorMessage, ok_msg: okMessage } = result.data;
if (error_msg) { if (errorMessage) {
setState({ ...state, errorMessage: error_msg, okMessage: '', loading: false }); setState({ ...state, errorMessage, okMessage: '', loading: false });
} else if (ok_msg) {
setState({ ...state, errorMessage: '', okMessage: ok_msg, loading: false });
} else { } else {
setState({ ...state, loading: false }) dispatch(refreshCounters()).then(() => {
setState({ ...state, okMessage, errorMessage: '', loading: false });
});
} }
} }
}) })
@ -131,7 +131,7 @@ const AddDatabase = props => {
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''}
<span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>
@ -141,7 +141,7 @@ const AddDatabase = props => {
<input type="hidden" name="ok" value="add" /> <input type="hidden" name="ok" value="add" />
<input type="hidden" name="token" value={token} /> <input type="hidden" name="token" value={token} />
<span className="prefix" dangerouslySetInnerHTML={{ __html: state.prefixI18N }}></span> <span className="prefix">{HtmlParser(state.prefixI18N)}</span>
<div className="form-group database"> <div className="form-group database">
<label htmlFor="database">{i18n.Database}</label> <label htmlFor="database">{i18n.Database}</label>
@ -215,6 +215,6 @@ const AddDatabase = props => {
</AddItemLayout> </AddItemLayout>
</div> </div>
); );
} });
export default AddDatabase; export default AddDatabase;

View file

@ -14,15 +14,18 @@ import QS from 'qs';
import './EditDatabase.scss'; import './EditDatabase.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
import HtmlParser from 'react-html-parser';
const EditDatabase = props => { const EditDatabase = props => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const { i18n } = useSelector(state => state.session); const { i18n, userName } = useSelector(state => state.session);
const history = useHistory(); const history = useHistory();
const dispatch = useDispatch(); const dispatch = useDispatch();
const [state, setState] = useState({ const [state, setState] = useState({
data: {}, data: {},
loading: false, loading: false,
databaseUserInputValue: '',
errorMessage: '', errorMessage: '',
okMessage: '' okMessage: ''
}); });
@ -42,6 +45,7 @@ const EditDatabase = props => {
setState({ setState({
...state, ...state,
data: response.data, data: response.data,
databaseUserInputValue: response.data.dbuser.split('_').splice(1).join('_'),
errorMessage: response.data['error_msg'], errorMessage: response.data['error_msg'],
okMessage: response.data['ok_msg'], okMessage: response.data['ok_msg'],
loading: false loading: false
@ -60,6 +64,7 @@ const EditDatabase = props => {
} }
updatedDatabase['v_database'] = state.data.database; updatedDatabase['v_database'] = state.data.database;
updatedDatabase['v_dbuser'] = `${userName}_${state.databaseUserInputValue}`;
if (Object.keys(updatedDatabase).length !== 0 && updatedDatabase.constructor === Object) { if (Object.keys(updatedDatabase).length !== 0 && updatedDatabase.constructor === Object) {
setState({ ...state, loading: true }); setState({ ...state, loading: true });
@ -67,14 +72,14 @@ const EditDatabase = props => {
updateDatabase(updatedDatabase, state.data.database) updateDatabase(updatedDatabase, state.data.database)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
const { error_msg, ok_msg } = result.data; const { error_msg: errorMessage, ok_msg: okMessage } = result.data;
if (error_msg) { if (errorMessage) {
setState({ ...state, errorMessage: error_msg, okMessage: '', loading: false }); setState({ ...state, errorMessage, okMessage, loading: false });
} else if (ok_msg) {
setState({ ...state, errorMessage: '', okMessage: ok_msg, loading: false });
} else { } else {
setState({ ...state, loading: false }); dispatch(refreshCounters()).then(() => {
setState({ ...state, okMessage, errorMessage: '', loading: false });
});
} }
} }
}) })
@ -82,6 +87,10 @@ const EditDatabase = props => {
} }
} }
const databaseUserInputHandler = value => {
setState({ ...state, databaseUserInputValue: value });
}
return ( return (
<div className="edit-template edit-db"> <div className="edit-template edit-db">
<Helmet> <Helmet>
@ -97,7 +106,7 @@ const EditDatabase = props => {
</div> </div>
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>
@ -109,7 +118,21 @@ const EditDatabase = props => {
<TextInputWithTextOnTheRight id="database" name="v_database" title={i18n['Database']} defaultValue={state.data.database} disabled /> <TextInputWithTextOnTheRight id="database" name="v_database" title={i18n['Database']} defaultValue={state.data.database} disabled />
<TextInputWithTextOnTheRight id="username" name="v_dbuser" title={i18n['User']} defaultValue={state.data.dbuser} /> <div className="form-group">
<div className="label-wrapper">
<label htmlFor="user">{i18n.User}</label>
</div>
<div className="input-wrapper">
<input
type="text"
className="form-control"
id="user"
value={state.databaseUserInputValue}
onChange={event => databaseUserInputHandler(event.target.value)}
name="v_dbuser" />
<span className="italic"><i>{`${userName}_${state.databaseUserInputValue}`}</i></span>
</div>
</div>
<Password name="v_password" defaultValue={state.data.password} /> <Password name="v_password" defaultValue={state.data.password} />

View file

@ -0,0 +1,9 @@
.input-wrapper {
display: flex;
align-items: center;
span.italic {
margin-left: 15px;
color: #777;
}
}

View file

@ -13,6 +13,8 @@ import './AddDomainNameSystem.scss';
import AdvancedOptions from './AdvancedOptions/AdvancedOptions'; import AdvancedOptions from './AdvancedOptions/AdvancedOptions';
import { addDomainNameSystem } from '../../../ControlPanelService/Dns'; import { addDomainNameSystem } from '../../../ControlPanelService/Dns';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
import HtmlParser from 'react-html-parser';
const AddDomainNameSystem = props => { const AddDomainNameSystem = props => {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
@ -33,7 +35,6 @@ const AddDomainNameSystem = props => {
dispatch(removeFocusedElement()); dispatch(removeFocusedElement());
setState({ ...state, loading: true }); setState({ ...state, loading: true });
getUserNS() getUserNS()
.then(result => { .then(result => {
if (result.data.length) { if (result.data.length) {
@ -53,18 +54,17 @@ const AddDomainNameSystem = props => {
if (Object.keys(domainNameSystem).length !== 0 && domainNameSystem.constructor === Object) { if (Object.keys(domainNameSystem).length !== 0 && domainNameSystem.constructor === Object) {
setState({ ...state, loading: true }); setState({ ...state, loading: true });
addDomainNameSystem(domainNameSystem) addDomainNameSystem(domainNameSystem)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
const { error_msg, ok_msg } = result.data; const { error_msg: errorMessage, ok_msg: okMessage } = result.data;
if (error_msg) { if (errorMessage) {
setState({ ...state, errorMessage: error_msg, okMessage: '', loading: false }); setState({ ...state, errorMessage, okMessage, loading: false });
} else if (ok_msg) {
setState({ ...state, errorMessage: '', okMessage: ok_msg, loading: false });
} else { } else {
setState({ ...state, loading: false }); dispatch(refreshCounters()).then(() => {
setState({ ...state, okMessage, errorMessage: '', loading: false });
});
} }
} }
}) })
@ -98,7 +98,7 @@ const AddDomainNameSystem = props => {
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''}
<span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -13,6 +13,9 @@ import QS from 'qs';
import './EditDomainNameSystem.scss'; import './EditDomainNameSystem.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { checkAuthHandler } from 'src/actions/Session/sessionActions';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
import HtmlParser from 'react-html-parser';
const EditDomainNameSystem = props => { const EditDomainNameSystem = props => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -66,14 +69,14 @@ const EditDomainNameSystem = props => {
updateDNS(updatedDomain, state.data.domain) updateDNS(updatedDomain, state.data.domain)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
const { error_msg, ok_msg } = result.data; const { error_msg: errorMessage, ok_msg: okMessage } = result.data;
if (error_msg) { if (errorMessage) {
setState({ ...state, errorMessage: error_msg, okMessage: '', loading: false }); setState({ ...state, errorMessage, okMessage, loading: false });
} else if (ok_msg) {
setState({ ...state, errorMessage: '', okMessage: ok_msg, loading: false });
} else { } else {
setState({ ...state, loading: false }); dispatch(refreshCounters()).then(() => {
setState({ ...state, okMessage, errorMessage: '', loading: false });
});
} }
} }
}) })
@ -96,7 +99,7 @@ const EditDomainNameSystem = props => {
</div> </div>
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -12,6 +12,8 @@ import { useDispatch, useSelector } from 'react-redux';
import './AddFirewall.scss'; import './AddFirewall.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
import HtmlParser from 'react-html-parser';
const AddFirewall = props => { const AddFirewall = props => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -48,18 +50,17 @@ const AddFirewall = props => {
if (Object.keys(newFirewall).length !== 0 && newFirewall.constructor === Object) { if (Object.keys(newFirewall).length !== 0 && newFirewall.constructor === Object) {
setState({ ...state, loading: true }); setState({ ...state, loading: true });
addFirewall(newFirewall) addFirewall(newFirewall)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
const { error_msg, ok_msg } = result.data; const { error_msg: errorMessage, ok_msg: okMessage } = result.data;
if (error_msg) { if (errorMessage) {
setState({ ...state, errorMessage: error_msg, okMessage: '', loading: false }); setState({ ...state, errorMessage, okMessage, loading: false });
} else if (ok_msg) {
setState({ ...state, errorMessage: '', okMessage: ok_msg, loading: false });
} else { } else {
setState({ ...state, loading: false }) dispatch(refreshCounters()).then(() => {
setState({ ...state, okMessage, errorMessage: '', loading: false });
});
} }
} }
}) })
@ -83,7 +84,7 @@ const AddFirewall = props => {
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''}
<span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -8,6 +8,7 @@ import Toolbar from '../../../MainNav/Toolbar/Toolbar';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import HtmlParser from 'react-html-parser';
const AddBanIP = () => { const AddBanIP = () => {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
@ -74,7 +75,7 @@ const AddBanIP = () => {
<div className="search-toolbar-name">{i18n['Adding IP Address to Banlist']}</div> <div className="search-toolbar-name">{i18n['Adding IP Address to Banlist']}</div>
<div className="error"><span className="error-message">{state.errorMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} {state.errorMessage}</span></div> <div className="error"><span className="error-message">{state.errorMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} {state.errorMessage}</span></div>
<div className="success"> <div className="success">
<span className="ok-message">{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> </span> <span className="ok-message">{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span>{HtmlParser(state.okMessage)}</span> </span>
</div> </div>
</Toolbar> </Toolbar>
<AddItemLayout> <AddItemLayout>

View file

@ -13,6 +13,9 @@ import QS from 'qs';
import './EditFirewall.scss'; import './EditFirewall.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { checkAuthHandler } from 'src/actions/Session/sessionActions';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
import HtmlParser from 'react-html-parser';
const EditFirewall = props => { const EditFirewall = props => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -64,14 +67,14 @@ const EditFirewall = props => {
updateFirewall(updatedDomain, state.data.domain) updateFirewall(updatedDomain, state.data.domain)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
const { error_msg, ok_msg } = result.data; const { error_msg: errorMessage, ok_msg: okMessage } = result.data;
if (error_msg) { if (errorMessage) {
setState({ ...state, errorMessage: error_msg, okMessage: '', loading: false }); setState({ ...state, errorMessage, okMessage, loading: false });
} else if (ok_msg) {
setState({ ...state, errorMessage: '', okMessage: ok_msg, loading: false });
} else { } else {
setState({ ...state, loading: false }); dispatch(refreshCounters()).then(() => {
setState({ ...state, okMessage, errorMessage: '', loading: false });
});
} }
} }
}) })
@ -94,7 +97,7 @@ const EditFirewall = props => {
</div> </div>
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -14,6 +14,8 @@ import { useDispatch, useSelector } from 'react-redux';
import './AddInternetProtocol.scss'; import './AddInternetProtocol.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
import HtmlParser from 'react-html-parser';
const AddInternetProtocol = props => { const AddInternetProtocol = props => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -49,18 +51,17 @@ const AddInternetProtocol = props => {
if (Object.keys(newIp).length !== 0 && newIp.constructor === Object) { if (Object.keys(newIp).length !== 0 && newIp.constructor === Object) {
setState({ ...state, loading: true }); setState({ ...state, loading: true });
addInternetProtocol(newIp) addInternetProtocol(newIp)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
const { error_msg, ok_msg } = result.data; const { error_msg: errorMessage, ok_msg: okMessage } = result.data;
if (error_msg) { if (errorMessage) {
setState({ ...state, errorMessage: error_msg, okMessage: '', loading: false }); setState({ ...state, errorMessage, okMessage, loading: false });
} else if (ok_msg) {
setState({ ...state, errorMessage: '', okMessage: ok_msg, loading: false });
} else { } else {
setState({ ...state, loading: false }) dispatch(refreshCounters()).then(() => {
setState({ ...state, okMessage, errorMessage: '', loading: false });
});
} }
} }
}) })
@ -96,7 +97,7 @@ const AddInternetProtocol = props => {
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''}
<span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -15,6 +15,9 @@ import QS from 'qs';
import './EditInternetProtocol.scss'; import './EditInternetProtocol.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { checkAuthHandler } from 'src/actions/Session/sessionActions';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
import HtmlParser from 'react-html-parser';
const EditInternetProtocol = () => { const EditInternetProtocol = () => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -72,8 +75,15 @@ const EditInternetProtocol = () => {
updateInternetProtocol(updatedIP, state.data.ip) updateInternetProtocol(updatedIP, state.data.ip)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
const { error_msg, ok_msg } = result.data; const { error_msg: errorMessage, ok_msg: okMessage } = result.data;
setState({ ...state, errorMessage: error_msg || '', okMessage: ok_msg || '', loading: false });
if (errorMessage) {
setState({ ...state, errorMessage, okMessage, loading: false });
} else {
dispatch(refreshCounters()).then(() => {
setState({ ...state, okMessage, errorMessage: '', loading: false });
});
}
} }
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
@ -99,7 +109,7 @@ const EditInternetProtocol = () => {
</div> </div>
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -169,8 +169,8 @@ li.inactive {
background: rgb(220, 220, 220); background: rgb(220, 220, 220);
} }
@media (max-width: 1200px){ @media (max-width: 1320px){
.fPermissions, .fOwner { .fPermissions, .fOwner {
display: none; display: none;
} }
} }

View file

@ -1,4 +1,8 @@
.logs-list { .logs-list {
.toolbar {
padding: 6px 12.5%;
}
.statistic-item { .statistic-item {
.l-col { .l-col {
font-size: 13px; font-size: 13px;
@ -25,4 +29,10 @@
color: #5edad0; color: #5edad0;
} }
} }
}
@media (max-width: 1350px) {
.logs-list .toolbar {
padding: 6px 9.5%;
}
} }

View file

@ -11,6 +11,9 @@ import { useDispatch, useSelector } from 'react-redux';
import './AddMail.scss' import './AddMail.scss'
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { checkAuthHandler } from 'src/actions/Session/sessionActions';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
import HtmlParser from 'react-html-parser';
const AddMail = props => { const AddMail = props => {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
@ -40,15 +43,18 @@ const AddMail = props => {
} }
if (Object.keys(newMailDomain).length !== 0 && newMailDomain.constructor === Object) { if (Object.keys(newMailDomain).length !== 0 && newMailDomain.constructor === Object) {
setState({ ...state, loading: true });
addMail(newMailDomain) addMail(newMailDomain)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
const { error_msg, ok_msg } = result.data; const { error_msg: errorMessage, ok_msg: okMessage } = result.data;
if (error_msg) { if (errorMessage) {
setState({ ...state, errorMessage: error_msg, okMessage: '' }); setState({ ...state, errorMessage, okMessage, loading: false });
} else if (ok_msg) { } else {
setState({ ...state, errorMessage: '', okMessage: ok_msg }); dispatch(refreshCounters()).then(() => {
setState({ ...state, okMessage, errorMessage: '', loading: false });
});
} }
} }
}) })
@ -72,7 +78,7 @@ const AddMail = props => {
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''}
<span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -13,6 +13,9 @@ import QS from 'qs';
import './EditMail.scss'; import './EditMail.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { checkAuthHandler } from 'src/actions/Session/sessionActions';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
import HtmlParser from 'react-html-parser';
const EditMail = props => { const EditMail = props => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -66,14 +69,14 @@ const EditMail = props => {
updateMail(updatedDomain, state.data.domain) updateMail(updatedDomain, state.data.domain)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
const { error_msg, ok_msg } = result.data; const { error_msg: errorMessage, ok_msg: okMessage } = result.data;
if (error_msg) { if (errorMessage) {
setState({ ...state, errorMessage: error_msg, okMessage: '', loading: false }); setState({ ...state, errorMessage, okMessage, loading: false });
} else if (ok_msg) {
setState({ ...state, errorMessage: '', okMessage: ok_msg, loading: false });
} else { } else {
setState({ ...state, loading: false }); dispatch(refreshCounters()).then(() => {
setState({ ...state, okMessage, errorMessage: '', loading: false });
});
} }
} }
}) })
@ -96,7 +99,7 @@ const EditMail = props => {
</div> </div>
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -62,7 +62,7 @@ const Mail = props => {
</Container> </Container>
<Container className="c-3"> <Container className="c-3">
{printStat(i18n['AntiSpam Support'], data.ANTISPAM)} {printStat(i18n['AntiSpam Support'], data.ANTISPAM)}
<div>{i18n['Catchall email']}: <span className="stat">{data.CATCHALL}</span></div> <div>{i18n['Catchall email']}: <span className="stat catchall-mail">{data.CATCHALL}</span></div>
</Container> </Container>
</div> </div>
</Container> </Container>

View file

@ -1,3 +1,7 @@
.crossed { .crossed {
text-decoration: line-through; text-decoration: line-through;
} }
.catchall-mail {
text-transform: none;
}

View file

@ -17,6 +17,8 @@ import { useDispatch, useSelector } from 'react-redux';
import './AddMailAccount.scss'; import './AddMailAccount.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
import HtmlParser from 'react-html-parser';
export default function AddMailAccount(props) { export default function AddMailAccount(props) {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
@ -26,6 +28,7 @@ export default function AddMailAccount(props) {
const [state, setState] = useState({ const [state, setState] = useState({
data: {}, data: {},
advancedOptions: false, advancedOptions: false,
autoreplyChecked: false,
quotaValue: '', quotaValue: '',
loading: false, loading: false,
password: '', password: '',
@ -54,15 +57,18 @@ export default function AddMailAccount(props) {
newMailDomain['Password'] = newMailDomain['v_password']; newMailDomain['Password'] = newMailDomain['v_password'];
if (Object.keys(newMailDomain).length !== 0 && newMailDomain.constructor === Object) { if (Object.keys(newMailDomain).length !== 0 && newMailDomain.constructor === Object) {
setState({ ...state, loading: true });
addMailAccount(newMailDomain, props.domain) addMailAccount(newMailDomain, props.domain)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
const { error_msg, ok_msg } = result.data; const { error_msg: errorMessage, ok_msg: okMessage } = result.data;
if (error_msg) { if (errorMessage) {
setState({ ...state, errorMessage: error_msg, okMessage: '' }); setState({ ...state, errorMessage, okMessage, loading: false });
} else if (ok_msg) { } else {
setState({ ...state, errorMessage: '', okMessage: ok_msg }); dispatch(refreshCounters()).then(() => {
setState({ ...state, okMessage, errorMessage: '', loading: false });
});
} }
} }
}) })
@ -114,7 +120,7 @@ export default function AddMailAccount(props) {
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''}
<span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -21,10 +21,25 @@
} }
} }
} }
.form-group:nth-child(3) {
> div {
display: flex;
input {
width: 100%;
}
input + button {
padding-left: 10px;
}
}
}
} }
.c-2 { .c-2 {
width: 45%; width: 45%;
height: 100%;
border: 1px solid #d9d9d9; border: 1px solid #d9d9d9;
padding: 0px 5px 12px 20px; padding: 0px 5px 12px 20px;
} }

View file

@ -15,6 +15,9 @@ import { useHistory } from 'react-router-dom';
import Spinner from '../../Spinner/Spinner'; import Spinner from '../../Spinner/Spinner';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { checkAuthHandler } from 'src/actions/Session/sessionActions';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
import HtmlParser from 'react-html-parser';
export default function EditMailAccount(props) { export default function EditMailAccount(props) {
const [autoreplyChecked, setAutoreplyChecked] = useState(false); const [autoreplyChecked, setAutoreplyChecked] = useState(false);
@ -56,13 +59,14 @@ export default function EditMailAccount(props) {
editMailAccount(newMailDomain, props.domain, props.account) editMailAccount(newMailDomain, props.domain, props.account)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
const { error_msg, ok_msg } = result.data; const { error_msg: errorMessage, ok_msg: okMessage } = result.data;
if (error_msg) { if (errorMessage) {
setState({ ...state, errorMessage: error_msg, okMessage: '', loading: false }); setState({ ...state, errorMessage, okMessage, loading: false });
} else if (ok_msg) { } else {
goBack(); dispatch(refreshCounters()).then(() => {
setState({ ...state, errorMessage: '', okMessage: ok_msg, loading: false }); setState({ ...state, okMessage, errorMessage: '', loading: false });
});
} }
} }
}) })
@ -88,12 +92,9 @@ export default function EditMailAccount(props) {
.catch(err => console.error(err)); .catch(err => console.error(err));
} }
const toggleQuotaValue = () => { const toggleQuota = () => {
if (state.quotaValue !== 'unlimited') { const value = state.data.quota === 'unlimited' ? '1000' : 'unlimited';
setState({ ...state, quotaValue: 'unlimited' }); setState({ ...state, data: { ...state.data, quota: value } });
} else {
setState({ ...state, quotaValue: '' });
}
} }
const goBack = () => { const goBack = () => {
@ -116,7 +117,7 @@ export default function EditMailAccount(props) {
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''}
<span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>
@ -135,13 +136,58 @@ export default function EditMailAccount(props) {
id="domain" id="domain"
disabled /> disabled />
<TextInput
title={i18n['Account']}
value={props.account}
name="v_account"
id="account" />
<Password name="v_password" onChange={password => setState({ ...state, password })} /> <Password name="v_password" onChange={password => setState({ ...state, password })} />
<TextInputWithExtraButton title={i18n['Quota']} optionalTitle={i18n['in megabytes']} id="quota" name="v_quota" value={state.data.quota}>
<button type="button" onClick={toggleQuota}>
<FontAwesomeIcon icon="infinity" />
</button>
</TextInputWithExtraButton>
<TextArea
optionalTitle={`${i18n['use local-part']}`}
defaultValue={state.data.aliases}
title={i18n['Aliases']}
name="v_aliases"
id="aliases" />
<TextArea
optionalTitle={`${i18n['one or more email addresses']}`}
defaultValue={state.data.fwd}
title={i18n['Forward to']}
name="v_fwd"
id="fwd" />
<Checkbox
title={i18n['Do not store forwarded mail']}
defaultChecked={state.data.fwd_only === 'yes'}
name="v_fwd_only"
id="fwd_only" />
<Checkbox
title={i18n['Autoreply']}
checked={autoreplyChecked}
onChange={checked => setAutoreplyChecked(checked)}
name="v_autoreply"
id="autoreply" />
{
autoreplyChecked && (
<div style={{ transform: 'translateX(3rem)' }}>
<TextArea
defaultValue={state.data.autoreply_message}
title={i18n['Message']}
name="v_autoreply_message"
id="autoreply_message" />
</div>
)
}
<TextInput
title={i18n['Send login credentials to email address']}
value={state.data.send_email}
name="v_credentials"
id="credentials" />
</div> </div>
<div className="c-2"> <div className="c-2">
@ -153,59 +199,6 @@ export default function EditMailAccount(props) {
</div> </div>
</div> </div>
<div className="r-2">
<TextInputWithExtraButton title={i18n['Quota']} optionalTitle={i18n['in megabytes']} id="quota" name="v_quota" value={state.data.quota}>
<button type="button" onClick={toggleQuotaValue}>
<FontAwesomeIcon icon="infinity" />
</button>
</TextInputWithExtraButton>
<TextArea
optionalTitle={`${i18n['use local-part']}`}
defaultValue={state.data.aliases}
title={i18n['Aliases']}
name="v_aliases"
id="aliases" />
<TextArea
optionalTitle={`${i18n['one or more email addresses']}`}
defaultValue={state.data.fwd}
title={i18n['Forward to']}
name="v_fwd"
id="fwd" />
<Checkbox
title={i18n['Do not store forwarded mail']}
defaultChecked={state.data.fwd_only === 'yes'}
name="v_fwd_only"
id="fwd_only" />
<Checkbox
title={i18n['Autoreply']}
checked={autoreplyChecked}
onChange={checked => setAutoreplyChecked(checked)}
name="v_fwd_only"
id="fwd_only" />
{
autoreplyChecked && (
<div style={{ transform: 'translateX(3rem)' }}>
<TextArea
defaultValue={state.data.autoreply_message}
title={i18n['Message']}
name="v_autoreply_message"
id="autoreply_message" />
</div>
)
}
<TextInput
title={i18n['Send login credentials to email address']}
value={state.data.send_email}
name="v_credentials"
id="credentials" />
</div>
<div className="buttons-wrapper"> <div className="buttons-wrapper">
<button type="submit" className="add">{i18n.Add}</button> <button type="submit" className="add">{i18n.Add}</button>
<button type="button" className="back" onClick={goBack}>{i18n.Back}</button> <button type="button" className="back" onClick={goBack}>{i18n.Back}</button>

View file

@ -1,3 +1,5 @@
$primary: #2c54ac;
.mail-info-block { .mail-info-block {
.select-group { .select-group {
select { select {
@ -5,7 +7,7 @@
margin-top: 5px; margin-top: 5px;
padding: 0; padding: 0;
border: none; border: none;
color: #2c9491; color: $primary;
text-transform: uppercase; text-transform: uppercase;
font-size: 11px; font-size: 11px;
font-weight: bold; font-weight: bold;

View file

@ -18,7 +18,8 @@ const MainNav = () => {
showTopNav: false showTopNav: false
}); });
const { userName, user, session: { look } } = useSelector(state => state.session); const { userName, session: { look } } = useSelector(state => state.session);
const { user } = useSelector(state => state.menuCounters);
const { activeElement, focusedElement, adminMenuTabs, userMenuTabs } = useSelector(state => state.mainNavigation); const { activeElement, focusedElement, adminMenuTabs, userMenuTabs } = useSelector(state => state.mainNavigation);
const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent); const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent);
const dispatch = useDispatch(); const dispatch = useDispatch();

View file

@ -5,6 +5,7 @@ import Bell from './Bell';
import BellUnread from './BellUnread'; import BellUnread from './BellUnread';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import './Notifications.scss'; import './Notifications.scss';
import HtmlParser from 'react-html-parser';
const Notifications = () => { const Notifications = () => {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
@ -13,8 +14,10 @@ const Notifications = () => {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
useEffect(() => { useEffect(() => {
fetchData(); if (!notifications) {
}, []); fetchData();
}
}, [notifications]);
const fetchData = () => { const fetchData = () => {
setLoading(true); setLoading(true);
@ -32,7 +35,7 @@ const Notifications = () => {
.catch(err => { .catch(err => {
console.error(err); console.error(err);
setLoading(false); setLoading(false);
}) });
} }
const removeNotification = id => { const removeNotification = id => {
@ -44,7 +47,7 @@ const Notifications = () => {
} }
const renderOptions = () => { const renderOptions = () => {
if (notifications.length) { if (notifications && notifications.length) {
return notifications.map(item => { return notifications.map(item => {
return ( return (
<> <>
@ -52,7 +55,7 @@ const Notifications = () => {
<span className="title"><b>{item.TOPIC}</b></span> <span className="title"><b>{item.TOPIC}</b></span>
<span className="delete-notification" onClick={() => removeNotification(item.ID)}></span> <span className="delete-notification" onClick={() => removeNotification(item.ID)}></span>
</div> </div>
<div dangerouslySetInnerHTML={{ __html: item.NOTICE }}></div> <div>{HtmlParser(item.NOTICE)}</div>
<div className="dropdown-divider"></div> <div className="dropdown-divider"></div>
</> </>
); );
@ -71,7 +74,7 @@ const Notifications = () => {
<button type="button" className="btn btn-danger dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <button type="button" className="btn btn-danger dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<div className="bell"> <div className="bell">
{ {
notifications.length notifications && notifications.length
? <BellUnread /> ? <BellUnread />
: <Bell /> : <Bell />
} }

View file

@ -56,7 +56,6 @@ const Panel = props => {
dispatch(logout()) dispatch(logout())
.then(() => { .then(() => {
history.push('/login/');
setLoading(false); setLoading(false);
}, },
error => { error => {
@ -69,7 +68,7 @@ const Panel = props => {
<div className="panel-wrapper"> <div className="panel-wrapper">
{loading && <Spinner />} {loading && <Spinner />}
<div className={`top-panel ${user ? 'long-profile' : ''}`}> <div className={`top-panel ${look ? 'long-profile' : ''}`}>
<div className="container left-menu"> <div className="container left-menu">
<div className="logo"> <div className="logo">
<Link to="/list/user/" onClick={() => dispatch(addActiveElement('/list/user/'))}> <Link to="/list/user/" onClick={() => dispatch(addActiveElement('/list/user/'))}>
@ -103,7 +102,7 @@ const Panel = props => {
<Link to="/list/firewall/" onClick={event => handleState("/list/firewall/", event)} onKeyPress={event => event.preventDefault()}>{i18n.Firewall}</Link> <Link to="/list/firewall/" onClick={event => handleState("/list/firewall/", event)} onKeyPress={event => event.preventDefault()}>{i18n.Firewall}</Link>
</div>} </div>}
</>)} </>)}
{session.session.FILEMANAGER_KEY && <div className={className("/list/directory/", "fm")}> {session.session.FILEMANAGER_KEY && <div className={className("/list/directory/")}>
<Link to="/list/directory/">{i18n['File Manager']}</Link> <Link to="/list/directory/">{i18n['File Manager']}</Link>
</div>} </div>}
{session.session.SOFTACULOUS === "yes" && <div className={className("/softaculous/")}><a href="/softaculous/">{i18n.Apps ?? 'Apps'}</a> {session.session.SOFTACULOUS === "yes" && <div className={className("/softaculous/")}><a href="/softaculous/">{i18n.Apps ?? 'Apps'}</a>

View file

@ -52,7 +52,7 @@ $textColor: #555;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
padding: 0 5px; padding: 0 10px !important;
width: 100%; width: 100%;
height: 100%; height: 100%;
text-decoration: none; text-decoration: none;
@ -93,14 +93,15 @@ $textColor: #555;
} }
.left-menu { .left-menu {
width: 80%; width: 75%;
padding-left: 0; padding-left: 0;
margin-left: 0;
justify-content: space-between;
div { div {
width: 7rem; flex: 1 1 auto;
height: 100%; height: 100%;
transform: translateX(-5px); transform: translateX(-5px);
padding-right: 5px;
&:hover { &:hover {
background: $secondaryLight; background: $secondaryLight;
@ -108,8 +109,19 @@ $textColor: #555;
} }
div.logo { div.logo {
img { width: 7rem;
width: 90%; padding-left: 0;
a {
div {
padding: 0;
width: 6rem;
flex: none;
img {
width: 90%;
}
}
} }
&:hover { &:hover {
@ -129,7 +141,7 @@ $textColor: #555;
} }
.profile-menu { .profile-menu {
width: 20%; width: auto;
div { div {
width: 4rem; width: 4rem;
@ -189,11 +201,24 @@ $textColor: #555;
.top-panel.long-profile { .top-panel.long-profile {
.left-menu { .left-menu {
width: 75%; justify-content: start;
> div {
width: max-content;
flex: unset;
padding: 0 1rem;
}
.logo {
width: 7rem;
padding: 0;
margin-right: 1rem;
}
} }
.profile-menu { .profile-menu {
width: 25%; justify-content: space-between;
align-items: center;
> div + div { > div + div {
width: max-content; width: max-content;

View file

@ -27,7 +27,8 @@ const style = ({ menuHeight, mobile }) => {
const Menu = props => { const Menu = props => {
const { activeElement, focusedElement } = useSelector(state => state.mainNavigation); const { activeElement, focusedElement } = useSelector(state => state.mainNavigation);
const { user, i18n, session: { look } } = useSelector(state => state.session); const { i18n, session: { look } } = useSelector(state => state.session);
const { user } = useSelector(state => state.menuCounters);
const dispatch = useDispatch(); const dispatch = useDispatch();
useEffect(() => { useEffect(() => {

View file

@ -81,12 +81,6 @@ $textColor: #555;
.servers-list, .servers-list,
.exclusions-list { .exclusions-list {
.l-menu { .l-menu {
&.server-icon {
a, span.add {
background: $primary;
}
}
&.backup-details-icon { &.backup-details-icon {
transform: translateX(2px); transform: translateX(2px);
} }

View file

@ -20,6 +20,14 @@ const SearchInput = props => {
return () => window.removeEventListener("keyup", focusInput); return () => window.removeEventListener("keyup", focusInput);
}, []); }, []);
const onSubmit = e => {
e.preventDefault();
if (searchTerm) {
handleClick();
}
}
const focusInput = event => { const focusInput = event => {
if (event.keyCode === 70) { if (event.keyCode === 70) {
return inputElement.current.focus(); return inputElement.current.focus();
@ -27,11 +35,13 @@ const SearchInput = props => {
} }
return ( return (
<div className="search-input-form"> <form onSubmit={onSubmit}>
<input type="text" className="form-control" onChange={e => setSearchTerm(e.target.value)} ref={inputElement} /> <div className="search-input-form">
<button className="btn btn-outline-secondary" type="submit" onClick={() => handleClick()}><FontAwesomeIcon icon="search" /></button> <input type="text" className="form-control" onChange={e => setSearchTerm(e.target.value)} ref={inputElement} />
</div> <button className="btn btn-outline-secondary" type="submit" onClick={() => handleClick()}><FontAwesomeIcon icon="search" /></button>
</div>
</form>
); );
} }
export default SearchInput; export default SearchInput;

View file

@ -4,7 +4,7 @@ import { values } from '../../../../ControlPanelService/Select';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import './Select.scss'; import './Select.scss';
const Select = props => { const Select = ({ cronReports, ...props }) => {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
const listValues = values(i18n); const listValues = values(i18n);
@ -44,6 +44,14 @@ const Select = props => {
const { list } = props; const { list } = props;
let activeList = state[list]; let activeList = state[list];
if (list === 'cronList') {
if (cronReports) {
activeList = activeList.filter((item, index) => index !== 0);
} else {
activeList = activeList.filter((item, index) => index !== 1);
}
}
if (list === 'statisticsList') { if (list === 'statisticsList') {
return props.users.map((item, index) => { return <option key={index} value={item}>{item}</option> }); return props.users.map((item, index) => { return <option key={index} value={item}>{item}</option> });
} else { } else {

View file

@ -1,3 +1,16 @@
$primary: #2c54ac;
$whiteBackground: #ececec;
$primary: #2c54ac;
$primaryLight: #d7dcef;
$primaryActive: #1e5cb2;
$secondary: #fcac04;
$secondaryLight: #f8b014;
$danger: #b00e5b;
$secondaryActive: #fdb51c;
$hoverButtonText: #2c54ac;
$activeButtonText: #fff;
$textColor: #555;
.toolbar { .toolbar {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@ -8,16 +21,17 @@
left: 0; left: 0;
width: 100%; width: 100%;
z-index: 1; z-index: 1;
padding: 0 13%; padding: 3px 10% 1px;
border-top: 1px solid #e0e0e0;
border-bottom: 1px solid #e0e0e0; border-bottom: 1px solid #e0e0e0;
padding-top: 5px;
.r-menu { .r-menu {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
a.button-extra, button.button-extra { a.button-extra,
button.button-extra {
background: none; background: none;
border: none; border: none;
padding: 0 0.75rem; padding: 0 0.75rem;
@ -27,9 +41,17 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
margin-right: 10px;
border-radius: 3px;
&:hover { &:hover {
color: rgb(78, 76, 76); background: $primaryLight;
color: $hoverButtonText;
}
&:active {
background: $primaryActive;
color: $activeButtonText;
} }
} }
@ -131,7 +153,7 @@
@media (max-width: 1350px) { @media (max-width: 1350px) {
.toolbar { .toolbar {
padding: 5px 10% 0; padding: 3px 10% 1px;
} }
} }

View file

@ -36,6 +36,8 @@ $black: #000;
margin-top: 100px; margin-top: 100px;
.modal-body { .modal-body {
overflow-wrap: anywhere;
font-size: 17px;
margin-bottom: 40px; margin-bottom: 40px;
input { input {

View file

@ -15,6 +15,8 @@ import { useDispatch, useSelector } from 'react-redux';
import './AddPackage.scss'; import './AddPackage.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
import HtmlParser from 'react-html-parser';
const AddPackage = props => { const AddPackage = props => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -89,18 +91,17 @@ const AddPackage = props => {
if (Object.keys(newPackage).length !== 0 && newPackage.constructor === Object) { if (Object.keys(newPackage).length !== 0 && newPackage.constructor === Object) {
setState({ ...state, loading: true }); setState({ ...state, loading: true });
addPackage(newPackage) addPackage(newPackage)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
const { error_msg, ok_msg } = result.data; const { error_msg: errorMessage, ok_msg: okMessage } = result.data;
if (error_msg) { if (errorMessage) {
setState({ ...state, errorMessage: error_msg, okMessage: '', loading: false }); setState({ ...state, errorMessage, okMessage, loading: false });
} else if (ok_msg) {
setState({ ...state, errorMessage: '', okMessage: ok_msg, loading: false });
} else { } else {
setState({ ...state, loading: false }) dispatch(refreshCounters()).then(() => {
setState({ ...state, okMessage, errorMessage: '', loading: false });
});
} }
} }
}) })
@ -141,7 +142,7 @@ const AddPackage = props => {
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''}
<span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -16,6 +16,9 @@ import QS from 'qs';
import './EditPackage.scss'; import './EditPackage.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { checkAuthHandler } from 'src/actions/Session/sessionActions';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
import HtmlParser from 'react-html-parser';
const EditPackage = props => { const EditPackage = props => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -70,9 +73,15 @@ const EditPackage = props => {
updatePackage(updatedPackage, state.data.package) updatePackage(updatedPackage, state.data.package)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
const { error_msg, ok_msg } = result.data; const { error_msg: errorMessage, ok_msg: okMessage } = result.data;
setState({ ...state, errorMessage: error_msg || '', okMessage: ok_msg || '', loading: false });
history.push('/list/package/'); if (errorMessage) {
setState({ ...state, errorMessage, okMessage, loading: false });
} else {
dispatch(refreshCounters()).then(() => {
setState({ ...state, okMessage, errorMessage: '', loading: false });
});
}
} }
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
@ -113,7 +122,7 @@ const EditPackage = props => {
</div> </div>
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -9,7 +9,6 @@ import { useSelector } from 'react-redux';
const Package = props => { const Package = props => {
const { data } = props; const { data } = props;
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token");
const printNameServers = servers => { const printNameServers = servers => {
let serversArray = servers.split(','); let serversArray = servers.split(',');
@ -32,7 +31,7 @@ const Package = props => {
} }
const handleDelete = () => { const handleDelete = () => {
props.handleModal(data.delete_conf, `/api/v1/delete/package?package=${data.NAME}`); props.handleModal(data.delete_conf, `/api/v1/delete/package/index.php?package=${data.NAME}`);
} }
return ( return (

View file

@ -5,13 +5,13 @@ import Dropdown from './Dropdown/Dropdown';
import './Path.scss'; import './Path.scss';
const Path = ({ path, isActive, className, openDirectory, changeSorting, sorting, order }) => { const Path = ({ path, isActive, className, openDirectory, changeSorting, sorting, order }) => {
const session = useSelector(state => state.session); const { user } = useSelector(state => state.menuCounters);
const clickablePath = () => { const clickablePath = () => {
let splitPath = path.split('/'); let splitPath = path.split('/');
splitPath.splice(0, 3); splitPath.splice(0, 3);
if (path !== session.user.HOME) { if (path !== user.HOME) {
return ( return (
splitPath.map((item, index) => <span className="clickable" key={index} onClick={() => openDirectoryHandler(index)}>&nbsp;/&nbsp;{item}</span>) splitPath.map((item, index) => <span className="clickable" key={index} onClick={() => openDirectoryHandler(index)}>&nbsp;/&nbsp;{item}</span>)
); );
@ -36,7 +36,7 @@ const Path = ({ path, isActive, className, openDirectory, changeSorting, sorting
<div className={className}> <div className={className}>
<div className="clickable-wrapper"> <div className="clickable-wrapper">
<span className="clickable-path"> <span className="clickable-path">
<span className="clickable" onClick={() => openDirectory(session.user.HOME)}>{session.user.HOME}</span> <span className="clickable" onClick={() => openDirectory(user.HOME)}>{user.HOME}</span>
{clickablePath()} {clickablePath()}
</span> </span>
</div> </div>

View file

@ -1,13 +1,54 @@
import React from 'react'; import React from 'react';
import { loginAs, logout } from 'src/actions/Session/sessionActions';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import ListItem from '../ControlPanel/ListItem/ListItem';
import Container from '../ControlPanel/Container/Container'; import Container from '../ControlPanel/Container/Container';
import { useSelector } from 'react-redux'; import ListItem from '../ControlPanel/ListItem/ListItem';
import { useDispatch, useSelector } from 'react-redux';
import { Link, useHistory } from 'react-router-dom';
import './SearchItem.scss'; import './SearchItem.scss';
import { Link } from 'react-router-dom';
const SearchItem = ({ data, handleModal }) => { const SearchItem = ({ data, handleModal }) => {
const { i18n } = useSelector(state => state.session); const { i18n, userName } = useSelector(state => state.session);
const dispatch = useDispatch();
const history = useHistory()
const signInAs = user => {
dispatch(loginAs(user)).then(() => history.push('/'));
}
const signOut = () => {
dispatch(logout()).then(() => history.push('/'));
}
const handleDelete = () => {
handleModal(data.delete_confirmation, `/api/v1/${data.TYPE === 'user' ? `/api/v1/delete/user/index.php?user=${data.USER}` : data.delete_link}`);
}
const handleSuspend = () => {
handleModal(data.spnd_confirmation, `/api/v1/${data.TYPE === 'user' ? `${data.spnd_action}/user/index.php?user=${data.USER}` : data.spnd_link}`);
}
const printLoginActionButton = () => {
if (data.TYPE !== 'user') return;
if (userName === data.USER) {
return (
<div>
<button onClick={signOut}>{i18n['Log out']}
{data.FOCUSED ? <span className="shortcut-button">L</span> : <FontAwesomeIcon icon="user-lock" />}
</button>
</div>
);
} else {
return (
<div>
<button onClick={() => signInAs(data.USER)}>{i18n['login as']} {data.USER}
{data.FOCUSED ? <span className="shortcut-button">L</span> : <FontAwesomeIcon icon="user-lock" />}
</button>
</div>
);
}
}
return ( return (
<ListItem date={data.DATE} suspended={data.SUSPENDED === 'yes'}> <ListItem date={data.DATE} suspended={data.SUSPENDED === 'yes'}>
@ -15,7 +56,7 @@ const SearchItem = ({ data, handleModal }) => {
<div className="name">{data.RESULT}</div> <div className="name">{data.RESULT}</div>
<div className="stats"> <div className="stats">
<Container className="c-1"> <Container className="c-1">
<div className="object">{i18n[data.object]}</div> <div className="object">{data.TYPE === 'user' ? i18n['USER'] : i18n[data.object]}</div>
</Container> </Container>
<Container className="c-2"> <Container className="c-2">
<div className="owner">{i18n.Owner}: <span>{data.USER}</span></div> <div className="owner">{i18n.Owner}: <span>{data.USER}</span></div>
@ -26,17 +67,20 @@ const SearchItem = ({ data, handleModal }) => {
</div> </div>
</Container> </Container>
<div className="actions"> <div className="actions">
{printLoginActionButton()}
<div><Link className="link-edit" to={data.edit_link}>{i18n.edit} <FontAwesomeIcon icon="pen" /></Link></div> <div><Link className="link-edit" to={data.edit_link}>{i18n.edit} <FontAwesomeIcon icon="pen" /></Link></div>
<div> <div>
<button <button
className="link-gray" className="link-gray"
onClick={() => handleModal(data.spnd_confirmation, '/api/v1' + data.spnd_link)}> onClick={handleSuspend}>
{data.spnd_action} {data.spnd_action}
<FontAwesomeIcon icon={data.SUSPENDED === 'yes' ? 'unlock' : 'lock'} /> <FontAwesomeIcon icon={data.SUSPENDED === 'yes' ? 'unlock' : 'lock'} />
</button> </button>
</div> </div>
<div> <div>
<button className="link-delete" onClick={() => this.props.handleModal(data.delete_confirmation, data, data.delete_link)}> <button
className="link-delete"
onClick={handleDelete}>
{i18n.Delete} {i18n.Delete}
<FontAwesomeIcon icon="times" /> <FontAwesomeIcon icon="times" />
</button> </button>

View file

@ -12,6 +12,7 @@ import { useDispatch, useSelector } from 'react-redux';
import './Bind9.scss'; import './Bind9.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import HtmlParser from 'react-html-parser';
const Bind9 = () => { const Bind9 = () => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -94,7 +95,7 @@ const Bind9 = () => {
</div> </div>
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -12,6 +12,7 @@ import { useDispatch, useSelector } from 'react-redux';
import './Dovecot.scss'; import './Dovecot.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import HtmlParser from 'react-html-parser';
const Dovecot = () => { const Dovecot = () => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -94,7 +95,7 @@ const Dovecot = () => {
</div> </div>
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -19,6 +19,7 @@ import { useDispatch, useSelector } from 'react-redux';
import './EditServer.scss'; import './EditServer.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import HtmlParser from 'react-html-parser';
const EditServer = props => { const EditServer = props => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -106,7 +107,7 @@ const EditServer = props => {
</div> </div>
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -12,6 +12,7 @@ import { useDispatch, useSelector } from 'react-redux';
import './EditHttpd.scss'; import './EditHttpd.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import HtmlParser from 'react-html-parser';
const EditHttpd = props => { const EditHttpd = props => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -89,7 +90,7 @@ const EditHttpd = props => {
</div> </div>
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -13,6 +13,7 @@ import { useDispatch, useSelector } from 'react-redux';
import './Mysql.scss'; import './Mysql.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import HtmlParser from 'react-html-parser';
const Mysql = ({ serviceName = '' }) => { const Mysql = ({ serviceName = '' }) => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -107,7 +108,7 @@ const Mysql = ({ serviceName = '' }) => {
</div> </div>
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -13,6 +13,7 @@ import { useDispatch, useSelector } from 'react-redux';
import './EditServerNginx.scss'; import './EditServerNginx.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import HtmlParser from 'react-html-parser';
const EditServerNginx = props => { const EditServerNginx = props => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -100,7 +101,7 @@ const EditServerNginx = props => {
</div> </div>
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -13,6 +13,7 @@ import { useDispatch, useSelector } from 'react-redux';
import './EditPhp.scss'; import './EditPhp.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import HtmlParser from 'react-html-parser';
const EditPhp = ({ serviceName = '' }) => { const EditPhp = ({ serviceName = '' }) => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -104,7 +105,7 @@ const EditPhp = ({ serviceName = '' }) => {
</div> </div>
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -12,6 +12,7 @@ import { useDispatch, useSelector } from 'react-redux';
import './Postgresql.scss'; import './Postgresql.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import HtmlParser from 'react-html-parser';
const Postgresql = () => { const Postgresql = () => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -94,7 +95,7 @@ const Postgresql = () => {
</div> </div>
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -12,6 +12,7 @@ import { useDispatch, useSelector } from 'react-redux';
import './Service.scss'; import './Service.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import HtmlParser from 'react-html-parser';
const Service = ({ serviceName = '' }) => { const Service = ({ serviceName = '' }) => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -100,7 +101,7 @@ const Service = ({ serviceName = '' }) => {
</div> </div>
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -10,10 +10,9 @@ import './TopPanel.scss';
const TopPanel = ({ menuItems = [], extraMenuItems = [] }) => { const TopPanel = ({ menuItems = [], extraMenuItems = [] }) => {
const mainNavigation = useSelector(state => state.mainNavigation); const mainNavigation = useSelector(state => state.mainNavigation);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const { i18n } = useSelector(state => state.session); const { i18n, userName } = useSelector(state => state.session);
const dispatch = useDispatch(); const dispatch = useDispatch();
const history = useHistory(); const history = useHistory();
const { userName } = useSelector(state => state.session);
const className = cls => { const className = cls => {
let className = 'nav-link'; let className = 'nav-link';

View file

@ -13,6 +13,9 @@ import { useDispatch, useSelector } from 'react-redux';
import './AddUser.scss'; import './AddUser.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { checkAuthHandler } from 'src/actions/Session/sessionActions';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
import HtmlParser from 'react-html-parser';
const AddUser = props => { const AddUser = props => {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
@ -71,19 +74,23 @@ const AddUser = props => {
} }
if (Object.keys(newUser).length !== 0 && newUser.constructor === Object) { if (Object.keys(newUser).length !== 0 && newUser.constructor === Object) {
setState({ ...state, loading: true });
addUser(newUser) addUser(newUser)
.then(result => { .then(result => {
if (result.status === 200) { const { error_msg: errorMessage, ok_msg: okMessage } = result.data;
const { error_msg, ok_msg } = result.data;
if (error_msg) { if (errorMessage) {
setState({ ...state, errorMessage: error_msg, okMessage: '' }); setState({ ...state, errorMessage, okMessage, loading: false });
} else if (ok_msg) { } else {
setState({ ...state, errorMessage: '', okMessage: ok_msg }); dispatch(refreshCounters()).then(() => {
} setState({ ...state, okMessage, errorMessage: '', loading: false });
});
} }
}) })
.catch(err => console.error(err)); .catch(err => {
setState({ ...state, loading: false });
console.error(err);
});
} }
} }
@ -133,7 +140,7 @@ const AddUser = props => {
<div className="search-toolbar-name">{i18n['Adding User']}</div> <div className="search-toolbar-name">{i18n['Adding User']}</div>
<div className="error"><span className="error-message">{state.errorMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} {state.errorMessage}</span></div> <div className="error"><span className="error-message">{state.errorMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} {state.errorMessage}</span></div>
<div className="success"> <div className="success">
<span className="ok-message">{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> </span> <span className="ok-message">{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span>{HtmlParser(state.okMessage)}</span> </span>
</div> </div>
</Toolbar> </Toolbar>
<AddItemLayout> <AddItemLayout>

View file

@ -15,6 +15,9 @@ import QS from 'qs';
import './EditUser.scss'; import './EditUser.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { checkAuthHandler } from 'src/actions/Session/sessionActions';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
import HtmlParser from 'react-html-parser';
const EditUser = props => { const EditUser = props => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -68,14 +71,14 @@ const EditUser = props => {
updateUser(updatedUser, state.username) updateUser(updatedUser, state.username)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
const { error_msg, ok_msg } = result.data; const { error_msg: errorMessage, ok_msg: okMessage } = result.data;
if (error_msg) { if (errorMessage) {
setState({ ...state, errorMessage: error_msg, okMessage: '', loading: false }); setState({ ...state, errorMessage, okMessage, loading: false });
} else if (ok_msg) {
setState({ ...state, errorMessage: '', okMessage: ok_msg, loading: false });
} else { } else {
setState({ ...state, loading: false }); dispatch(refreshCounters()).then(() => {
setState({ ...state, okMessage, errorMessage: '', loading: false });
});
} }
} }
}) })
@ -103,7 +106,7 @@ const EditUser = props => {
<div className="search-toolbar-name">{i18n['Editing User']}</div> <div className="search-toolbar-name">{i18n['Editing User']}</div>
<div className="error"><span className="error-message">{state.data.errorMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} {state.errorMessage}</span></div> <div className="error"><span className="error-message">{state.data.errorMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} {state.errorMessage}</span></div>
<div className="success"> <div className="success">
<span className="ok-message">{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> </span> <span className="ok-message">{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span>{HtmlParser(state.okMessage)}</span> </span>
</div> </div>
</Toolbar> </Toolbar>
<AddItemLayout date={state.data.date} time={state.data.time} status={state.data.status}> <AddItemLayout date={state.data.date} time={state.data.time} status={state.data.status}>

View file

@ -9,9 +9,8 @@ import { Link } from 'react-router-dom';
import './User.scss'; import './User.scss';
const User = ({ data, toggleFav, handleModal, checkItem }) => { const User = ({ data, toggleFav, handleModal, checkItem }) => {
const { i18n } = useSelector(state => state.session); const { i18n, userName } = useSelector(state => state.session);
const session = useSelector(state => state.session); const session = useSelector(state => state.session);
const token = localStorage.getItem("token");
const dispatch = useDispatch(); const dispatch = useDispatch();
const printNameServers = servers => { const printNameServers = servers => {

View file

@ -39,6 +39,7 @@ $textColor: #555;
span.stat.email{ span.stat.email{
display: block; display: block;
width: max-content;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;

View file

@ -13,6 +13,8 @@ import { useDispatch, useSelector } from 'react-redux';
import './AddWebDomain.scss'; import './AddWebDomain.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
import HtmlParser from 'react-html-parser';
const AddWebDomain = props => { const AddWebDomain = props => {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
@ -37,7 +39,6 @@ const AddWebDomain = props => {
dispatch(removeFocusedElement()); dispatch(removeFocusedElement());
setState({ ...state, loading: true }); setState({ ...state, loading: true });
Promise.all([getWebStats(), getIpList()]) Promise.all([getWebStats(), getIpList()])
.then(result => { .then(result => {
const [webStats, internetProtocols] = result; const [webStats, internetProtocols] = result;
@ -94,12 +95,14 @@ const AddWebDomain = props => {
addWeb(newWebDomain) addWeb(newWebDomain)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
const { error_msg, ok_msg } = result.data; const { error_msg: errorMessage, ok_msg: okMessage } = result.data;
if (error_msg) { if (errorMessage) {
setState({ ...state, errorMessage: error_msg, okMessage: '', loading: false }); setState({ ...state, errorMessage, okMessage, loading: false });
} else if (ok_msg) { } else {
setState({ ...state, errorMessage: '', okMessage: ok_msg, loading: false }); dispatch(refreshCounters()).then(() => {
setState({ ...state, okMessage, errorMessage: '', loading: false });
});
} }
} }
}) })
@ -123,7 +126,7 @@ const AddWebDomain = props => {
<div className="success"> <div className="success">
<span className="ok-message"> <span className="ok-message">
{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} {state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''}
<span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> <span>{HtmlParser(state.okMessage)}</span>
</span> </span>
</div> </div>
</Toolbar> </Toolbar>

View file

@ -5,10 +5,10 @@ import Password from '../../../../components/ControlPanel/AddItemLayout/Form/Pas
import './AdditionalFtpForEditing.scss'; import './AdditionalFtpForEditing.scss';
const AdditionalFtpForEditing = ({ domain, data = {}, onDeleteAdditionalFtp, prefixI18N, prePath, checked }) => { const AdditionalFtpForEditing = ({ domain, data = {}, onDeleteAdditionalFtp, prefixI18N, prePath, checked, ...props }) => {
const { userName, i18n } = useSelector(state => state.session); const { i18n, userName } = useSelector(state => state.session);
const [state, setState] = useState({ const [state, setState] = useState({
username: data.v_ftp_user, username: data.v_ftp_user || '',
path: '' path: ''
}); });
@ -29,72 +29,73 @@ const AdditionalFtpForEditing = ({ domain, data = {}, onDeleteAdditionalFtp, pre
return <></>; return <></>;
} }
return (<div className="additional-ftp"> return (
<div className="title"> <div className="additional-ftp">
<input type="hidden" name={`v_ftp_user[${data.id}][delete]`} value="0" /> <div className="title">
<input type="hidden" name={`v_ftp_user[${data.id}][is_new]`} value="1" /> <input type="hidden" name={`v_ftp_user[${data.id}][delete]`} value="0" />
<input type="hidden" name={`v_ftp_user[${data.id}][is_new]`} value="1" />
<span className="data.indexed-name">{i18n.FTP} #{data.id + 1}</span> <span className="data.indexed-name">{i18n.FTP} #{data.id + 1}</span>
<span> <span>
&nbsp; &nbsp;
<button <button
type="button" type="button"
onClick={() => onDeleteAdditionalFtp(data.id)}> onClick={() => onDeleteAdditionalFtp(data.id)}>
({i18n.Delete ?? 'Delete'}) ({i18n.Delete ?? 'Delete'})
</button> </button>
</span> </span>
</div>
<div className="form-transform">
<div className="form-group username">
<label htmlFor={`ftp_user_${data.id}`}>{i18n.Username}</label>
<span className="prefix-note">{prefixI18N}</span>
<div className="input-wrapper">
<input
defaultValue={state.username}
onChange={event => setState({ ...state, username: event.target.value })}
type="text"
disabled={data.v_ftp_user}
className="form-control"
id={`ftp_user_${data.id}`}
name={`v_ftp_user[${data.id}][v_ftp_user]`} />
<span>{`${userName}_${state.username}`}</span>
</div>
</div> </div>
<Password name={`v_ftp_user[${data.id}][v_ftp_password]`} id={data.id} /> <div className="form-transform">
<div className="form-group username">
<div className="form-group"> <label htmlFor={`ftp_user_${data.id}`}>{i18n.Username}</label>
<input type="hidden" name="v_ftp_pre_path" value={prePath} /> <span className="prefix-note">{prefixI18N}</span>
<input type="hidden" name={`v_ftp_user[${data.id}][v_ftp_path_prev]`} value={data.v_ftp_path !== '/' ? '/' : ''} /> <div className="input-wrapper">
<label htmlFor={`path${data.id}`}>{i18n.Path}</label>
<input
type="text"
value={state.path}
onChange={event => setState({ ...state, path: event.target.value })}
className="form-control"
id={`path${data.id}`}
name={`v_ftp_user[${data.id}][v_ftp_path]`} />
<span className="path-note">{`${data.v_ftp_pre_path ? data.v_ftp_pre_path : ''}/${state.path}`}</span>
</div>
{
data.is_new === 1 && (
<div className="form-group">
<label htmlFor={`sendLoginCredentialsToEmailAddress_${data.id}`}>{i18n['Send login credentials to email address']}</label>
<input <input
type="email" defaultValue={state.username}
onChange={event => setState({ ...state, username: event.target.value })}
type="text"
disabled={data.v_ftp_user}
className="form-control" className="form-control"
id={`sendLoginCredentialsToEmailAddress_${data.id}`} id={`ftp_user_${data.id}`}
defaultValue={data.v_ftp_email} name={`v_ftp_user[${data.id}][v_ftp_user]`} />
name={`v_ftp_user[${data.id}][v_ftp_email]`} /> <span>{data.v_ftp_user ? data.v_ftp_user : `${userName}_${state.username}`}</span>
</div> </div>
) </div>
}
</div> <Password name={`v_ftp_user[${data.id}][v_ftp_password]`} id={data.id} />
</div >);
<div className="form-group">
<input type="hidden" name="v_ftp_pre_path" value={prePath} />
<input type="hidden" name={`v_ftp_user[${data.id}][v_ftp_path_prev]`} value={data.v_ftp_path !== '/' ? '/' : ''} />
<label htmlFor={`path${data.id}`}>{i18n.Path}</label>
<input
type="text"
value={state.path}
onChange={event => setState({ ...state, path: event.target.value })}
className="form-control"
id={`path${data.id}`}
name={`v_ftp_user[${data.id}][v_ftp_path]`} />
<span className="path-note">{prePath}</span>
</div>
{
data.is_new === 1 && (
<div className="form-group">
<label htmlFor={`sendLoginCredentialsToEmailAddress_${data.id}`}>{i18n['Send login credentials to email address']}</label>
<input
type="email"
className="form-control"
id={`sendLoginCredentialsToEmailAddress_${data.id}`}
defaultValue={data.v_ftp_email}
name={`v_ftp_user[${data.id}][v_ftp_email]`} />
</div>
)
}
</div>
</div >);
} }
return <></>; return <></>;

View file

@ -1,34 +1,35 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import AdditionalFtp from '../AdditionalFtp/AdditionalFtp';
import AdditionalFtpForEditing from '../AdditionalFtpForEditing/AdditionalFtpForEditing'; import AdditionalFtpForEditing from '../AdditionalFtpForEditing/AdditionalFtpForEditing';
import './AdditionalFtpWrapper.scss';
const AdditionalFtpWrapper = props => { const AdditionalFtpWrapper = ({ checked, ftps, unCheckAdditionalFtpBox, prefixI18N, ftpUserPrePath, domain, ...props }) => {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
const [state, setState] = useState({ const [state, setState] = useState({
additionalFtp: [] additionalFtp: []
}); });
useEffect(() => { useEffect(() => {
if (props.ftps) { if (ftps) {
const data = props.ftps.map((item, index) => { const data = ftps.map((item, index) => {
item['deleted'] = false; item['deleted'] = !checked;
item['id'] = index; item['id'] = index;
return item; return item;
}); });
setState({ ...state, additionalFtp: data }); setState({ ...state, additionalFtp: data });
} }
}, [props.ftps]); }, [checked, ftps]);
const renderAdditionalFtps = () => { const renderAdditionalFtps = () => {
return state.additionalFtp.map(ftp => { return state.additionalFtp.map(ftp => {
return <AdditionalFtpForEditing return <AdditionalFtpForEditing
key={ftp.id} key={ftp.id}
prefixI18N={props.prefixI18N} prefixI18N={prefixI18N}
data={ftp} data={ftp}
checked={props.checked} checked={checked}
prePath={props.ftpUserPrePath} prePath={ftpUserPrePath}
domain={props.domain} domain={domain}
onDeleteAdditionalFtp={id => onDeleteFtp(id)} />; onDeleteAdditionalFtp={id => onDeleteFtp(id)} />;
}); });
} }
@ -45,7 +46,7 @@ const AdditionalFtpWrapper = props => {
}); });
if (!updatedAdditionalFtps.length) { if (!updatedAdditionalFtps.length) {
props.unCheckAdditionalFtpBox(); unCheckAdditionalFtpBox();
} }
setState({ ...state, additionalFtp: updatedAdditionalFtps }); setState({ ...state, additionalFtp: updatedAdditionalFtps });
@ -64,7 +65,7 @@ const AdditionalFtpWrapper = props => {
<div> <div>
{renderAdditionalFtps()} {renderAdditionalFtps()}
{props.checked && ( {checked && (
<button type="button" onClick={() => addAdditionalFtp()}> <button type="button" onClick={() => addAdditionalFtp()}>
{i18n['Add one more FTP Account'] ?? 'Add'} {i18n['Add one more FTP Account'] ?? 'Add'}
</button>)} </button>)}

View file

@ -0,0 +1,48 @@
.additional-ftp {
.title {
span:nth-child(1) {
color: #555;
font-size: 15px;
font-weight: bold;
}
}
.form-transform {
margin-top: 15px;
transform: translateX(3rem);
.form-group.username {
display: flex;
flex-direction: column;
label {
margin: 0;
}
span {
font-size: 10pt;
color: #777;
font-weight: bold;
margin-bottom: 10px;
}
.input-wrapper {
display: flex;
align-items: center;
span {
color: #777;
font-size: 15px;
font-style: italic;
font-weight: normal;
margin-left: 15px;
}
}
}
}
.path-note {
font-weight: bold;
color: #555;
}
}

View file

@ -18,6 +18,9 @@ import QS from 'qs';
import './EditWeb.scss'; import './EditWeb.scss';
import TextArea from '../../ControlPanel/AddItemLayout/Form/TextArea/TextArea'; import TextArea from '../../ControlPanel/AddItemLayout/Form/TextArea/TextArea';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { checkAuthHandler } from 'src/actions/Session/sessionActions';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
import HtmlParser from 'react-html-parser';
const EditWeb = props => { const EditWeb = props => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -83,14 +86,14 @@ const EditWeb = props => {
updateWebDomain(updatedDomain, state.domain) updateWebDomain(updatedDomain, state.domain)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
const { error_msg, ok_msg } = result.data; const { error_msg: errorMessage, ok_msg: okMessage } = result.data;
if (error_msg) { if (errorMessage) {
setState({ ...state, errorMessage: error_msg, okMessage: '', loading: false }); setState({ ...state, errorMessage, okMessage, loading: false });
} else if (ok_msg) {
setState({ ...state, errorMessage: '', okMessage: ok_msg, loading: false });
} else { } else {
setState({ ...state, loading: false }); dispatch(refreshCounters()).then(() => {
setState({ ...state, okMessage, errorMessage: '', loading: false });
});
} }
} }
}) })
@ -134,7 +137,7 @@ const EditWeb = props => {
<div className="search-toolbar-name">{i18n['Editing Domain']}</div> <div className="search-toolbar-name">{i18n['Editing Domain']}</div>
<div className="error"><span className="error-message">{state.data.errorMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} {state.errorMessage}</span></div> <div className="error"><span className="error-message">{state.data.errorMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} {state.errorMessage}</span></div>
<div className="success"> <div className="success">
<span className="ok-message">{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span dangerouslySetInnerHTML={{ __html: state.okMessage }}></span> </span> <span className="ok-message">{state.okMessage ? <FontAwesomeIcon icon="long-arrow-alt-right" /> : ''} <span>{HtmlParser(state.okMessage)}</span> </span>
</div> </div>
</Toolbar> </Toolbar>
<AddItemLayout date={state.data.date} time={state.data.time} status={state.data.status}> <AddItemLayout date={state.data.date} time={state.data.time} status={state.data.status}>

View file

@ -93,10 +93,10 @@ export default function WebDomain(props) {
</Link> </Link>
</div> </div>
<div> <div>
<a className="link-gray" href={`/list/web-log?domain=${data.NAME}&type=access`}> <Link className="link-gray" to={`/list/web-log?domain=${data.NAME}&type=access`}>
{i18n['view logs']} {i18n['view logs']}
{data.FOCUSED ? <span className="shortcut-button">L</span> : <FontAwesomeIcon icon="list" />} {data.FOCUSED ? <span className="shortcut-button">L</span> : <FontAwesomeIcon icon="list" />}
</a> </Link>
</div> </div>
{ {
data.STATS && ( data.STATS && (

View file

@ -22,7 +22,7 @@
align-items: center; align-items: center;
> div:nth-child(1) { > div:nth-child(1) {
width: 34%; margin-right: 2rem;
} }
.dns-name-span { .dns-name-span {

View file

@ -71,10 +71,6 @@ const App = () => {
useEffect(() => { useEffect(() => {
if (!Object.entries(session.i18n).length) { if (!Object.entries(session.i18n).length) {
dispatch(checkAuthHandler()).then(token => { dispatch(checkAuthHandler()).then(token => {
if (token) {
setAuthToken(token);
}
setLoading(false); setLoading(false);
}); });
} }

View file

@ -10,6 +10,10 @@ $hoverButtonText: #2c54ac;
$activeButtonText: #fff; $activeButtonText: #fff;
$textColor: #555; $textColor: #555;
html {
overflow-y: scroll;
}
.App { .App {
font-size: 25px; font-size: 25px;
font-family: Arial; font-family: Arial;

View file

@ -16,13 +16,14 @@ import Backup from '../../components/Backup/Backup';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import './Backups.scss'; import './Backups.scss';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
const Backups = props => { const Backups = props => {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token");
const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent); const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent);
const { focusedElement } = useSelector(state => state.mainNavigation); const { focusedElement } = useSelector(state => state.mainNavigation);
const dispatch = useDispatch(); const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
const [modal, setModal] = useState({ const [modal, setModal] = useState({
text: '', text: '',
visible: false, visible: false,
@ -31,7 +32,6 @@ const Backups = props => {
const [state, setState] = useState({ const [state, setState] = useState({
backups: [], backups: [],
backupFav: [], backupFav: [],
loading: true,
toggledAll: false, toggledAll: false,
selection: [], selection: [],
totalAmount: '' totalAmount: ''
@ -41,7 +41,7 @@ const Backups = props => {
dispatch(addActiveElement('/list/backup/')); dispatch(addActiveElement('/list/backup/'));
dispatch(removeFocusedElement()); dispatch(removeFocusedElement());
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
fetchData(); fetchData().then(() => setLoading(false));
return () => { return () => {
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
@ -146,7 +146,7 @@ const Backups = props => {
} }
const download = () => { const download = () => {
props.history.push(`/download/backup?backup=${controlPanelFocusedElement}`); window.open(`/api/v1/download/backup?backup=${controlPanelFocusedElement}`);
} }
const handleDelete = () => { const handleDelete = () => {
@ -157,19 +157,22 @@ const Backups = props => {
} }
const fetchData = () => { const fetchData = () => {
getBackupList() setLoading(true);
.then(result => { return new Promise((resolve, reject) => {
setState({ getBackupList()
...state, .then(result => {
backups: reformatData(result.data.data), setState({
backupFav: result.data.backup_fav, ...state,
totalAmount: result.data.totalAmount, backups: reformatData(result.data.data),
selection: [], backupFav: result.data.backup_fav,
toggledAll: false, totalAmount: result.data.totalAmount,
loading: false selection: [],
}); toggledAll: false
}) });
.catch(err => console.error(err)); resolve();
})
.catch(err => console.error(err));
});
} }
const reformatData = data => { const reformatData = data => {
@ -278,12 +281,14 @@ const Backups = props => {
const { selection } = state; const { selection } = state;
if (selection.length && action) { if (selection.length && action) {
setState({ ...state, loading: true }); setLoading(true);
bulkAction(action, selection) bulkAction(action, selection)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
fetchData(); fetchData().then(() => {
toggleAll(false); refreshMenuCounters();
toggleAll(false);
});
} }
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
@ -291,7 +296,7 @@ const Backups = props => {
} }
const displayModal = (text, url) => { const displayModal = (text, url) => {
setState({ ...state, loading: false }); setLoading(false);
setModal({ setModal({
...modal, ...modal,
visible: true, visible: true,
@ -301,13 +306,25 @@ const Backups = props => {
} }
const modalConfirmHandler = () => { const modalConfirmHandler = () => {
if (!modal.actionUrl) return; if (!modal.actionUrl) {
return modalCancelHandler();
}
modalCancelHandler(); modalCancelHandler();
setLoading(true);
handleAction(modal.actionUrl) handleAction(modal.actionUrl)
.then(() => fetchData()) .then(res => {
.catch(err => console.error(err)); if (res.data.error) {
setLoading(false);
return displayModal(res.data.error, '');
}
fetchData().then(() => refreshMenuCounters())
})
.catch(err => { setLoading(false); console.error(err); });
}
const refreshMenuCounters = () => {
dispatch(refreshCounters()).then(() => setLoading(false));
} }
const modalCancelHandler = () => { const modalCancelHandler = () => {
@ -320,10 +337,15 @@ const Backups = props => {
} }
const scheduleBackupButton = () => { const scheduleBackupButton = () => {
setState({ ...state, loading: true }); setLoading(true);
scheduleBackup() scheduleBackup()
.then(result => displayModal(result.data.error_msg, '')) .then(result => {
if (result.data.error) {
displayModal(result.data.error, '');
} else {
displayModal(result.data.ok, '');
}
})
.catch(err => console.error(err)); .catch(err => console.error(err));
} }
@ -349,9 +371,13 @@ const Backups = props => {
</div> </div>
</Toolbar> </Toolbar>
<div className="backups-wrapper"> <div className="backups-wrapper">
{state.loading ? <Spinner /> : backups()} {loading
? <Spinner />
: (<>
{backups()}
<div className="total">{state.totalAmount}</div>
</>)}
</div> </div>
<div className="total">{state.totalAmount}</div>
<Modal <Modal
onSave={modalConfirmHandler} onSave={modalConfirmHandler}
onCancel={modalCancelHandler} onCancel={modalCancelHandler}

View file

@ -66,10 +66,10 @@ const ControlPanelContent = props => {
const dispatch = useDispatch(); const dispatch = useDispatch();
useEffect(() => { useEffect(() => {
if (userName) { if (!userName) {
setLoading(false); return history.push('/login');
} else { } else {
history.push('/login'); setLoading(false);
} }
if (look) { if (look) {
@ -102,7 +102,6 @@ const ControlPanelContent = props => {
return; return;
} }
console.log(event);
switch (event.keyCode) { switch (event.keyCode) {
case 49: return history.push('/list/user/'); case 49: return history.push('/list/user/');
case 50: return history.push('/list/web/'); case 50: return history.push('/list/web/');
@ -200,7 +199,7 @@ const ControlPanelContent = props => {
}) })
} }
<Route path="/list/user" component={props => <Users changeSearchTerm={handleSearchTerm} loading={loading} {...props} />} /> <Route path="/list/user" component={props => <Users changeSearchTerm={handleSearchTerm} {...props} />} />
<Route path="/add/user" component={() => <AddUser />} /> <Route path="/add/user" component={() => <AddUser />} />
<Route path="/edit/user" component={() => <EditUser />} /> <Route path="/edit/user" component={() => <EditUser />} />
<Route path="/list/web" component={props => <Web {...props} changeSearchTerm={handleSearchTerm} />} /> <Route path="/list/web" component={props => <Web {...props} changeSearchTerm={handleSearchTerm} />} />

View file

@ -16,13 +16,14 @@ import Spinner from '../../components/Spinner/Spinner';
import { useSelector, useDispatch } from 'react-redux'; import { useSelector, useDispatch } from 'react-redux';
import './CronJobs.scss'; import './CronJobs.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
const CronJobs = props => { const CronJobs = props => {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token");
const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent); const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent);
const { focusedElement } = useSelector(state => state.mainNavigation); const { focusedElement } = useSelector(state => state.mainNavigation);
const dispatch = useDispatch(); const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
const [modal, setModal] = useState({ const [modal, setModal] = useState({
text: '', text: '',
visible: false, visible: false,
@ -31,7 +32,6 @@ const CronJobs = props => {
const [state, setState] = useState({ const [state, setState] = useState({
cronJobs: [], cronJobs: [],
cronFav: [], cronFav: [],
loading: true,
toggledAll: false, toggledAll: false,
cronReports: '', cronReports: '',
sorting: i18n.Date, sorting: i18n.Date,
@ -44,7 +44,7 @@ const CronJobs = props => {
dispatch(addActiveElement('/list/cron/')); dispatch(addActiveElement('/list/cron/'));
dispatch(removeFocusedElement()); dispatch(removeFocusedElement());
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
fetchData(); fetchData().then(() => setLoading(false));
return () => { return () => {
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
@ -164,20 +164,23 @@ const CronJobs = props => {
} }
const fetchData = () => { const fetchData = () => {
getCronList() setLoading(true);
.then(result => { return new Promise((resolve, reject) => {
setState({ getCronList()
...state, .then(result => {
cronJobs: reformatData(result.data.data), setState({
cronReports: result.data.cron_reports, ...state,
cronFav: result.data.cron_fav, cronJobs: reformatData(result.data.data),
selection: [], cronReports: result.data.cron_reports,
toggledAll: false, cronFav: result.data.cron_fav,
totalAmount: result.data.totalAmount, selection: [],
loading: false toggledAll: false,
}); totalAmount: result.data.totalAmount
}) });
.catch(err => console.error(err)); resolve();
})
.catch(err => console.error(err));
});
} }
const reformatData = data => { const reformatData = data => {
@ -316,13 +319,21 @@ const CronJobs = props => {
const bulk = action => { const bulk = action => {
const { selection } = state; const { selection } = state;
const notifications = state.cronReports === 'yes' ? 'delete-cron-reports' : 'add-cron-reports';
if (action === notifications) {
return handleCronNotifications();
}
if (selection.length && action) { if (selection.length && action) {
setLoading(true);
bulkAction(action, selection) bulkAction(action, selection)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
fetchData(); fetchData().then(() => {
toggleAll(false); refreshMenuCounters();
toggleAll(false);
});
} }
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
@ -340,15 +351,24 @@ const CronJobs = props => {
const modalConfirmHandler = () => { const modalConfirmHandler = () => {
if (!modal.actionUrl) { if (!modal.actionUrl) {
modalCancelHandler(); return modalCancelHandler();
} }
setState({ ...state, loading: true });
modalCancelHandler(); modalCancelHandler();
setLoading(true);
handleAction(modal.actionUrl) handleAction(modal.actionUrl)
.then(() => fetchData()) .then(res => {
.catch(err => console.error(err)); if (res.data.error) {
setLoading(false);
return displayModal(res.data.error, '');
}
fetchData().then(() => refreshMenuCounters())
})
.catch(err => { setLoading(false); console.error(err); });
}
const refreshMenuCounters = () => {
dispatch(refreshCounters()).then(() => setLoading(false));
} }
const modalCancelHandler = () => { const modalCancelHandler = () => {
@ -385,16 +405,20 @@ const CronJobs = props => {
{state.cronReports === 'yes' ? i18n['turn off notifications'] : i18n['turn on notifications']} {state.cronReports === 'yes' ? i18n['turn off notifications'] : i18n['turn on notifications']}
</button> </button>
<Checkbox toggleAll={toggleAll} toggled={state.toggledAll} /> <Checkbox toggleAll={toggleAll} toggled={state.toggledAll} />
<Select list='cronList' bulkAction={bulk} /> <Select list='cronList' bulkAction={bulk} cronReports={state.cronReports === 'yes'} />
<DropdownFilter changeSorting={changeSorting} sorting={state.sorting} order={state.order} list="cronList" /> <DropdownFilter changeSorting={changeSorting} sorting={state.sorting} order={state.order} list="cronList" />
<SearchInput handleSearchTerm={term => props.changeSearchTerm(term)} /> <SearchInput handleSearchTerm={term => props.changeSearchTerm(term)} />
</div> </div>
</div> </div>
</Toolbar> </Toolbar>
<div className="cron-wrapper"> <div className="cron-wrapper">
{state.loading ? <Spinner /> : cronJobs()} {loading
? <Spinner />
: (<>
{cronJobs()}
<div className="total">{state.totalAmount}</div>
</>)}
</div> </div>
<div className="total">{state.totalAmount}</div>
<Modal <Modal
showCancelButton={modal.actionUrl} showCancelButton={modal.actionUrl}
onCancel={modalCancelHandler} onCancel={modalCancelHandler}

View file

@ -17,14 +17,15 @@ import QueryString from 'qs';
import './DNSRecords.scss'; import './DNSRecords.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
export default function DnsRecords(props) { export default function DnsRecords(props) {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem('token');
const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent); const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent);
const { focusedElement } = useSelector(state => state.mainNavigation); const { focusedElement } = useSelector(state => state.mainNavigation);
const dispatch = useDispatch(); const dispatch = useDispatch();
const history = useHistory(); const history = useHistory();
const [loading, setLoading] = useState(false);
const [modal, setModal] = useState({ const [modal, setModal] = useState({
text: '', text: '',
visible: false, visible: false,
@ -34,7 +35,6 @@ export default function DnsRecords(props) {
dnsRecords: [], dnsRecords: [],
dnsRecordFav: [], dnsRecordFav: [],
domain: '', domain: '',
loading: true,
toggledAll: false, toggledAll: false,
sorting: i18n.Date, sorting: i18n.Date,
order: "descending", order: "descending",
@ -44,7 +44,7 @@ export default function DnsRecords(props) {
useEffect(() => { useEffect(() => {
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
fetchData(); fetchData().then(() => setLoading(false));
return () => { return () => {
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
@ -156,23 +156,23 @@ export default function DnsRecords(props) {
const fetchData = () => { const fetchData = () => {
let parsedQueryString = QueryString.parse(history.location.search, { ignoreQueryPrefix: true }); let parsedQueryString = QueryString.parse(history.location.search, { ignoreQueryPrefix: true });
setLoading(true);
setState({ ...state, loading: true }); return new Promise((resolve, reject) => {
getDNSRecordsList(parsedQueryString.domain || '')
getDNSRecordsList(parsedQueryString.domain || '') .then(result => {
.then(result => { setState({
setState({ ...state,
...state, dnsRecords: reformatData(result.data.data),
dnsRecords: reformatData(result.data.data), dnsRecordFav: result.data.dnsRecordsFav,
dnsRecordFav: result.data.dnsRecordsFav, totalAmount: result.data.totalAmount,
totalAmount: result.data.totalAmount, domain: parsedQueryString.domain,
domain: parsedQueryString.domain, toggledAll: false,
toggledAll: false, selection: []
selection: [], });
loading: false resolve();
}); })
}) .catch(err => console.error(err));
.catch(err => console.error(err)); });
} }
const reformatData = data => { const reformatData = data => {
@ -281,11 +281,14 @@ export default function DnsRecords(props) {
const { selection } = state; const { selection } = state;
if (selection.length && action) { if (selection.length && action) {
bulkAction(action, selection) setLoading(true);
bulkAction(action, selection, state.domain)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
fetchData(); fetchData().then(() => {
toggleAll(false); refreshMenuCounters();
toggleAll(false);
});
} }
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
@ -302,12 +305,25 @@ export default function DnsRecords(props) {
} }
const modalConfirmHandler = () => { const modalConfirmHandler = () => {
if (!modal.actionUrl) {
return modalCancelHandler();
}
modalCancelHandler();
setLoading(true);
handleAction(modal.actionUrl) handleAction(modal.actionUrl)
.then(() => { .then(res => {
fetchData(); if (res.data.error) {
modalCancelHandler(); setLoading(false);
return displayModal(res.data.error, '');
}
fetchData().then(() => refreshMenuCounters())
}) })
.catch(err => console.error(err)); .catch(err => { setLoading(false); console.error(err); });
}
const refreshMenuCounters = () => {
dispatch(refreshCounters()).then(() => setLoading(false));
} }
const modalCancelHandler = () => { const modalCancelHandler = () => {
@ -334,7 +350,7 @@ export default function DnsRecords(props) {
</div> </div>
</div> </div>
</Toolbar> </Toolbar>
{state.loading {loading
? <Spinner /> ? <Spinner />
: ( : (
<> <>

View file

@ -70,6 +70,7 @@ $textColor: #555;
display: flex; display: flex;
align-items: center; align-items: center;
margin-top: 2rem; margin-top: 2rem;
padding-bottom: 1.5rem;
.total { .total {
margin: 0 3.5rem 0 14.3%; margin: 0 3.5rem 0 14.3%;

View file

@ -16,13 +16,14 @@ import { useSelector, useDispatch } from 'react-redux';
import Spinner from '../../components/Spinner/Spinner'; import Spinner from '../../components/Spinner/Spinner';
import './Databases.scss'; import './Databases.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
const Databases = props => { const Databases = props => {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token");
const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent); const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent);
const { focusedElement } = useSelector(state => state.mainNavigation); const { focusedElement } = useSelector(state => state.mainNavigation);
const dispatch = useDispatch(); const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
const [modal, setModal] = useState({ const [modal, setModal] = useState({
text: '', text: '',
visible: false, visible: false,
@ -31,7 +32,6 @@ const Databases = props => {
const [state, setState] = useState({ const [state, setState] = useState({
databases: [], databases: [],
dbFav: [], dbFav: [],
loading: true,
toggledAll: false, toggledAll: false,
dbAdmin: '', dbAdmin: '',
dbAdminLink: '', dbAdminLink: '',
@ -45,7 +45,7 @@ const Databases = props => {
dispatch(addActiveElement('/list/db/')); dispatch(addActiveElement('/list/db/'));
dispatch(removeFocusedElement()); dispatch(removeFocusedElement());
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
fetchData(); fetchData().then(() => setLoading(false));
return () => { return () => {
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
@ -165,21 +165,24 @@ const Databases = props => {
} }
const fetchData = () => { const fetchData = () => {
getDatabaseList() setLoading(true);
.then(result => { return new Promise((resolve, reject) => {
setState({ getDatabaseList()
...state, .then(result => {
databases: reformatData(result.data.data), setState({
dbAdmin: result.data.db_admin, ...state,
dbAdminLink: result.data.db_admin_link, databases: reformatData(result.data.data),
dbFav: result.data.dbFav, dbAdmin: result.data.db_admin,
selection: [], dbAdminLink: result.data.db_admin_link,
toggledAll: false, dbFav: result.data.dbFav,
totalAmount: result.data.totalAmount, selection: [],
loading: false toggledAll: false,
}); totalAmount: result.data.totalAmount
}) });
.catch(err => console.error(err)); resolve();
})
.catch(err => console.error(err));
});
} }
const reformatData = data => { const reformatData = data => {
@ -323,12 +326,14 @@ const Databases = props => {
const { selection } = state; const { selection } = state;
if (selection.length && action) { if (selection.length && action) {
setState({ ...state, loading: true }); setLoading(true);
bulkAction(action, selection) bulkAction(action, selection)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
fetchData(); fetchData().then(() => {
toggleAll(false); refreshMenuCounters();
toggleAll(false);
});
} }
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
@ -345,13 +350,25 @@ const Databases = props => {
} }
const modalConfirmHandler = () => { const modalConfirmHandler = () => {
setState({ ...state, loading: true }); if (!modal.actionUrl) {
return modalCancelHandler();
}
modalCancelHandler();
setLoading(true);
handleAction(modal.actionUrl) handleAction(modal.actionUrl)
.then(() => { .then(res => {
fetchData(); if (res.data.error) {
modalCancelHandler(); setLoading(false);
return displayModal(res.data.error, '');
}
fetchData().then(() => refreshMenuCounters())
}) })
.catch(err => console.error(err)); .catch(err => { setLoading(false); console.error(err); });
}
const refreshMenuCounters = () => {
dispatch(refreshCounters()).then(() => setLoading(false));
} }
const modalCancelHandler = () => { const modalCancelHandler = () => {
@ -381,7 +398,7 @@ const Databases = props => {
</div> </div>
</Toolbar> </Toolbar>
<div className="mails-wrapper"> <div className="mails-wrapper">
{state.loading {loading
? <Spinner /> ? <Spinner />
: (<> : (<>
{databases()} {databases()}

View file

@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react';
import { addControlPanelContentFocusedElement, removeControlPanelContentFocusedElement } from '../../actions/ControlPanelContent/controlPanelContentActions'; import { addControlPanelContentFocusedElement, removeControlPanelContentFocusedElement } from '../../actions/ControlPanelContent/controlPanelContentActions';
import { addActiveElement, removeFocusedElement } from '../../actions/MainNavigation/mainNavigationActions'; import { addActiveElement, removeFocusedElement } from '../../actions/MainNavigation/mainNavigationActions';
import DropdownFilter from '../../components/MainNav/Toolbar/DropdownFilter/DropdownFilter'; import DropdownFilter from '../../components/MainNav/Toolbar/DropdownFilter/DropdownFilter';
import { bulkAction, getDnsList, handleAction } from '../../ControlPanelService/Dns'; import { bulkDomainAction, getDnsList, handleAction } from '../../ControlPanelService/Dns';
import * as MainNavigation from '../../actions/MainNavigation/mainNavigationActions'; import * as MainNavigation from '../../actions/MainNavigation/mainNavigationActions';
import SearchInput from '../../components/MainNav/Toolbar/SearchInput/SearchInput'; import SearchInput from '../../components/MainNav/Toolbar/SearchInput/SearchInput';
import DomainNameSystem from '../../components/DomainNameSystem/DomainNameSystem'; import DomainNameSystem from '../../components/DomainNameSystem/DomainNameSystem';
@ -17,13 +17,14 @@ import './DomainNameSystems.scss';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
const DomainNameSystems = props => { const DomainNameSystems = props => {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token");
const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent); const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent);
const { focusedElement } = useSelector(state => state.mainNavigation); const { focusedElement } = useSelector(state => state.mainNavigation);
const dispatch = useDispatch(); const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
const [modal, setModal] = useState({ const [modal, setModal] = useState({
text: '', text: '',
visible: false, visible: false,
@ -32,7 +33,6 @@ const DomainNameSystems = props => {
const [state, setState] = useState({ const [state, setState] = useState({
domainNameSystems: [], domainNameSystems: [],
dnsFav: [], dnsFav: [],
loading: false,
toggledAll: false, toggledAll: false,
sorting: i18n.Date, sorting: i18n.Date,
order: "descending", order: "descending",
@ -44,7 +44,7 @@ const DomainNameSystems = props => {
dispatch(addActiveElement('/list/dns/')); dispatch(addActiveElement('/list/dns/'));
dispatch(removeFocusedElement()); dispatch(removeFocusedElement());
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
fetchData(); fetchData().then(() => setLoading(false));
return () => { return () => {
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
@ -174,21 +174,22 @@ const DomainNameSystems = props => {
} }
const fetchData = () => { const fetchData = () => {
setState({ ...state, loading: true }); setLoading(true);
return new Promise((resolve, reject) => {
getDnsList() getDnsList()
.then(result => { .then(result => {
setState({ setState({
...state, ...state,
domainNameSystems: reformatData(result.data.data), domainNameSystems: reformatData(result.data.data),
dnsFav: result.data.dnsFav, dnsFav: result.data.dnsFav,
selection: [], selection: [],
toggledAll: false, toggledAll: false,
totalAmount: result.data.totalAmount, totalAmount: result.data.totalAmount
loading: false });
}); resolve();
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
});
} }
const reformatData = data => { const reformatData = data => {
@ -341,12 +342,14 @@ const DomainNameSystems = props => {
const { selection } = state; const { selection } = state;
if (selection.length && action) { if (selection.length && action) {
setState({ loading: true }); setLoading(true);
bulkAction(action, selection) bulkDomainAction(action, selection)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
fetchData(); fetchData().then(() => {
toggleAll(false); refreshMenuCounters();
toggleAll(false);
});
} }
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
@ -363,12 +366,25 @@ const DomainNameSystems = props => {
} }
const modalConfirmHandler = () => { const modalConfirmHandler = () => {
if (!modal.actionUrl) {
return modalCancelHandler();
}
modalCancelHandler();
setLoading(true);
handleAction(modal.actionUrl) handleAction(modal.actionUrl)
.then(() => { .then(res => {
fetchData(); if (res.data.error) {
modalCancelHandler(); setLoading(false);
return displayModal(res.data.error, '');
}
fetchData().then(() => refreshMenuCounters())
}) })
.catch(err => console.error(err)); .catch(err => { setLoading(false); console.error(err); });
}
const refreshMenuCounters = () => {
dispatch(refreshCounters()).then(() => setLoading(false));
} }
const modalCancelHandler = () => { const modalCancelHandler = () => {
@ -397,7 +413,7 @@ const DomainNameSystems = props => {
</div> </div>
</Toolbar> </Toolbar>
<div className="dns-wrapper"> <div className="dns-wrapper">
{state.loading ? <Spinner /> : dns()} {loading ? <Spinner /> : dns()}
</div> </div>
<div className="total">{state.totalAmount}</div> <div className="total">{state.totalAmount}</div>
<Modal <Modal

View file

@ -20,15 +20,15 @@ class FileManager extends Component {
super(props); super(props);
this.state = { this.state = {
leftList: { leftList: {
path: this.props.session.user.HOME, path: this.props.menuCounters.user.HOME,
files: { listing: [] }, files: { listing: [] },
}, },
rightList: { rightList: {
path: this.props.session.user.HOME, path: this.props.menuCounters.user.HOME,
files: { listing: [] }, files: { listing: [] },
}, },
currentPath: this.props.session.user.HOME, currentPath: this.props.menuCounters.user.HOME,
currentUser: this.props.session.user.HOME, currentUser: this.props.menuCounters.user.HOME,
activeWindow: "left", activeWindow: "left",
modalWindow: null, modalWindow: null,
modalVisible: false, modalVisible: false,
@ -44,7 +44,7 @@ class FileManager extends Component {
} }
UNSAFE_componentWillMount = () => { UNSAFE_componentWillMount = () => {
FM.cacheData(this.state.currentUser, this.props.history, this.props.session.user.HOME); FM.cacheData(this.state.currentUser, this.props.history, this.props.menuCounters.user.HOME);
let currentPath = FM.activeWindowPath(); let currentPath = FM.activeWindowPath();
this.setState({ currentPath }); this.setState({ currentPath });
this.changeDirectoryOnLoading(); this.changeDirectoryOnLoading();
@ -435,7 +435,7 @@ class FileManager extends Component {
addToPath={this.addToPath} addToPath={this.addToPath}
cursor={this.state.cursor} cursor={this.state.cursor}
passData={this.passData} passData={this.passData}
rootDir={this.props.session.user.HOME} rootDir={this.props.menuCounters.user.HOME}
ref={el => this[`${side}List`] = el} ref={el => this[`${side}List`] = el}
download={this.download} download={this.download}
moveBack={this.moveBack} moveBack={this.moveBack}
@ -480,7 +480,8 @@ class FileManager extends Component {
function mapStateToProps(state) { function mapStateToProps(state) {
return { return {
session: state.session session: state.session,
menuCounters: state.menuCounters
} }
} }

View file

@ -16,6 +16,7 @@ import { Helmet } from 'react-helmet';
import { useHistory } from 'react-router'; import { useHistory } from 'react-router';
import './styles.scss'; import './styles.scss';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
const BanLists = props => { const BanLists = props => {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
@ -23,6 +24,7 @@ const BanLists = props => {
const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent); const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent);
const { focusedElement } = useSelector(state => state.mainNavigation); const { focusedElement } = useSelector(state => state.mainNavigation);
const dispatch = useDispatch(); const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
const [modal, setModal] = useState({ const [modal, setModal] = useState({
text: '', text: '',
visible: false, visible: false,
@ -31,7 +33,6 @@ const BanLists = props => {
const [state, setState] = useState({ const [state, setState] = useState({
banIps: [], banIps: [],
selection: [], selection: [],
loading: false,
toggledAll: false, toggledAll: false,
sorting: i18n.Action, sorting: i18n.Action,
order: "descending", order: "descending",
@ -42,7 +43,7 @@ const BanLists = props => {
dispatch(addActiveElement('/list/firewall/')); dispatch(addActiveElement('/list/firewall/'));
dispatch(removeFocusedElement()); dispatch(removeFocusedElement());
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
fetchData(); fetchData().then(() => setLoading(false));
return () => { return () => {
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
@ -148,20 +149,21 @@ const BanLists = props => {
} }
const fetchData = () => { const fetchData = () => {
setState({ ...state, loading: true }); setLoading(true);
return new Promise((resolve, reject) => {
getBanList() getBanList()
.then(result => { .then(result => {
setState({ setState({
...state, ...state,
banIps: reformatData(result.data.data), banIps: reformatData(result.data.data),
totalAmount: result.data.total_amount, totalAmount: result.data.total_amount,
toggledAll: false, toggledAll: false,
selection: [], selection: []
loading: false });
}); resolve();
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
});
} }
const reformatData = data => { const reformatData = data => {
@ -234,8 +236,10 @@ const BanLists = props => {
bulkAction(action, selection) bulkAction(action, selection)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
fetchData(); fetchData().then(() => {
toggleAll(false); refreshMenuCounters();
toggleAll(false);
});
} }
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
@ -247,12 +251,25 @@ const BanLists = props => {
} }
const modalConfirmHandler = () => { const modalConfirmHandler = () => {
modalCancelHandler(); if (!modal.actionUrl) {
setState({ ...state, loading: true }); return modalCancelHandler();
}
handleAction(state.modalActionUrl) modalCancelHandler();
.then(() => fetchData()) setLoading(true);
.catch(err => console.error(err)); handleAction(modal.actionUrl)
.then(res => {
if (res.data.error) {
setLoading(false);
return displayModal(res.data.error, '');
}
fetchData().then(() => refreshMenuCounters())
})
.catch(err => { setLoading(false); console.error(err); });
}
const refreshMenuCounters = () => {
dispatch(refreshCounters()).then(() => setLoading(false));
} }
const modalCancelHandler = () => { const modalCancelHandler = () => {
@ -275,7 +292,7 @@ const BanLists = props => {
</div> </div>
</Toolbar> </Toolbar>
<div className="banlist-wrapper"> <div className="banlist-wrapper">
{state.loading {loading
? <Spinner /> ? <Spinner />
: (<> : (<>
{banIps()} {banIps()}

View file

@ -17,13 +17,14 @@ import { useDispatch, useSelector } from 'react-redux';
import './Firewalls.scss'; import './Firewalls.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
const Firewalls = props => { const Firewalls = props => {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token");
const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent); const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent);
const { focusedElement } = useSelector(state => state.mainNavigation); const { focusedElement } = useSelector(state => state.mainNavigation);
const dispatch = useDispatch(); const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
const [modal, setModal] = useState({ const [modal, setModal] = useState({
text: '', text: '',
visible: false, visible: false,
@ -34,7 +35,6 @@ const Firewalls = props => {
firewallFav: [], firewallFav: [],
selection: [], selection: [],
firewallExtension: '', firewallExtension: '',
loading: false,
toggledAll: false, toggledAll: false,
sorting: i18n.Action, sorting: i18n.Action,
order: "descending", order: "descending",
@ -45,7 +45,7 @@ const Firewalls = props => {
dispatch(addActiveElement('/list/firewall/')); dispatch(addActiveElement('/list/firewall/'));
dispatch(removeFocusedElement()); dispatch(removeFocusedElement());
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
fetchData(); fetchData().then(() => setLoading(false));
return () => { return () => {
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
@ -165,22 +165,23 @@ const Firewalls = props => {
} }
const fetchData = () => { const fetchData = () => {
setState({ ...state, loading: true }); setLoading(true);
return new Promise((resolve, reject) => {
getFirewallList() getFirewallList()
.then(result => { .then(result => {
setState({ setState({
...state, ...state,
firewalls: reformatData(result.data.data), firewalls: reformatData(result.data.data),
firewallFav: result.data.firewallFav, firewallFav: result.data.firewallFav,
selection: [], selection: [],
firewallExtension: result.data.firewallExtension, firewallExtension: result.data.firewallExtension,
totalAmount: result.data.totalAmount, totalAmount: result.data.totalAmount,
toggledAll: false, toggledAll: false
loading: false });
}); resolve();
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
});
} }
const reformatData = data => { const reformatData = data => {
@ -319,11 +320,14 @@ const Firewalls = props => {
const { selection } = state; const { selection } = state;
if (selection.length && action) { if (selection.length && action) {
setLoading(true);
bulkAction(action, selection) bulkAction(action, selection)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
fetchData(); fetchData().then(() => {
toggleAll(false); refreshMenuCounters();
toggleAll(false);
});
} }
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
@ -335,12 +339,25 @@ const Firewalls = props => {
} }
const modalConfirmHandler = () => { const modalConfirmHandler = () => {
modalCancelHandler(); if (!modal.actionUrl) {
setState({ ...state, loading: true }); return modalCancelHandler();
}
handleAction(state.modalActionUrl) modalCancelHandler();
.then(() => fetchData()) setLoading(true);
.catch(err => console.error(err)); handleAction(modal.actionUrl)
.then(res => {
if (res.data.error) {
setLoading(false);
return displayModal(res.data.error, '');
}
fetchData().then(() => refreshMenuCounters())
})
.catch(err => { setLoading(false); console.error(err); });
}
const refreshMenuCounters = () => {
dispatch(refreshCounters()).then(() => setLoading(false));
} }
const modalCancelHandler = () => { const modalCancelHandler = () => {
@ -365,9 +382,13 @@ const Firewalls = props => {
</div> </div>
</Toolbar> </Toolbar>
<div className="firewalls-wrapper"> <div className="firewalls-wrapper">
{state.loading ? <Spinner /> : firewalls()} {loading
? <Spinner />
: (<>
{firewalls()}
<div className="total">{state.totalAmount}</div>
</>)}
</div> </div>
<div className="total">{state.totalAmount}</div>
<Modal <Modal
onSave={modalConfirmHandler} onSave={modalConfirmHandler}
onCancel={modalCancelHandler} onCancel={modalCancelHandler}

View file

@ -16,12 +16,14 @@ import Spinner from '../../components/Spinner/Spinner';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import './InternetProtocols.scss'; import './InternetProtocols.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
const InternetProtocols = props => { const InternetProtocols = props => {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent); const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent);
const { focusedElement } = useSelector(state => state.mainNavigation); const { focusedElement } = useSelector(state => state.mainNavigation);
const dispatch = useDispatch(); const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
const [modal, setModal] = useState({ const [modal, setModal] = useState({
text: '', text: '',
visible: false, visible: false,
@ -30,7 +32,6 @@ const InternetProtocols = props => {
const [state, setState] = useState({ const [state, setState] = useState({
internetProtocols: [], internetProtocols: [],
ipFav: [], ipFav: [],
loading: false,
toggledAll: false, toggledAll: false,
sorting: i18n.Date, sorting: i18n.Date,
order: "descending", order: "descending",
@ -42,7 +43,7 @@ const InternetProtocols = props => {
dispatch(addActiveElement('/list/ip/')); dispatch(addActiveElement('/list/ip/'));
dispatch(removeFocusedElement()); dispatch(removeFocusedElement());
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
fetchData(); fetchData().then(() => setLoading(false));
return () => { return () => {
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
@ -153,21 +154,22 @@ const InternetProtocols = props => {
} }
const fetchData = () => { const fetchData = () => {
setState({ ...state, loading: true }); setLoading(true);
return new Promise((resolve, reject) => {
getIpList() getIpList()
.then(result => { .then(result => {
setState({ setState({
...state, ...state,
internetProtocols: reformatData(result.data.data), internetProtocols: reformatData(result.data.data),
ipFav: result.data.ipFav, ipFav: result.data.ipFav,
selection: [], selection: [],
totalAmount: result.data.totalAmount, totalAmount: result.data.totalAmount,
toggledAll: false, toggledAll: false
loading: false });
}); resolve();
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
});
} }
const reformatData = data => { const reformatData = data => {
@ -312,13 +314,14 @@ const InternetProtocols = props => {
const { selection } = state; const { selection } = state;
if (selection.length && action) { if (selection.length && action) {
setState({ ...state, loading: true }); setLoading(true);
bulkAction(action, selection) bulkAction(action, selection)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
fetchData(); fetchData().then(() => {
toggleAll(false); refreshMenuCounters();
toggleAll(false);
});
} }
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
@ -330,12 +333,25 @@ const InternetProtocols = props => {
} }
const modalConfirmHandler = () => { const modalConfirmHandler = () => {
modalCancelHandler(); if (!modal.actionUrl) {
setState({ ...state, loading: true }); return modalCancelHandler();
}
modalCancelHandler();
setLoading(true);
handleAction(modal.actionUrl) handleAction(modal.actionUrl)
.then(() => fetchData()) .then(res => {
.catch(err => console.error(err)); if (res.data.error) {
setLoading(false);
return displayModal(res.data.error, '');
}
fetchData().then(() => refreshMenuCounters())
})
.catch(err => { setLoading(false); console.error(err); });
}
const refreshMenuCounters = () => {
dispatch(refreshCounters()).then(() => setLoading(false));
} }
const modalCancelHandler = () => { const modalCancelHandler = () => {
@ -359,9 +375,13 @@ const InternetProtocols = props => {
</div> </div>
</Toolbar> </Toolbar>
<div className="ip-wrapper"> <div className="ip-wrapper">
{state.loading ? <Spinner /> : internetProtocols()} {loading
? <Spinner />
: (<>
{internetProtocols()}
<div className="total">{state.totalAmount}</div>
</>)}
</div> </div>
<div className="total">{state.totalAmount}</div>
<Modal <Modal
onSave={modalConfirmHandler} onSave={modalConfirmHandler}
onCancel={modalCancelHandler} onCancel={modalCancelHandler}

View file

@ -17,13 +17,15 @@ import { Link } from 'react-router-dom';
import './MailAccounts.scss'; import './MailAccounts.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { checkAuthHandler } from 'src/actions/Session/sessionActions';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
export default function MailAccounts(props) { export default function MailAccounts(props) {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token");
const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent); const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent);
const { focusedElement } = useSelector(state => state.mainNavigation); const { focusedElement } = useSelector(state => state.mainNavigation);
const dispatch = useDispatch(); const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
const [modal, setModal] = useState({ const [modal, setModal] = useState({
text: '', text: '',
visible: false, visible: false,
@ -32,7 +34,6 @@ export default function MailAccounts(props) {
const [state, setState] = useState({ const [state, setState] = useState({
mailAccounts: [], mailAccounts: [],
mailAccountsFav: [], mailAccountsFav: [],
loading: false,
domain: props.domain, domain: props.domain,
toggledAll: false, toggledAll: false,
sorting: i18n.Date, sorting: i18n.Date,
@ -43,7 +44,7 @@ export default function MailAccounts(props) {
useEffect(() => { useEffect(() => {
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
fetchData(); fetchData().then(() => setLoading(false));
return () => { return () => {
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
@ -131,7 +132,6 @@ export default function MailAccounts(props) {
} }
const handleFocusedElementShortcuts = event => { const handleFocusedElementShortcuts = event => {
event.preventDefault();
let isSearchInputFocused = document.querySelector('input:focus') || document.querySelector('textarea:focus'); let isSearchInputFocused = document.querySelector('input:focus') || document.querySelector('textarea:focus');
if (controlPanelFocusedElement && !isSearchInputFocused) { if (controlPanelFocusedElement && !isSearchInputFocused) {
@ -164,22 +164,23 @@ export default function MailAccounts(props) {
} }
const fetchData = () => { const fetchData = () => {
setState({ ...state, loading: true }); setLoading(true);
return new Promise((resolve, reject) => {
getMailAccountList(props.domain) getMailAccountList(props.domain)
.then(result => { .then(result => {
setState({ setState({
...state, ...state,
mailAccounts: reformatData(result.data.data), mailAccounts: reformatData(result.data.data),
webMail: result.data.webMail, webMail: result.data.webmail,
selection: [], selection: [],
toggledAll: false, toggledAll: false,
mailAccountsFav: result.data.mailAccountsFav, mailAccountsFav: result.data.mailAccountsFav,
totalAmount: result.data.totalAmount, totalAmount: result.data.totalAmount
loading: false });
}); resolve();
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
});
} }
const reformatData = data => { const reformatData = data => {
@ -319,11 +320,14 @@ export default function MailAccounts(props) {
const bulk = action => { const bulk = action => {
const { selection } = state; const { selection } = state;
if (selection.length && action) { if (selection.length && action) {
setLoading(true);
bulkMailAccountAction(action, props.domain, selection) bulkMailAccountAction(action, props.domain, selection)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
fetchData(); fetchData().then(() => {
toggleAll(false); refreshMenuCounters();
toggleAll(false);
});
} }
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
@ -340,12 +344,25 @@ export default function MailAccounts(props) {
} }
const modalConfirmHandler = () => { const modalConfirmHandler = () => {
if (!modal.actionUrl) {
return modalCancelHandler();
}
modalCancelHandler();
setLoading(true);
handleAction(modal.actionUrl) handleAction(modal.actionUrl)
.then(() => { .then(res => {
fetchData(); if (res.data.error) {
modalCancelHandler(); setLoading(false);
return displayModal(res.data.error, '');
}
fetchData().then(() => refreshMenuCounters())
}) })
.catch(err => console.error(err)); .catch(err => { setLoading(false); console.error(err); });
}
const refreshMenuCounters = () => {
dispatch(refreshCounters()).then(() => setLoading(false));
} }
const modalCancelHandler = () => { const modalCancelHandler = () => {
@ -374,7 +391,7 @@ export default function MailAccounts(props) {
</div> </div>
</div> </div>
</Toolbar> </Toolbar>
{state.loading {loading
? <Spinner /> ? <Spinner />
: ( : (
<> <>

View file

@ -17,6 +17,7 @@ $primary: #2c54ac;
div.list-item { div.list-item {
.r-col { .r-col {
.stat.email { .stat.email {
width: max-content;
text-transform: none; text-transform: none;
} }
} }
@ -27,6 +28,7 @@ $primary: #2c54ac;
display: flex; display: flex;
align-items: center; align-items: center;
margin-top: 2rem; margin-top: 2rem;
padding-bottom: 1.5rem;
.total { .total {
margin: 0 3.5rem 0 14.3%; margin: 0 3.5rem 0 14.3%;

View file

@ -17,13 +17,14 @@ import './Mails.scss';
import { useSelector, useDispatch } from 'react-redux'; import { useSelector, useDispatch } from 'react-redux';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
const Mails = props => { const Mails = props => {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token");
const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent); const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent);
const { focusedElement } = useSelector(state => state.mainNavigation); const { focusedElement } = useSelector(state => state.mainNavigation);
const dispatch = useDispatch(); const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
const [modal, setModal] = useState({ const [modal, setModal] = useState({
text: '', text: '',
visible: false, visible: false,
@ -32,7 +33,6 @@ const Mails = props => {
const [state, setState] = useState({ const [state, setState] = useState({
mails: [], mails: [],
mailFav: [], mailFav: [],
loading: false,
toggledAll: false, toggledAll: false,
webMail: '', webMail: '',
sorting: i18n.Date, sorting: i18n.Date,
@ -45,7 +45,7 @@ const Mails = props => {
dispatch(addActiveElement('/list/mail/')); dispatch(addActiveElement('/list/mail/'));
dispatch(removeFocusedElement()); dispatch(removeFocusedElement());
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
fetchData(); fetchData().then(() => setLoading(false));
return () => { return () => {
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
@ -175,22 +175,23 @@ const Mails = props => {
} }
const fetchData = () => { const fetchData = () => {
setState({ ...state, loading: true }); setLoading(true);
return new Promise((resolve, reject) => {
getMailList() getMailList()
.then(result => { .then(result => {
setState({ setState({
...state, ...state,
mails: reformatData(result.data.data), mails: reformatData(result.data.data),
webMail: result.data.webMail, webMail: result.data.webMail,
mailFav: result.data.mailFav, mailFav: result.data.mailFav,
selection: [], selection: [],
toggledAll: false, toggledAll: false,
totalAmount: result.data.totalAmount, totalAmount: result.data.totalAmount
loading: false });
}); resolve();
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
});
} }
const reformatData = data => { const reformatData = data => {
@ -332,12 +333,14 @@ const Mails = props => {
const { selection } = state; const { selection } = state;
if (selection.length && action) { if (selection.length && action) {
setState({ ...state, loading: true }); setLoading(true);
bulkAction(action, selection) bulkAction(action, selection)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
fetchData(); fetchData().then(() => {
toggleAll(false); refreshMenuCounters();
toggleAll(false);
});
} }
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
@ -354,12 +357,25 @@ const Mails = props => {
} }
const modalConfirmHandler = () => { const modalConfirmHandler = () => {
if (!modal.actionUrl) {
return modalCancelHandler();
}
modalCancelHandler();
setLoading(true);
handleAction(modal.actionUrl) handleAction(modal.actionUrl)
.then(() => { .then(res => {
fetchData(); if (res.data.error) {
modalCancelHandler(); setLoading(false);
return displayModal(res.data.error, '');
}
fetchData().then(() => refreshMenuCounters())
}) })
.catch(err => console.error(err)); .catch(err => { setLoading(false); console.error(err); });
}
const refreshMenuCounters = () => {
dispatch(refreshCounters()).then(() => setLoading(false));
} }
const modalCancelHandler = () => { const modalCancelHandler = () => {
@ -389,7 +405,7 @@ const Mails = props => {
</div> </div>
</Toolbar> </Toolbar>
<div className="mails-wrapper"> <div className="mails-wrapper">
{state.loading {loading
? <Spinner /> ? <Spinner />
: (<> : (<>
{mails()} {mails()}

View file

@ -16,12 +16,14 @@ import Spinner from '../../components/Spinner/Spinner';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import './Packages.scss'; import './Packages.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
const Packages = props => { const Packages = props => {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent); const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent);
const { focusedElement } = useSelector(state => state.mainNavigation); const { focusedElement } = useSelector(state => state.mainNavigation);
const dispatch = useDispatch(); const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
const [modal, setModal] = useState({ const [modal, setModal] = useState({
text: '', text: '',
visible: false, visible: false,
@ -30,7 +32,6 @@ const Packages = props => {
const [state, setState] = useState({ const [state, setState] = useState({
packages: [], packages: [],
packagesFav: [], packagesFav: [],
loading: true,
toggledAll: false, toggledAll: false,
sorting: i18n.Date, sorting: i18n.Date,
order: "descending", order: "descending",
@ -42,7 +43,7 @@ const Packages = props => {
dispatch(addActiveElement('/list/package/')); dispatch(addActiveElement('/list/package/'));
dispatch(removeFocusedElement()); dispatch(removeFocusedElement());
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
fetchData(); fetchData().then(() => setLoading(false));
return () => { return () => {
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
@ -149,23 +150,26 @@ const Packages = props => {
const { packages } = state; const { packages } = state;
let currentPackageData = packages.filter(pack => pack.NAME === controlPanelFocusedElement)[0]; let currentPackageData = packages.filter(pack => pack.NAME === controlPanelFocusedElement)[0];
displayModal(currentPackageData.delete_conf, `/api/v1/delete/package/?package=${controlPanelFocusedElement}`); displayModal(currentPackageData.delete_conf, `/api/v1/delete/package/index.php?package=${controlPanelFocusedElement}`);
} }
const fetchData = () => { const fetchData = () => {
getPackageList() setLoading(true);
.then(result => { return new Promise((resolve, reject) => {
setState({ getPackageList()
...state, .then(result => {
packages: reformatData(result.data.data), setState({
packagesFav: result.data.packagesFav, ...state,
totalAmount: result.data.totalAmount, packages: reformatData(result.data.data),
selection: [], packagesFav: result.data.packagesFav,
toggledAll: false, totalAmount: result.data.totalAmount,
loading: false selection: [],
}); toggledAll: false
}) });
.catch(err => console.error(err)); resolve();
})
.catch(err => console.error(err));
});
} }
const reformatData = data => { const reformatData = data => {
@ -306,13 +310,14 @@ const Packages = props => {
const { selection } = state; const { selection } = state;
if (selection.length && action) { if (selection.length && action) {
setState({ ...state, loading: true }); setLoading(true);
bulkAction(action, selection) bulkAction(action, selection)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
fetchData(); fetchData().then(() => {
toggleAll(false); refreshMenuCounters();
toggleAll(false);
});
} }
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
@ -324,12 +329,25 @@ const Packages = props => {
} }
const modalConfirmHandler = () => { const modalConfirmHandler = () => {
modalCancelHandler(); if (!modal.actionUrl) {
setState({ ...state, loading: true }); return modalCancelHandler();
}
modalCancelHandler();
setLoading(true);
handleAction(modal.actionUrl) handleAction(modal.actionUrl)
.then(() => fetchData()) .then(res => {
.catch(err => console.error(err)); if (res.data.error) {
setLoading(false);
return displayModal(res.data.error, '');
}
fetchData().then(() => refreshMenuCounters())
})
.catch(err => { setLoading(false); console.error(err); });
}
const refreshMenuCounters = () => {
dispatch(refreshCounters()).then(() => setLoading(false));
} }
const modalCancelHandler = () => { const modalCancelHandler = () => {
@ -354,7 +372,7 @@ const Packages = props => {
</Toolbar> </Toolbar>
<div className="packages-wrapper"> <div className="packages-wrapper">
{ {
state.loading loading
? <Spinner /> ? <Spinner />
: (<> : (<>
{packages()} {packages()}

View file

@ -18,7 +18,7 @@ div.content {
color: $textColor; color: $textColor;
.toolbar { .toolbar {
padding-bottom: 10px; padding: 6px 12.5%;
} }
.rrd-item { .rrd-item {
@ -89,4 +89,10 @@ div.content {
> div.active { > div.active {
color: $secondaryActive; color: $secondaryActive;
} }
} }
@media (max-width: 1350px) {
.rrd-list .toolbar {
padding: 6px 9.5%;
}
}

View file

@ -7,18 +7,20 @@ import Toolbar from '../../components/MainNav/Toolbar/Toolbar';
import Modal from '../../components/ControlPanel/Modal/Modal'; import Modal from '../../components/ControlPanel/Modal/Modal';
import Spinner from '../../components/Spinner/Spinner'; import Spinner from '../../components/Spinner/Spinner';
import './Search.scss'; import './Search.scss';
import { useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
const Search = props => { const Search = props => {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
const history = useHistory(); const history = useHistory();
const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
const [state, setState] = useState({ const [state, setState] = useState({
searchResults: [], searchResults: [],
totalAmount: '', totalAmount: '',
sorting: i18n.Date, sorting: i18n.Date,
order: "descending", order: "descending",
loading: false,
total: 0 total: 0
}); });
const [modal, setModal] = useState({ const [modal, setModal] = useState({
@ -34,29 +36,31 @@ const Search = props => {
let searchTerm = search.split('=')[1]; let searchTerm = search.split('=')[1];
if (searchTerm !== '') { if (searchTerm !== '') {
fetchData(searchTerm); fetchData(searchTerm).then(() => setLoading(false));
} else { } else {
return history.push({ pathname: '/list/user/', search: '' }); return history.push({ pathname: '/list/user/', search: '' });
} }
} else if (props.searchTerm !== '') { } else if (props.searchTerm !== '') {
fetchData(props.searchTerm); fetchData(props.searchTerm).then(() => setLoading(false));
} else { } else {
return history.push({ pathname: '/list/user/', search: '' }); return history.push({ pathname: '/list/user/', search: '' });
} }
}, []); }, []);
const fetchData = searchTerm => { const fetchData = searchTerm => {
setState({ ...state, loading: true }); setLoading(true);
getSearchResultsList(searchTerm) return new Promise((resolve, reject) => {
.then(result => { getSearchResultsList(searchTerm)
setState({ .then(result => {
...state, setState({
searchResults: result.data.data, ...state,
totalAmount: result.data.total_amount, searchResults: result.data.data,
loading: false totalAmount: result.data.total
}); });
}) resolve();
.catch(err => console.error(err)); })
.catch(err => console.error(err));
});
} }
const searchResults = () => { const searchResults = () => {
@ -99,7 +103,6 @@ const Search = props => {
switch (sorting) { switch (sorting) {
case Date: return 'DATE'; case Date: return 'DATE';
case Name: return 'RESULT'; case Name: return 'RESULT';
case Starred: return 'STARRED';
default: break; default: break;
} }
} }
@ -114,12 +117,25 @@ const Search = props => {
} }
const modalConfirmHandler = () => { const modalConfirmHandler = () => {
handleAction(state.modalActionUrl) if (!modal.actionUrl) {
.then(() => { return modalCancelHandler();
fetchData(); }
modalCancelHandler();
modalCancelHandler();
setLoading(true);
handleAction(modal.actionUrl)
.then(res => {
if (res.data.error) {
setLoading(false);
return displayModal(res.data.error, '');
}
fetchData().then(() => refreshMenuCounters())
}) })
.catch(err => console.error(err)); .catch(err => { setLoading(false); console.error(err); });
}
const refreshMenuCounters = () => {
dispatch(refreshCounters()).then(() => setLoading(false));
} }
const modalCancelHandler = () => { const modalCancelHandler = () => {
@ -141,9 +157,13 @@ const Search = props => {
</div> </div>
</Toolbar> </Toolbar>
<div className="statistics-wrapper"> <div className="statistics-wrapper">
{state.loading ? <Spinner /> : searchResults()} {loading
? <Spinner />
: (<>
{searchResults()}
<div className="total">{state.totalAmount}</div>
</>)}
</div> </div>
<div className="total">{state.totalAmount}</div>
<Modal <Modal
onSave={modalConfirmHandler} onSave={modalConfirmHandler}
onCancel={modalCancelHandler} onCancel={modalCancelHandler}

View file

@ -15,12 +15,14 @@ import Server from '../../components/Server/Server';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import './Servers.scss'; import './Servers.scss';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
const Servers = props => { const Servers = props => {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent); const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent);
const { focusedElement } = useSelector(state => state.mainNavigation); const { focusedElement } = useSelector(state => state.mainNavigation);
const dispatch = useDispatch(); const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
const [modal, setModal] = useState({ const [modal, setModal] = useState({
text: '', text: '',
visible: false, visible: false,
@ -29,7 +31,6 @@ const Servers = props => {
const [state, setState] = useState({ const [state, setState] = useState({
servers: [], servers: [],
selection: [], selection: [],
loading: false,
toggledAll: false, toggledAll: false,
sorting: i18n.Action, sorting: i18n.Action,
order: "descending", order: "descending",
@ -39,7 +40,7 @@ const Servers = props => {
dispatch(addActiveElement('/list/server/')); dispatch(addActiveElement('/list/server/'));
dispatch(removeFocusedElement()); dispatch(removeFocusedElement());
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
fetchData(); fetchData().then(() => setLoading(false));
return () => { return () => {
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
@ -156,19 +157,20 @@ const Servers = props => {
} }
const fetchData = () => { const fetchData = () => {
setState({ ...state, loading: true }); setLoading(true);
return new Promise((resolve, reject) => {
getServersList() getServersList()
.then(result => { .then(result => {
setState({ setState({
...state, ...state,
selection: [], selection: [],
toggledAll: false, toggledAll: false,
servers: reformatData(result.data.data, result.data.sys), servers: reformatData(result.data.data, result.data.sys)
loading: false });
}); resolve();
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
});
} }
const reformatData = (servers, sysInfo) => { const reformatData = (servers, sysInfo) => {
@ -207,18 +209,17 @@ const Servers = props => {
const onHandleAction = uri => { const onHandleAction = uri => {
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
if (uri) { if (uri) {
setState({ ...state, loading: true }); setLoading(true);
handleAction(uri) handleAction(uri)
.then(res => { .then(res => {
if (res.data.error) { if (res.data.error) {
displayModal(res.data.error); displayModal(res.data.error);
} }
setState({ ...state, loading: false }); setLoading(false);
}) })
.catch(err => { .catch(err => {
setState({ ...state, loading: false }); setLoading(false);
console.error(err) console.error(err)
}); });
} }
@ -258,8 +259,10 @@ const Servers = props => {
displayModal(res.data.error); displayModal(res.data.error);
} }
fetchData(); fetchData().then(() => {
toggleAll(false); refreshMenuCounters();
toggleAll(false);
});
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
} }
@ -288,11 +291,25 @@ const Servers = props => {
} }
const modalConfirmHandler = () => { const modalConfirmHandler = () => {
if (!modal.actionUrl) {
return modalCancelHandler();
}
modalCancelHandler(); modalCancelHandler();
setState({ ...state, loading: true }); setLoading(true);
handleAction(modal.actionUrl) handleAction(modal.actionUrl)
.then(() => fetchData()) .then(res => {
.catch(err => console.error(err)); if (res.data.error) {
setLoading(false);
return displayModal(res.data.error, '');
}
fetchData().then(() => refreshMenuCounters())
})
.catch(err => { setLoading(false); console.error(err); });
}
const refreshMenuCounters = () => {
dispatch(refreshCounters()).then(() => setLoading(false));
} }
const modalCancelHandler = () => { const modalCancelHandler = () => {
@ -315,7 +332,7 @@ const Servers = props => {
</div> </div>
</div> </div>
</Toolbar> </Toolbar>
{state.loading ? <Spinner /> : ( {loading ? <Spinner /> : (
<div className="servers-wrapper"> <div className="servers-wrapper">
{servers()} {servers()}
</div> </div>

View file

@ -2,7 +2,7 @@
color: #686868; color: #686868;
.toolbar { .toolbar {
padding-bottom: 5px; padding: 6px 12.5%;
} }
.l-col { .l-col {
@ -28,4 +28,10 @@
.r-col .date { .r-col .date {
color: #5edad0; color: #5edad0;
} }
}
@media (max-width: 1350px) {
.statistics-list .toolbar {
padding: 6px 9.5%;
}
} }

View file

@ -16,12 +16,14 @@ import Spinner from '../../components/Spinner/Spinner';
import User from '../../components/User/User'; import User from '../../components/User/User';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import './Users.scss'; import './Users.scss';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
const Users = props => { const Users = props => {
const { userName, i18n, session: { look } } = useSelector(state => state.session); const { userName, i18n, session: { look } } = useSelector(state => state.session);
const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent); const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent);
const { focusedElement } = useSelector(state => state.mainNavigation); const { focusedElement } = useSelector(state => state.mainNavigation);
const dispatch = useDispatch(); const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
const [modal, setModal] = useState({ const [modal, setModal] = useState({
text: '', text: '',
visible: false, visible: false,
@ -30,7 +32,6 @@ const Users = props => {
const [state, setState] = useState({ const [state, setState] = useState({
users: [], users: [],
userFav: [], userFav: [],
loading: false,
toggledAll: false, toggledAll: false,
sorting: i18n.Date, sorting: i18n.Date,
order: "descending", order: "descending",
@ -42,7 +43,7 @@ const Users = props => {
dispatch(addActiveElement('/list/user/')); dispatch(addActiveElement('/list/user/'));
dispatch(removeFocusedElement()); dispatch(removeFocusedElement());
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
fetchData(); fetchData().then(() => setLoading(false));
return () => { return () => {
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
@ -60,21 +61,22 @@ const Users = props => {
}, [controlPanelFocusedElement, focusedElement, state.users]); }, [controlPanelFocusedElement, focusedElement, state.users]);
const fetchData = () => { const fetchData = () => {
setState({ ...state, loading: true }); setLoading(true);
return new Promise((resolve, reject) => {
getUsersList() getUsersList()
.then(result => { .then(result => {
setState({ setState({
...state, ...state,
users: reformatData(result.data.data), users: reformatData(result.data.data),
userFav: result.data.userFav, userFav: result.data.userFav,
totalAmount: result.data.totalAmount, totalAmount: result.data.totalAmount,
toggledAll: false, toggledAll: false,
selection: [], selection: []
loading: false });
}); resolve();
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
});
} }
const handleFocusedElementShortcuts = event => { const handleFocusedElementShortcuts = event => {
@ -322,13 +324,14 @@ const Users = props => {
const bulk = action => { const bulk = action => {
if (state.selection.length && action) { if (state.selection.length && action) {
setState({ ...state, loading: true }); setLoading(true);
bulkAction(action, state.selection) bulkAction(action, state.selection)
.then(result => { .then(result => {
if (result.status === 200) { if (result.status === 200) {
fetchData(); fetchData().then(() => {
toggleAll(false); refreshMenuCounters();
toggleAll(false);
});
} }
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
@ -345,13 +348,25 @@ const Users = props => {
} }
const modalConfirmHandler = () => { const modalConfirmHandler = () => {
if (!modal.actionUrl) {
return modalCancelHandler();
}
modalCancelHandler(); modalCancelHandler();
setState({ ...state, loading: true }); setLoading(true);
handleAction(modal.actionUrl) handleAction(modal.actionUrl)
.then(() => { .then(res => {
fetchData(); if (res.data.error) {
setLoading(false);
return displayModal(res.data.error, '');
}
fetchData().then(() => refreshMenuCounters())
}) })
.catch(err => console.error(err)); .catch(err => { setLoading(false); console.error(err); });
}
const refreshMenuCounters = () => {
dispatch(refreshCounters()).then(() => setLoading(false));
} }
const modalCancelHandler = () => { const modalCancelHandler = () => {
@ -383,7 +398,7 @@ const Users = props => {
</div> </div>
</Toolbar> </Toolbar>
<div className="users-wrapper"> <div className="users-wrapper">
{state.loading {loading
? <Spinner /> ? <Spinner />
: (<> : (<>
{users()} {users()}

View file

@ -16,13 +16,14 @@ import Modal from '../../components/ControlPanel/Modal/Modal';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import './Web.scss'; import './Web.scss';
import { refreshCounters } from 'src/actions/MenuCounters/menuCounterActions';
const Web = props => { const Web = props => {
const { i18n } = useSelector(state => state.session); const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token");
const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent); const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent);
const { focusedElement } = useSelector(state => state.mainNavigation); const { focusedElement } = useSelector(state => state.mainNavigation);
const dispatch = useDispatch(); const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
const [modal, setModal] = useState({ const [modal, setModal] = useState({
text: '', text: '',
visible: false, visible: false,
@ -31,7 +32,6 @@ const Web = props => {
const [state, setState] = useState({ const [state, setState] = useState({
webDomains: [], webDomains: [],
webFav: [], webFav: [],
loading: false,
toggledAll: false, toggledAll: false,
sorting: i18n.Date, sorting: i18n.Date,
order: "descending", order: "descending",
@ -43,7 +43,7 @@ const Web = props => {
dispatch(addActiveElement('/list/web/')); dispatch(addActiveElement('/list/web/'));
dispatch(removeFocusedElement()); dispatch(removeFocusedElement());
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
fetchData(); fetchData().then(() => setLoading(false));
return () => { return () => {
dispatch(removeControlPanelContentFocusedElement()); dispatch(removeControlPanelContentFocusedElement());
@ -168,21 +168,22 @@ const Web = props => {
} }
const fetchData = () => { const fetchData = () => {
setState({ ...state, loading: true }); setLoading(true);
return new Promise((resolve, reject) => {
getWebList() getWebList()
.then(result => { .then(result => {
setState({ setState({
...state, ...state,
webDomains: reformatData(result.data.data), webDomains: reformatData(result.data.data),
webFav: result.data.webFav, webFav: result.data.webFav,
totalAmount: result.data.totalAmount, totalAmount: result.data.totalAmount,
toggledAll: false, toggledAll: false,
selection: [], selection: []
loading: false });
}); resolve();
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
});
} }
const changeSorting = (sorting, order) => { const changeSorting = (sorting, order) => {
@ -318,14 +319,13 @@ const Web = props => {
const bulk = action => { const bulk = action => {
if (state.selection.length && action) { if (state.selection.length && action) {
setState({ ...state, loading: true }); setLoading(true);
bulkAction(action, state.selection) bulkAction(action, state.selection)
.then(result => { .then(result => {
if (result.status === 200) { fetchData().then(() => {
fetchData(); refreshMenuCounters();
toggleAll(false); toggleAll(false);
} });
}) })
.catch(err => console.error(err)); .catch(err => console.error(err));
} }
@ -334,20 +334,32 @@ const Web = props => {
const displayModal = (text, url) => { const displayModal = (text, url) => {
setModal({ setModal({
...modal, ...modal,
visible: !modal.visible, visible: true,
text, text,
actionUrl: url actionUrl: url
}); });
} }
const modalConfirmHandler = () => { const modalConfirmHandler = () => {
setState({ ...state, loading: true }); if (!modal.actionUrl) {
return modalCancelHandler();
}
modalCancelHandler(); modalCancelHandler();
setLoading(true);
handleAction(modal.actionUrl) handleAction(modal.actionUrl)
.then(() => { .then(res => {
fetchData(); if (res.data.error) {
setLoading(false);
return displayModal(res.data.error, '');
}
fetchData().then(() => refreshMenuCounters())
}) })
.catch(err => console.error(err)); .catch(err => { setLoading(false); console.error(err); });
}
const refreshMenuCounters = () => {
dispatch(refreshCounters()).then(() => setLoading(false));
} }
const modalCancelHandler = () => { const modalCancelHandler = () => {
@ -376,7 +388,7 @@ const Web = props => {
</div> </div>
</Toolbar> </Toolbar>
<div className="web-domains-wrapper"> <div className="web-domains-wrapper">
{state.loading {loading
? <Spinner /> ? <Spinner />
: ( : (
<> <>

View file

@ -12,11 +12,10 @@ import Spinner from 'src/components/Spinner/Spinner';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
export default function WebLogs() { export default function WebLogs() {
const { i18n } = useSelector(state => state.session); const { i18n, userName } = useSelector(state => state.session);
const history = useHistory(); const history = useHistory();
const dispatch = useDispatch(); const dispatch = useDispatch();
const mainNavigation = useSelector(state => state.mainNavigation); const mainNavigation = useSelector(state => state.mainNavigation);
const { userName } = useSelector(state => state.session);
const [domain, setDomain] = useState(); const [domain, setDomain] = useState();
const [state, setState] = useState({ const [state, setState] = useState({
data: "", data: "",

View file

@ -0,0 +1,19 @@
import { REFRESH_COUNTERS } from 'src/actions/MenuCounters/menuCounterTypes';
const INITIAL_STATE = {
user: {},
};
const menuCounterReducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
case REFRESH_COUNTERS:
return {
...state,
user: action.value.user,
};
default: return state;
}
};
export default menuCounterReducer;

View file

@ -1,7 +1,7 @@
import { ADD_NOTIFICATIONS, REMOVE_NOTIFICATIONS } from 'src/actions/Notification/notificationTypes'; import { ADD_NOTIFICATIONS, REMOVE_NOTIFICATIONS } from 'src/actions/Notification/notificationTypes';
const INITIAL_STATE = { const INITIAL_STATE = {
notifications: [] notifications: null
}; };
const notificationReducer = (state = INITIAL_STATE, action) => { const notificationReducer = (state = INITIAL_STATE, action) => {

View file

@ -2,7 +2,6 @@ import { LOGGED_OUT_AS, LOGIN, LOGOUT, CHECK_AUTH } from '../../actions/Session/
const INITIAL_STATE = { const INITIAL_STATE = {
token: '', token: '',
user: {},
error: '', error: '',
session: {}, session: {},
i18n: {}, i18n: {},
@ -16,7 +15,6 @@ const sessionReducer = (state = INITIAL_STATE, action) => {
return { return {
...state, ...state,
token: action.value.token, token: action.value.token,
user: action.value.user,
session: action.value.session, session: action.value.session,
userName: action.value.userName, userName: action.value.userName,
i18n: action.value.i18n || {}, i18n: action.value.i18n || {},
@ -28,7 +26,6 @@ const sessionReducer = (state = INITIAL_STATE, action) => {
return { return {
...state, ...state,
token: action.value.token, token: action.value.token,
user: action.value.user,
session: action.value.session, session: action.value.session,
userName: action.value.userName, userName: action.value.userName,
i18n: action.value.i18n || {}, i18n: action.value.i18n || {},
@ -40,7 +37,6 @@ const sessionReducer = (state = INITIAL_STATE, action) => {
return { return {
...state, ...state,
token: action.value.token, token: action.value.token,
user: action.value.user,
session: action.value.session, session: action.value.session,
userName: action.value.userName, userName: action.value.userName,
i18n: action.value.i18n || {}, i18n: action.value.i18n || {},
@ -51,7 +47,6 @@ const sessionReducer = (state = INITIAL_STATE, action) => {
case CHECK_AUTH: return { case CHECK_AUTH: return {
...state, ...state,
token: action.value.token, token: action.value.token,
user: action.value.user,
session: action.value.session, session: action.value.session,
userName: action.value.userName, userName: action.value.userName,
i18n: action.value.i18n || {}, i18n: action.value.i18n || {},

Some files were not shown because too many files have changed in this diff Show more