React integration ready for v1.0.0 release.

This commit is contained in:
Alexander 2021-10-22 17:55:25 +03:00
commit 095e2e9e4a
213 changed files with 2699 additions and 1713 deletions

View file

@ -3,12 +3,10 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" /> <link rel="icon" href="/images/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="theme-color" content="#000000" /> <meta name="theme-color" content="#000000" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="stylesheet" href="/node_modules/bootstrap/dist/css/bootstrap.css">
<link rel="stylesheet" href="/node_modules/bootstrap/dist/js/bootstrap.min.js">
<title>Vesta</title> <title>Vesta</title>
</head> </head>

View file

@ -1,14 +1,14 @@
import axios from "axios"; import axios from "axios";
import { getAuthToken } from "src/utils/token";
const token = localStorage.getItem("token");
const BASE_URL = window.location.origin; const BASE_URL = window.location.origin;
const webApiUri = '/list/backup/backup.php'; const webApiUri = '/api/v1/list/backup/index.php';
const scheduleBackupUri = '/schedule/backup/'; const scheduleBackupUri = '/schedule/backup/';
const backupDetailsUri = '/list/backup/backup.php'; const backupDetailsUri = '/api/v1/list/backup/index.php';
const backupExclusionsUri = '/api/list/backup/exclusions/index.php'; const backupExclusionsUri = '/api/v1/list/backup/exclusions/index.php';
const backupExclusionsInfoUri = '/api/edit/backup/exclusions/index.php'; const backupExclusionsInfoUri = '/api/v1/edit/backup/exclusions/index.php';
const backupRestoreSettingUri = '/api/schedule/restore/index.php'; const backupRestoreSettingUri = '/api/v1/schedule/restore/index.php';
const bulkRestoreUri = '/api/bulk/restore/index.php'; const bulkRestoreUri = '/api/v1/bulk/restore/index.php';
export const getBackupList = () => { export const getBackupList = () => {
return axios.get(BASE_URL + webApiUri); return axios.get(BASE_URL + webApiUri);
@ -17,18 +17,21 @@ export const getBackupList = () => {
export const bulkAction = (action, backups) => { export const bulkAction = (action, backups) => {
const formData = new FormData(); const formData = new FormData();
formData.append("action", action); formData.append("action", action);
formData.append("token", token); formData.append("token", getAuthToken());
backups.forEach(backup => { backups.forEach(backup => {
formData.append("backup[]", backup); formData.append("backup[]", backup);
formData.append("delete_url", `/delete/backup/?backup=${backup}&token=${token}`);
}); });
return axios.post(BASE_URL + '/bulk/backup/', formData); return axios.post(BASE_URL + '/api/v1/bulk/backup/', formData);
}; };
export const handleAction = uri => { export const handleAction = uri => {
return axios.get(BASE_URL + uri); return axios.get(BASE_URL + uri, {
params: {
token: getAuthToken()
}
});
} }
export const scheduleBackup = () => { export const scheduleBackup = () => {
@ -45,7 +48,7 @@ export const restoreBackupSetting = params => {
export const bulkRestore = (action, selection, backup) => { export const bulkRestore = (action, selection, backup) => {
const formData = new FormData(); const formData = new FormData();
formData.append("token", token); formData.append("token", getAuthToken());
formData.append("action", action); formData.append("action", action);
formData.append("backup", backup); formData.append("backup", backup);
@ -73,7 +76,7 @@ export const updateBackupExclusions = data => {
return axios.post(BASE_URL + backupExclusionsInfoUri, formDataObject, { return axios.post(BASE_URL + backupExclusionsInfoUri, formDataObject, {
params: { params: {
token token: getAuthToken()
} }
}); });
} }

View file

@ -1,11 +1,11 @@
import axios from "axios"; import axios from "axios";
import { getAuthToken } from "src/utils/token";
const token = localStorage.getItem("token");
const BASE_URL = window.location.origin; const BASE_URL = window.location.origin;
const webApiUri = '/list/cron/cron.php'; const webApiUri = '/api/v1/list/cron/index.php';
const cronAddApiUri = '/api/add/cron/index.php'; const cronAddApiUri = '/api/v1/add/cron/index.php';
const jobInfoUri = '/api/edit/cron/index.php'; const jobInfoUri = '/api/v1/edit/cron/index.php';
const updateCronJobUri = '/api/edit/cron/index.php'; const updateCronJobUri = '/api/v1/edit/cron/index.php';
export const getCronList = () => { export const getCronList = () => {
return axios.get(BASE_URL + webApiUri); return axios.get(BASE_URL + webApiUri);
@ -14,19 +14,21 @@ export const getCronList = () => {
export const bulkAction = (action, domainNameSystems) => { export const bulkAction = (action, domainNameSystems) => {
const formData = new FormData(); const formData = new FormData();
formData.append("action", action); formData.append("action", action);
formData.append("token", token); formData.append("token", getAuthToken());
domainNameSystems.forEach(domainNameSystem => { domainNameSystems.forEach(domainNameSystem => {
formData.append("job[]", domainNameSystem); formData.append("job[]", domainNameSystem);
formData.append("suspend_url", `/suspend/cron/?job=${domainNameSystem}&token=${token}`);
formData.append("delete_url", `/delete/cron/?job=${domainNameSystem}&token=${token}`);
}); });
return axios.post(BASE_URL + '/bulk/cron/', formData); return axios.post(BASE_URL + '/api/v1/bulk/cron/', formData);
}; };
export const handleAction = uri => { export const handleAction = uri => {
return axios.get(BASE_URL + uri); return axios.get(BASE_URL + uri, {
params: {
token: getAuthToken()
}
});
} }
export const addCronJob = data => { export const addCronJob = data => {
@ -43,7 +45,7 @@ export const getCronJobInfo = job => {
return axios.get(BASE_URL + jobInfoUri, { return axios.get(BASE_URL + jobInfoUri, {
params: { params: {
job, job,
token token: getAuthToken()
} }
}); });
} }
@ -58,7 +60,7 @@ export const updateCronJob = (data, job) => {
return axios.post(BASE_URL + updateCronJobUri, formDataObject, { return axios.post(BASE_URL + updateCronJobUri, formDataObject, {
params: { params: {
job, job,
token token: getAuthToken()
} }
}); });
} }

View file

@ -1,12 +1,12 @@
import axios from "axios"; import axios from "axios";
import { getAuthToken } from "src/utils/token";
const token = localStorage.getItem("token");
const BASE_URL = window.location.origin; const BASE_URL = window.location.origin;
const webApiUri = '/list/db/db.php'; const webApiUri = '/api/v1/list/db/index.php';
const addDbApiUri = '/api/add/db/index.php'; const addDbApiUri = '/api/v1/add/db/index.php';
const optionalDbInfoUri = '/api/add/db/index.php'; const optionalDbInfoUri = '/api/v1/add/db/index.php';
const dbInfoUri = '/api/edit/db/index.php'; const dbInfoUri = '/api/v1/edit/db/index.php';
const updateDatabaseUri = '/api/edit/db/index.php'; const updateDatabaseUri = '/api/v1/edit/db/index.php';
export const getDatabaseList = () => { export const getDatabaseList = () => {
return axios.get(BASE_URL + webApiUri); return axios.get(BASE_URL + webApiUri);
@ -15,17 +15,21 @@ export const getDatabaseList = () => {
export const bulkAction = (action, domainNameSystems) => { export const bulkAction = (action, domainNameSystems) => {
const formData = new FormData(); const formData = new FormData();
formData.append("action", action); formData.append("action", action);
formData.append("token", token); formData.append("token", getAuthToken());
domainNameSystems.forEach(domainNameSystem => { domainNameSystems.forEach(domainNameSystem => {
formData.append("database[]", domainNameSystem); formData.append("database[]", domainNameSystem);
}); });
return axios.post(BASE_URL + '/bulk/db/', formData); return axios.post(BASE_URL + '/api/v1/bulk/db/', formData);
}; };
export const handleAction = uri => { export const handleAction = uri => {
return axios.get(BASE_URL + uri); return axios.get(BASE_URL + uri, {
params: {
token: getAuthToken()
}
});
} }
export const getDbOptionalInfo = () => { export const getDbOptionalInfo = () => {
@ -85,7 +89,7 @@ export const getDatabaseInfo = database => {
return axios.get(BASE_URL + dbInfoUri, { return axios.get(BASE_URL + dbInfoUri, {
params: { params: {
database, database,
token token: getAuthToken()
} }
}); });
} }
@ -100,7 +104,7 @@ export const updateDatabase = (data, database) => {
return axios.post(BASE_URL + updateDatabaseUri, formDataObject, { return axios.post(BASE_URL + updateDatabaseUri, formDataObject, {
params: { params: {
database, database,
token token: getAuthToken()
} }
}); });
} }

View file

@ -1,11 +1,11 @@
import axios from "axios"; import axios from "axios";
import { getAuthToken } from "src/utils/token";
const updateDNSUri = '/api/edit/dns/index.php'; const updateDNSUri = '/api/v1/edit/dns/index.php';
const addDnsApiUri = '/api/add/dns/index.php'; const addDnsApiUri = '/api/v1/add/dns/index.php';
const dNSInfoUri = '/api/edit/dns/index.php'; const dNSInfoUri = '/api/v1/edit/dns/index.php';
const token = localStorage.getItem("token");
const BASE_URL = window.location.origin; const BASE_URL = window.location.origin;
const dnsApiUri = '/list/dns/dns.php'; const dnsApiUri = '/api/v1/list/dns/index.php';
export const getDnsList = () => { export const getDnsList = () => {
return axios.get(BASE_URL + dnsApiUri); return axios.get(BASE_URL + dnsApiUri);
@ -22,17 +22,21 @@ export const getDNSRecordInfo = (domain, recordId) => {
export const bulkAction = (action, domainNameSystems) => { export const bulkAction = (action, domainNameSystems) => {
const formData = new FormData(); const formData = new FormData();
formData.append("action", action); formData.append("action", action);
formData.append("token", token); formData.append("token", getAuthToken());
domainNameSystems.forEach(domainNameSystem => { domainNameSystems.forEach(domainNameSystem => {
formData.append("domain[]", domainNameSystem); formData.append("domain[]", domainNameSystem);
}); });
return axios.post(BASE_URL + '/bulk/dns/', formData); return axios.post(BASE_URL + '/api/v1/bulk/dns/', formData);
}; };
export const handleAction = uri => { export const handleAction = uri => {
return axios.get(BASE_URL + uri); return axios.get(BASE_URL + uri, {
params: {
token: getAuthToken()
}
});
} }
export const addDomainNameSystem = data => { export const addDomainNameSystem = data => {
@ -59,12 +63,12 @@ export const getDNSInfo = domain => {
return axios.get(BASE_URL + dNSInfoUri, { return axios.get(BASE_URL + dNSInfoUri, {
params: { params: {
domain, domain,
token token: getAuthToken()
} }
}); });
} }
export const updateDNS = (data, domain) => { export const updateDNS = (data, domain, recordId) => {
let formDataObject = new FormData(); let formDataObject = new FormData();
for (let key in data) { for (let key in data) {
@ -74,7 +78,8 @@ export const updateDNS = (data, domain) => {
return axios.post(BASE_URL + updateDNSUri, formDataObject, { return axios.post(BASE_URL + updateDNSUri, formDataObject, {
params: { params: {
domain, domain,
token record_id: recordId,
token: getAuthToken()
} }
}); });
} }

View file

@ -1,6 +1,6 @@
import axios from "axios"; import axios from "axios";
let addFavoriteUri = '/add/favorite/index.php'; let addFavoriteUri = '/api/v1/add/favorite/index.php';
let deleteFavoriteUri = '/delete/favorite/index.php'; let deleteFavoriteUri = '/api/v1/delete/favorite/index.php';
let BASE_URL = window.location.origin; let BASE_URL = window.location.origin;

View file

@ -1,13 +1,13 @@
import axios from 'axios'; import axios from 'axios';
import { getAuthToken } from 'src/utils/token';
const BASE_URL = window.location.origin; const BASE_URL = window.location.origin;
const token = localStorage.getItem("token"); const usersUri = '/api/v1/list/firewall/index.php';
const usersUri = '/list/firewall/firewall.php'; const addFirewallUri = '/api/v1/add/firewall/index.php';
const addFirewallUri = '/api/add/firewall/index.php'; const firewallInfoUri = '/api/v1/edit/firewall/index.php';
const firewallInfoUri = '/api/edit/firewall/index.php'; const updateFirewallUri = '/api/v1/edit/firewall/index.php';
const updateFirewallUri = '/api/edit/firewall/index.php'; const addBanIpsUri = '/api/v1/add/firewall/banlist/index.php';
const addBanIpsUri = '/api/add/firewall/banlist/index.php'; const banListUri = '/api/v1/list/firewall/banlist/index.php';
const banListUri = '/list/firewall/banlist/banlist.php';
export const getFirewallList = () => { export const getFirewallList = () => {
return axios.get(BASE_URL + usersUri); return axios.get(BASE_URL + usersUri);
@ -20,17 +20,21 @@ export const getBanList = () => {
export const bulkAction = (action, firewalls) => { export const bulkAction = (action, firewalls) => {
const formData = new FormData(); const formData = new FormData();
formData.append("action", action); formData.append("action", action);
formData.append("token", token); formData.append("token", getAuthToken());
firewalls.forEach(firewall => { firewalls.forEach(firewall => {
formData.append("rule[]", firewall); formData.append("rule[]", firewall);
}); });
return axios.post(BASE_URL + '/bulk/firewall/', formData); return axios.post(BASE_URL + '/api/v1/bulk/firewall/', formData);
}; };
export const handleAction = uri => { export const handleAction = uri => {
return axios.get(BASE_URL + uri); return axios.get(BASE_URL + uri, {
params: {
token: getAuthToken()
}
});
} }
export const getBanIps = data => { export const getBanIps = data => {
@ -42,7 +46,7 @@ export const getBanIps = data => {
return axios.get(BASE_URL + addBanIpsUri, { return axios.get(BASE_URL + addBanIpsUri, {
params: { params: {
token token: getAuthToken()
} }
}); });
} }
@ -56,7 +60,7 @@ export const addBanIp = (data) => {
return axios.get(BASE_URL + addBanIpsUri, { return axios.get(BASE_URL + addBanIpsUri, {
params: { params: {
token token: getAuthToken()
} }
}); });
} }
@ -75,7 +79,7 @@ export const getFirewallInfo = rule => {
return axios.get(BASE_URL + firewallInfoUri, { return axios.get(BASE_URL + firewallInfoUri, {
params: { params: {
rule, rule,
token token: getAuthToken()
} }
}); });
} }
@ -90,7 +94,7 @@ export const updateFirewall = (data, rule) => {
return axios.post(BASE_URL + updateFirewallUri, formDataObject, { return axios.post(BASE_URL + updateFirewallUri, formDataObject, {
params: { params: {
rule, rule,
token token: getAuthToken()
} }
}); });
} }

View file

@ -1,22 +1,20 @@
const { i18n } = window.GLOBAL.App; export const generatorOptions = i18n => {
return {
export const minutesRunCommandsOptions = [ minutesRunCommandsOptions: [
{ name: i18n['every minute'] ?? 'every minute', value: '*' }, { name: i18n['every minute'] ?? 'every minute', value: '*' },
{ name: i18n['every two minutes'] ?? 'every two minutes', value: '*/2' }, { name: i18n['every two minutes'] ?? 'every two minutes', value: '*/2' },
{ name: `${i18n.every || 'every'} 5`, value: '*/5' }, { name: `${i18n.every || 'every'} 5`, value: '*/5' },
{ name: `${i18n.every || 'every'} 10`, value: '*/10' }, { name: `${i18n.every || 'every'} 10`, value: '*/10' },
{ name: `${i18n.every || 'every'} 15`, value: '*/15' }, { name: `${i18n.every || 'every'} 15`, value: '*/15' },
{ name: `${i18n.every || 'every'} 30`, value: '*/30' } { name: `${i18n.every || 'every'} 30`, value: '*/30' }
]; ],
hoursRunCommandsOptions: [
export const hoursRunCommandsOptions = [
{ name: i18n['every hour'] ?? 'every hour', value: '*' }, { name: i18n['every hour'] ?? 'every hour', value: '*' },
{ name: i18n['every two hours'] ?? 'every two hours', value: '*/2' }, { name: i18n['every two hours'] ?? 'every two hours', value: '*/2' },
{ name: `${i18n.every || 'every'} 6`, value: '*/6' }, { name: `${i18n.every || 'every'} 6`, value: '*/6' },
{ name: `${i18n.every || 'every'} 12`, value: '*/12' } { name: `${i18n.every || 'every'} 12`, value: '*/12' }
]; ],
daysRunCommandsOptions: [
export const daysRunCommandsOptions = [
{ name: i18n['every day'] ?? 'every day', value: '*' }, { name: i18n['every day'] ?? 'every day', value: '*' },
{ name: i18n['every odd day'] ?? 'every odd day', value: '1-31/2' }, { name: i18n['every odd day'] ?? 'every odd day', value: '1-31/2' },
{ name: i18n['every even day'] ?? 'every even day', value: '*/2' }, { name: i18n['every even day'] ?? 'every even day', value: '*/2' },
@ -24,9 +22,8 @@ export const daysRunCommandsOptions = [
{ name: `${i18n.every || 'every'} 5`, value: '*/5' }, { name: `${i18n.every || 'every'} 5`, value: '*/5' },
{ name: `${i18n.every || 'every'} 10`, value: '*/10' }, { name: `${i18n.every || 'every'} 10`, value: '*/10' },
{ name: `${i18n.every || 'every'} 15`, value: '*/15' } { name: `${i18n.every || 'every'} 15`, value: '*/15' }
]; ],
hoursOptions: [
export const hoursOptions = [
{ name: '00', value: '0' }, { name: '00', value: '0' },
{ name: '01', value: '1' }, { name: '01', value: '1' },
{ name: '02', value: '2' }, { name: '02', value: '2' },
@ -51,16 +48,14 @@ export const hoursOptions = [
{ name: '21', value: '21' }, { name: '21', value: '21' },
{ name: '22', value: '22' }, { name: '22', value: '22' },
{ name: '23', value: '23' } { name: '23', value: '23' }
]; ],
hourlyMinutesOptions: [
export const hourlyMinutesOptions = [
{ name: '00', value: '0' }, { name: '00', value: '0' },
{ name: '15', value: '15' }, { name: '15', value: '15' },
{ name: '30', value: '30' }, { name: '30', value: '30' },
{ name: '45', value: '45' } { name: '45', value: '45' }
]; ],
dailyMinutesOptions: [
export const dailyMinutesOptions = [
{ name: '00', value: '0' }, { name: '00', value: '0' },
{ name: '01', value: '1' }, { name: '01', value: '1' },
{ name: '02', value: '2' }, { name: '02', value: '2' },
@ -75,9 +70,8 @@ export const dailyMinutesOptions = [
{ name: '45', value: '45' }, { name: '45', value: '45' },
{ name: '50', value: '50' }, { name: '50', value: '50' },
{ name: '55', value: '55' } { name: '55', value: '55' }
]; ],
weeklyRunCommandOptions: [
export const weeklyRunCommandOptions = [
{ name: i18n['every day'] ?? 'every day', value: '*' }, { name: i18n['every day'] ?? 'every day', value: '*' },
{ name: i18n['weekdays (5 days)'] ?? 'weekdays (5 days)', value: '1,2,3,4,5' }, { name: i18n['weekdays (5 days)'] ?? 'weekdays (5 days)', value: '1,2,3,4,5' },
{ name: i18n['weekend (2 days)'] ?? 'weekend (2 days)', value: '0,6' }, { name: i18n['weekend (2 days)'] ?? 'weekend (2 days)', value: '0,6' },
@ -88,9 +82,8 @@ export const weeklyRunCommandOptions = [
{ name: i18n.Friday ?? 'Friday', value: '5' }, { name: i18n.Friday ?? 'Friday', value: '5' },
{ name: i18n.Saturday ?? 'Saturday', value: '6' }, { name: i18n.Saturday ?? 'Saturday', value: '6' },
{ name: i18n.Sunday ?? 'Sunday', value: '0' } { name: i18n.Sunday ?? 'Sunday', value: '0' }
]; ],
monthlyRunCommandOptions: [
export const monthlyRunCommandOptions = [
{ name: i18n['every month'] ?? 'every month', value: '*' }, { name: i18n['every month'] ?? 'every month', value: '*' },
{ name: i18n['every odd month'] ?? 'every odd month', value: '1-11/2' }, { name: i18n['every odd month'] ?? 'every odd month', value: '1-11/2' },
{ name: i18n['every even month'] ?? 'every even month', value: '*/2' }, { name: i18n['every even month'] ?? 'every even month', value: '*/2' },
@ -108,9 +101,8 @@ export const monthlyRunCommandOptions = [
{ name: i18n.Oct ?? 'Oct', value: '10' }, { name: i18n.Oct ?? 'Oct', value: '10' },
{ name: i18n.Nov ?? 'Nov', value: '11' }, { name: i18n.Nov ?? 'Nov', value: '11' },
{ name: i18n.Dec ?? 'Dec', value: '12' } { name: i18n.Dec ?? 'Dec', value: '12' }
]; ],
dateOptions: [
export const dateOptions = [
{ name: '1', value: '1' }, { name: '1', value: '1' },
{ name: '2', value: '2' }, { name: '2', value: '2' },
{ name: '3', value: '3' }, { name: '3', value: '3' },
@ -142,4 +134,6 @@ export const dateOptions = [
{ name: '29', value: '29' }, { name: '29', value: '29' },
{ name: '30', value: '30' }, { name: '30', value: '30' },
{ name: '31', value: '31' } { name: '31', value: '31' }
]; ]
}
}

View file

@ -1,12 +1,12 @@
import axios from "axios"; import axios from "axios";
import { getAuthToken } from "src/utils/token";
const token = localStorage.getItem("token");
const BASE_URL = window.location.origin; const BASE_URL = window.location.origin;
const webApiUri = '/list/ip/ip.php'; const webApiUri = '/api/v1/list/ip/index.php';
const addIpApiUri = '/api/add/ip/index.php'; const addIpApiUri = '/api/v1/add/ip/index.php';
const additionalInfoUri = '/api/add/ip/index.php'; const additionalInfoUri = '/api/v1/add/ip/index.php';
const ipInfoUri = '/api/edit/ip/index.php'; const ipInfoUri = '/api/v1/edit/ip/index.php';
const updateIpUri = '/api/edit/ip/index.php'; const updateIpUri = '/api/v1/edit/ip/index.php';
export const getIpList = () => { export const getIpList = () => {
return axios.get(BASE_URL + webApiUri); return axios.get(BASE_URL + webApiUri);
@ -15,18 +15,21 @@ export const getIpList = () => {
export const bulkAction = (action, internetProtocols) => { export const bulkAction = (action, internetProtocols) => {
const formData = new FormData(); const formData = new FormData();
formData.append("action", action); formData.append("action", action);
formData.append("token", token); formData.append("token", getAuthToken());
internetProtocols.forEach(internetProtocol => { internetProtocols.forEach(internetProtocol => {
formData.append("ip[]", internetProtocol); formData.append("ip[]", internetProtocol);
formData.append("delete_url", `/delete/ip/?ip=${internetProtocol}&token=${token}`);
}); });
return axios.post(BASE_URL + '/bulk/ip/', formData); return axios.post(BASE_URL + '/api/v1/bulk/ip/', formData);
}; };
export const handleAction = uri => { export const handleAction = uri => {
return axios.get(BASE_URL + uri); return axios.get(BASE_URL + uri, {
params: {
token: getAuthToken()
}
});
} }
export const getAdditionalInfo = () => { export const getAdditionalInfo = () => {
@ -47,7 +50,7 @@ export const getInternetProtocolInfo = ip => {
return axios.get(BASE_URL + ipInfoUri, { return axios.get(BASE_URL + ipInfoUri, {
params: { params: {
ip, ip,
token token: getAuthToken()
} }
}); });
} }
@ -62,7 +65,7 @@ export const updateInternetProtocol = (data, ip) => {
return axios.post(BASE_URL + updateIpUri, formDataObject, { return axios.post(BASE_URL + updateIpUri, formDataObject, {
params: { params: {
ip, ip,
token token: getAuthToken()
} }
}); });
} }

View file

@ -1,6 +1,6 @@
import axios from "axios"; import axios from "axios";
const webApiUri = '/api/languages.php'; const webApiUri = '/api/v1/languages.php';
const BASE_URL = window.location.origin; const BASE_URL = window.location.origin;
export const getLanguages = () => { export const getLanguages = () => {

View file

@ -1,7 +1,7 @@
import axios from "axios"; import axios from "axios";
const BASE_URL = window.location.origin; const BASE_URL = window.location.origin;
const webApiUri = '/list/log/log.php'; const webApiUri = '/api/v1/list/log/index.php';
export const getLogsList = () => { export const getLogsList = () => {
return axios.get(BASE_URL + webApiUri); return axios.get(BASE_URL + webApiUri);

View file

@ -1,12 +1,11 @@
import axios from "axios"; import axios from "axios";
import { getAuthToken } from "src/utils/token";
const token = localStorage.getItem("token");
const { i18n } = window.GLOBAL.App;
const BASE_URL = window.location.origin; const BASE_URL = window.location.origin;
const webApiUri = '/list/mail/mail.php'; const webApiUri = '/api/v1/list/mail/index.php';
const addMailApiUri = '/api/add/mail/index.php'; const addMailApiUri = '/api/v1/add/mail/index.php';
const mailInfoUri = '/api/edit/mail/index.php'; const mailInfoUri = '/api/v1/edit/mail/index.php';
const updateMailUri = '/api/edit/mail/index.php'; const updateMailUri = '/api/v1/edit/mail/index.php';
export const getMailList = () => { export const getMailList = () => {
return axios.get(BASE_URL + webApiUri); return axios.get(BASE_URL + webApiUri);
@ -23,30 +22,34 @@ export const getMailAccountInfo = (domain, account) => {
export const bulkAction = (action, domainNameSystems) => { export const bulkAction = (action, domainNameSystems) => {
const formData = new FormData(); const formData = new FormData();
formData.append("action", action); formData.append("action", action);
formData.append("token", token); formData.append("token", getAuthToken());
domainNameSystems.forEach(domainNameSystem => { domainNameSystems.forEach(domainNameSystem => {
formData.append("domain[]", domainNameSystem); formData.append("domain[]", domainNameSystem);
}); });
return axios.post(BASE_URL + '/bulk/mail/', formData); return axios.post(BASE_URL + '/api/v1/bulk/mail/', formData);
}; };
export const bulkMailAccountAction = (action, domain, accounts = []) => { export const bulkMailAccountAction = (action, domain, accounts = []) => {
const formData = new FormData(); const formData = new FormData();
formData.append("action", action); formData.append("action", action);
formData.append("token", token); formData.append("token", getAuthToken());
formData.append("domain", domain); formData.append("domain", domain);
accounts.forEach(account => { accounts.forEach(account => {
formData.append("account[]", account); formData.append("account[]", account);
}); });
return axios.post(BASE_URL + '/bulk/mail/', formData); return axios.post(BASE_URL + '/api/v1/bulk/mail/', formData);
}; };
export const handleAction = uri => { export const handleAction = uri => {
return axios.get(BASE_URL + uri); return axios.get(BASE_URL + uri, {
params: {
token: getAuthToken()
}
});
} }
export const addMail = data => { export const addMail = data => {
@ -83,7 +86,7 @@ export const getMailInfo = domain => {
return axios.get(BASE_URL + mailInfoUri, { return axios.get(BASE_URL + mailInfoUri, {
params: { params: {
domain, domain,
token token: getAuthToken()
} }
}); });
} }
@ -98,12 +101,12 @@ export const updateMail = (data, domain) => {
return axios.post(BASE_URL + updateMailUri, formDataObject, { return axios.post(BASE_URL + updateMailUri, formDataObject, {
params: { params: {
domain, domain,
token token: getAuthToken()
} }
}); });
} }
export const mailInfoBlockSelectOptions = [ export const mailInfoBlockSelectOptions = i18n => [
{ {
value: i18n['Use server hostname'], value: i18n['Use server hostname'],
type: 'hostname', type: 'hostname',

View file

@ -1,10 +1,16 @@
import axios from "axios"; import axios from "axios";
import { getAuthToken } from "src/utils/token";
let BASE_URL = window.location.origin; let BASE_URL = window.location.origin;
let getNotificationsUri = '/list/notifications/?ajax=1'; let getNotificationsUri = '/api/v1/list/notifications/index.php';
let deleteNotificationsUri = '/delete/notification'; let deleteNotificationsUri = '/api/v1/delete/notification/index.php';
export const getAppNotifications = () => { export const getAppNotifications = () => {
return axios.get(BASE_URL + getNotificationsUri); return axios.get(BASE_URL + getNotificationsUri, {
params: {
ajax: 1,
token: getAuthToken()
}
});
} }
export const deleteNotification = id => { export const deleteNotification = id => {
@ -12,7 +18,7 @@ export const deleteNotification = id => {
params: { params: {
'delete': 1, 'delete': 1,
'notification_id': id, 'notification_id': id,
'token': localStorage.getItem("token") token: getAuthToken()
} }
}); });
} }

View file

@ -1,12 +1,12 @@
import axios from "axios"; import axios from "axios";
import { getAuthToken } from "src/utils/token";
const BASE_URL = window.location.origin; const BASE_URL = window.location.origin;
const token = localStorage.getItem("token"); const webApiUri = '/api/v1/list/package/index.php';
const webApiUri = '/list/package/package.php'; const additionalPackageInfoUri = '/api/v1/add/package/index.php';
const additionalPackageInfoUri = '/api/add/package/index.php'; const addPackageUri = '/api/v1/add/package/index.php';
const addPackageUri = '/api/add/package/index.php'; const packageInfoUri = '/api/v1/edit/package/index.php';
const packageInfoUri = '/api/edit/package/index.php'; const updatePackageUri = '/api/v1/edit/package/index.php';
const updatePackageUri = '/api/edit/package/index.php';
export const getPackageList = () => { export const getPackageList = () => {
return axios.get(BASE_URL + webApiUri); return axios.get(BASE_URL + webApiUri);
@ -15,18 +15,21 @@ export const getPackageList = () => {
export const bulkAction = (action, backups) => { export const bulkAction = (action, backups) => {
const formData = new FormData(); const formData = new FormData();
formData.append("action", action); formData.append("action", action);
formData.append("token", token); formData.append("token", getAuthToken());
backups.forEach(backup => { backups.forEach(backup => {
formData.append("package[]", backup); formData.append("package[]", backup);
formData.append("delete_url", `/delete/package/?package=${backup}&token=${token}`);
}); });
return axios.post(BASE_URL + '/bulk/package/', formData); return axios.post(BASE_URL + '/api/v1/bulk/package/', formData);
}; };
export const handleAction = uri => { export const handleAction = uri => {
return axios.get(BASE_URL + uri); return axios.get(BASE_URL + uri, {
params: {
token: getAuthToken()
}
});
} }
export const addPackage = data => { export const addPackage = data => {
@ -47,7 +50,7 @@ export const getPackageInfo = item => {
return axios.get(BASE_URL + packageInfoUri, { return axios.get(BASE_URL + packageInfoUri, {
params: { params: {
package: item, package: item,
token token: getAuthToken()
} }
}); });
} }

View file

@ -1,12 +1,12 @@
import axios from "axios"; import axios from "axios";
const BASE_URL = window.location.origin; const BASE_URL = window.location.origin;
const webApiUri = '/list/rrd/rrd.php'; const webApiUri = '/api/v1/list/rrd/index.php';
export const getRrdList = () => { export const getRrdList = () => {
return axios.get(BASE_URL + webApiUri); return axios.get(BASE_URL + webApiUri);
} }
export function generateImagePath(period, type, rrd) { export function generateImagePath(period, type, rrd) {
return `/list/rrd/image.php?/rrd/${type}/${period}-${rrd}.png`; return `/api/v1/list/rrd/image.php?/rrd/${type}/${period}-${rrd}.png`;
} }

View file

@ -1,7 +1,7 @@
import axios from "axios"; import axios from "axios";
const BASE_URL = window.location.origin; const BASE_URL = window.location.origin;
const resetPasswordUri = '/api/reset/index.php'; const resetPasswordUri = '/api/v1/reset/index.php';
export const resetPassword = (user = '', code = '', password = '', confirmPassword = '') => { export const resetPassword = (user = '', code = '', password = '', confirmPassword = '') => {
const formData = new FormData(); const formData = new FormData();

View file

@ -1,4 +1,5 @@
import axios from "axios"; import axios from "axios";
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 = '/search/search.php';
@ -8,5 +9,9 @@ export const getSearchResultsList = term => {
} }
export const handleAction = uri => { export const handleAction = uri => {
return axios.get(BASE_URL + uri); return axios.get(BASE_URL + uri, {
params: {
token: getAuthToken()
}
});
} }

View file

@ -1,9 +1,9 @@
import axios from "axios"; import axios from "axios";
import { getAuthToken } from "src/utils/token";
const BASE_URL = window.location.origin; const BASE_URL = window.location.origin;
const token = localStorage.getItem("token"); const webApiUri = '/api/v1/list/server/index.php';
const webApiUri = '/list/server/server.php'; const serverAdditionalInfoUri = '/api/v1/edit/server/index.php';
const serverAdditionalInfoUri = '/api/edit/server/index.php';
export const getServersList = () => { export const getServersList = () => {
return axios.get(BASE_URL + webApiUri); return axios.get(BASE_URL + webApiUri);
@ -12,23 +12,27 @@ export const getServersList = () => {
export const bulkAction = (action, services) => { export const bulkAction = (action, services) => {
const formData = new FormData(); const formData = new FormData();
formData.append("action", action); formData.append("action", action);
formData.append("token", token); formData.append("token", getAuthToken());
services.forEach(service => { services.forEach(service => {
formData.append("service[]", service); formData.append("service[]", service);
}); });
return axios.post(BASE_URL + '/api/bulk/service/', formData); return axios.post(BASE_URL + '/api/v1/bulk/service/', formData);
}; };
export const handleAction = uri => { export const handleAction = uri => {
return axios.get(BASE_URL + uri); return axios.get(BASE_URL + uri, {
params: {
token: getAuthToken()
}
});
} }
export const getServerAdditionalInfo = () => { export const getServerAdditionalInfo = () => {
return axios.get(BASE_URL + serverAdditionalInfoUri, { return axios.get(BASE_URL + serverAdditionalInfoUri, {
params: { params: {
token token: getAuthToken()
} }
}); });
} }
@ -40,19 +44,19 @@ export const updateService = (data, uri = '') => {
formDataObject.append(key, data[key]); formDataObject.append(key, data[key]);
} }
return axios.post(BASE_URL + `/api/edit/server/${uri}/index.php`, formDataObject, { return axios.post(BASE_URL + `/api/v1/edit/server/${uri}/index.php`, formDataObject, {
params: { params: {
token token: getAuthToken()
} }
}); });
} }
export const getServiceInfo = service => { export const getServiceInfo = service => {
return axios.get(`${BASE_URL}/api/edit/server/${service}/index.php`); return axios.get(`${BASE_URL}/api/v1/edit/server/${service}/index.php`);
} }
export const getServiceLogs = service => { export const getServiceLogs = service => {
return axios.get(`${BASE_URL}/list/server/server.php?${service}`); return axios.get(`${BASE_URL}${webApiUri}?${service}`);
} }
export const services = [ export const services = [

View file

@ -1,7 +1,7 @@
import axios from "axios"; import axios from "axios";
const BASE_URL = window.location.origin; const BASE_URL = window.location.origin;
const webApiUri = '/list/stats/stats.php'; const webApiUri = '/api/v1/list/stats/index.php';
export const getStatisticsList = user => { export const getStatisticsList = user => {
return axios.get(BASE_URL + webApiUri + '?user=' + user); return axios.get(BASE_URL + webApiUri + '?user=' + user);

View file

@ -1,9 +1,9 @@
import axios from "axios"; import axios from "axios";
import { getAuthToken } from "src/utils/token";
const deleteAutoUpdateUri = '/delete/cron/autoupdate/'; const deleteAutoUpdateUri = '/delete/cron/autoupdate/';
const addAutoUpdateUri = '/add/cron/autoupdate/'; const addAutoUpdateUri = '/add/cron/autoupdate/';
const webApiUri = '/list/updates/updates.php'; const webApiUri = '/api/v1/list/updates/index.php';
const token = localStorage.getItem("token");
const BASE_URL = window.location.origin; const BASE_URL = window.location.origin;
export const getUpdatesList = () => { export const getUpdatesList = () => {
@ -13,23 +13,35 @@ export const getUpdatesList = () => {
export const bulkAction = (action, updates) => { export const bulkAction = (action, updates) => {
const formData = new FormData(); const formData = new FormData();
formData.append("action", action); formData.append("action", action);
formData.append("token", token); formData.append("token", getAuthToken());
updates.forEach(update => { updates.forEach(update => {
formData.append("pkg[]", update); formData.append("pkg[]", update);
}); });
return axios.post(BASE_URL + '/bulk/vesta/', formData); return axios.post(BASE_URL + '/api/v1/bulk/vesta/', formData);
}; };
export const handleAction = uri => { export const handleAction = uri => {
return axios.get(`${BASE_URL}${uri}?token=${token}`); return axios.get(BASE_URL + uri, {
params: {
token: getAuthToken()
}
});
} }
export const enableAutoUpdate = () => { export const enableAutoUpdate = () => {
return axios.get(`${BASE_URL}${addAutoUpdateUri}?token=${token}`); return axios.get(`${BASE_URL}${addAutoUpdateUri}`, {
params: {
token: getAuthToken()
}
});
}; };
export const disableAutoUpdate = () => { export const disableAutoUpdate = () => {
return axios.get(`${BASE_URL}${deleteAutoUpdateUri}?token=${token}`); return axios.get(`${BASE_URL}${deleteAutoUpdateUri}`, {
params: {
token: getAuthToken()
}
});
}; };

View file

@ -1,7 +1,7 @@
import axios from "axios"; import axios from "axios";
const BASE_URL = window.location.origin; const BASE_URL = window.location.origin;
const userNSApiUri = '/api/list-user-ns.php'; const userNSApiUri = '/api/v1/list-user-ns.php';
export const getUserNS = () => { export const getUserNS = () => {
return axios.get(BASE_URL + userNSApiUri); return axios.get(BASE_URL + userNSApiUri);

View file

@ -1,30 +1,38 @@
import axios from 'axios'; import axios from 'axios';
import { getAuthToken } from 'src/utils/token';
let token = localStorage.getItem('token');
const BASE_URL = window.location.origin; const BASE_URL = window.location.origin;
const usersUri = '/list/user/user.php'; const usersUri = '/api/v1/list/user/index.php';
const addUsersUri = '/api/add/user/index.php'; const addUsersUri = '/api/v1/add/user/index.php';
const userInfoUri = '/api/edit/user/index.php'; const userInfoUri = '/api/v1/edit/user/index.php';
const updateUserUri = '/api/edit/user/index.php'; const updateUserUri = '/api/v1/edit/user/index.php';
export const getUsersList = () => { export const getUsersList = () => {
return axios.get(BASE_URL + usersUri); return axios.get(BASE_URL + usersUri, {
params: {
token: getAuthToken()
}
});
} }
export const bulkAction = (action, selectedUsers) => { export const bulkAction = (action, selectedUsers) => {
const formData = new FormData(); const formData = new FormData();
formData.append("token", token); formData.append("token", getAuthToken());
formData.append("action", action); formData.append("action", action);
selectedUsers.forEach(user => { selectedUsers.forEach(user => {
formData.append("user[]", user); formData.append("user[]", user);
}); });
return axios.post(BASE_URL + '/bulk/user/', formData); return axios.post(BASE_URL + '/api/v1/bulk/user/', formData);
}; };
export const handleAction = uri => { export const handleAction = uri => {
return axios.get(BASE_URL + uri); return axios.get(BASE_URL + uri, {
params: {
token: getAuthToken()
}
});
} }
export const addUser = data => { export const addUser = data => {
@ -34,7 +42,7 @@ export const addUser = data => {
formDataObject.append(key, data[key]); formDataObject.append(key, data[key]);
} }
formDataObject.append("token", token); formDataObject.append("token", getAuthToken());
formDataObject.append("ok", "Add"); formDataObject.append("ok", "Add");
return axios.post(BASE_URL + addUsersUri, formDataObject); return axios.post(BASE_URL + addUsersUri, formDataObject);
@ -44,7 +52,7 @@ export const getUserInfo = username => {
return axios.get(BASE_URL + userInfoUri, { return axios.get(BASE_URL + userInfoUri, {
params: { params: {
user: username, user: username,
token token: getAuthToken()
} }
}); });
} }
@ -59,7 +67,7 @@ export const updateUser = (data, user) => {
return axios.post(BASE_URL + updateUserUri, formDataObject, { return axios.post(BASE_URL + updateUserUri, formDataObject, {
params: { params: {
user, user,
token token: getAuthToken()
} }
}); });
} }

View file

@ -1,12 +1,12 @@
import axios from "axios"; import axios from "axios";
import { getAuthToken } from "src/utils/token";
const token = localStorage.getItem("token");
const BASE_URL = window.location.origin; const BASE_URL = window.location.origin;
const addWebUri = '/api/add/web/index.php'; const addWebUri = '/api/v1/add/web/index.php';
const webApiUri = '/list/web/web.php'; const webApiUri = '/api/v1/list/web/index.php';
const webStatsUri = '/api/web-stats.php'; const webStatsUri = '/api/v1/web-stats.php';
const domainInfoUri = '/api/edit/web/index.php'; const domainInfoUri = '/api/v1/edit/web/index.php';
const updateDomainUri = '/api/edit/web/index.php'; const updateDomainUri = '/api/v1/edit/web/index.php';
export const getWebList = () => { export const getWebList = () => {
return axios.get(BASE_URL + webApiUri); return axios.get(BASE_URL + webApiUri);
@ -15,17 +15,21 @@ export const getWebList = () => {
export const bulkAction = (action, webDomains) => { export const bulkAction = (action, webDomains) => {
const formData = new FormData(); const formData = new FormData();
formData.append("action", action); formData.append("action", action);
formData.append("token", token); formData.append("token", getAuthToken());
webDomains.forEach(webDomain => { webDomains.forEach(webDomain => {
formData.append("domain[]", webDomain); formData.append("domain[]", webDomain);
}); });
return axios.post(BASE_URL + '/bulk/web/', formData); return axios.post(BASE_URL + '/api/v1/bulk/web/', formData);
}; };
export const handleAction = uri => { export const handleAction = uri => {
return axios.get(BASE_URL + uri); return axios.get(BASE_URL + uri, {
params: {
token: getAuthToken()
}
});
} }
export const addWeb = data => { export const addWeb = data => {
@ -46,7 +50,7 @@ export const getDomainInfo = domain => {
return axios.get(BASE_URL + domainInfoUri, { return axios.get(BASE_URL + domainInfoUri, {
params: { params: {
domain, domain,
token token: getAuthToken()
} }
}); });
} }
@ -61,7 +65,7 @@ export const updateWebDomain = (data, domain) => {
return axios.post(BASE_URL + updateDomainUri, formDataObject, { return axios.post(BASE_URL + updateDomainUri, formDataObject, {
params: { params: {
domain, domain,
token token: getAuthToken()
} }
}); });
} }

View file

@ -3,5 +3,5 @@ import axios from "axios";
const BASE_URL = window.location.origin; const BASE_URL = window.location.origin;
export const getWebLogs = uri => { export const getWebLogs = uri => {
return axios.get(BASE_URL + uri); return axios.get(BASE_URL + '/api/v1' +uri);
} }

View file

@ -1,23 +1,35 @@
import axios from "axios"; import axios from "axios";
import QueryString from "qs";
const server = window.location.origin + "/file_manager/fm_api.php?"; const server = window.location.origin + "/file_manager/fm_api.php?";
export function validateAction(url) { export function validateAction(url) {
return axios.get(url); return axios.get(url);
} }
export function cacheData(currentUser, history) { export function cacheData(currentUser, history, rootDir) {
const parsedQueryString = QueryString.parse(history.location.search, { ignoreQueryPrefix: true });
if (parsedQueryString.path) {
localStorage.setItem("activeWindow", "left");
localStorage.setItem("leftListPath", parsedQueryString.path);
localStorage.setItem("rightListPath", parsedQueryString.path);
return;
}
if (localStorage.getItem("lastUser") === null || currentUser !== localStorage.getItem("lastUser")) { if (localStorage.getItem("lastUser") === null || currentUser !== localStorage.getItem("lastUser")) {
localStorage.setItem("lastUser", currentUser); localStorage.setItem("lastUser", currentUser);
localStorage.setItem("activeWindow", "left"); localStorage.setItem("activeWindow", "left");
localStorage.setItem("leftListPath", window.GLOBAL.ROOT_DIR); localStorage.setItem("leftListPath", rootDir);
localStorage.setItem("rightListPath", window.GLOBAL.ROOT_DIR); localStorage.setItem("rightListPath", rootDir);
return;
} }
if (localStorage.getItem("activeWindow") === null || localStorage.getItem("leftListPath") === null || localStorage.getItem("rightListPath") === null) { if (localStorage.getItem("activeWindow") === null || localStorage.getItem("leftListPath") === null || localStorage.getItem("rightListPath") === null) {
let path = history.location.search.substring(6).split('/'); let path = history.location.search.substring(6).split('/');
localStorage.setItem("activeWindow", "left"); localStorage.setItem("activeWindow", "left");
localStorage.setItem("leftListPath", path); localStorage.setItem("leftListPath", path);
localStorage.setItem("rightListPath", window.GLOBAL.ROOT_DIR); localStorage.setItem("rightListPath", rootDir);
return;
} }
} }

View file

@ -0,0 +1,15 @@
import { ADD_NOTIFICATIONS, REMOVE_NOTIFICATIONS } from './notificationTypes';
export const addNotifications = value => {
return {
type: ADD_NOTIFICATIONS,
value
};
};
export const removeNotifications = () => {
return {
type: REMOVE_NOTIFICATIONS,
value: []
};
};

View file

@ -0,0 +1,2 @@
export const ADD_NOTIFICATIONS = 'ADD_NOTIFICATIONS';
export const REMOVE_NOTIFICATIONS = 'REMOVE_NOTIFICATIONS';

View file

@ -1,29 +1,31 @@
import { LOGIN, LOGOUT, LOGGED_OUT_AS, RESET_PASSWORD } from './sessionTypes'; import { LOGIN, LOGOUT, LOGGED_OUT_AS, CHECK_AUTH, RESET_PASSWORD } from './sessionTypes';
import { checkAuth, signIn, signInAs, signOut } from 'src/services/session'; import { checkAuth, signIn, signInAs, signOut } from 'src/services/session';
import { resetAuthToken, setAuthToken } from 'src/utils/token';
import { resetPassword } from 'src/ControlPanelService/ResetPassword'; import { resetPassword } from 'src/ControlPanelService/ResetPassword';
import { resetAuthToken, setAuthToken } from 'src/utils/token';
const LOGOUT_RESPONSE = 'logged_out'; const LOGOUT_RESPONSE = 'logged_out';
const LOGOUT_AS_RESPONSE = 'logged_out_as'; const LOGOUT_AS_RESPONSE = 'logged_out_as';
export const login = (user, password) => dispatch => { export const login = (user, password) => dispatch => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
signIn(user, password).then((response) => { signIn({ user, password }).then((response) => {
const { error, session, token, panel, data, user } = response.data; const { error, session, token, panel, data, user, i18n } = response.data;
if (token) setAuthToken(token); if (token) setAuthToken(token);
dispatch({ dispatch({
type: LOGIN, type: LOGIN,
value: { value: {
token: data ? token : '', token: token || '',
panel, panel,
session, session,
i18n: i18n || {},
userName: user, userName: user,
user: data, user: data,
error error
}, },
}); });
resolve(response.data); resolve(token);
}, (error) => { }, (error) => {
reject(error); reject(error);
}); });
@ -34,7 +36,6 @@ export const reset = ({ user = '', code = '', password = '', password_confirm =
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
resetPassword(user, code, password, password_confirm).then((response) => { resetPassword(user, code, password, password_confirm).then((response) => {
const { error, session, token, panel, user } = response.data; const { error, session, token, panel, user } = response.data;
if (token) setAuthToken(token);
dispatch({ dispatch({
type: RESET_PASSWORD, type: RESET_PASSWORD,
@ -47,7 +48,7 @@ export const reset = ({ user = '', code = '', password = '', password_confirm =
error error
}, },
}); });
resolve(response.data); resolve(token);
}, (error) => { }, (error) => {
reject(error); reject(error);
}); });
@ -57,22 +58,23 @@ export const reset = ({ user = '', code = '', password = '', password_confirm =
export const loginAs = username => dispatch => { export const loginAs = username => dispatch => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
signInAs(username).then((response) => { signInAs(username).then((response) => {
const { error, token, session, panel, data, user } = response.data; const { error, token, session, panel, data, user, i18n } = response.data;
if (token) setAuthToken(token); if (token) setAuthToken(token);
dispatch({ dispatch({
type: LOGIN, type: LOGIN,
value: { value: {
token,
panel,
session,
userName: user, userName: user,
user: data, user: data,
error, i18n,
}, session,
panel,
token,
error
}
}); });
resolve(response.data); resolve(token);
}, (error) => { }, (error) => {
console.error(error); console.error(error);
reject(); reject();
@ -83,7 +85,7 @@ export const loginAs = username => dispatch => {
export const logout = () => (dispatch, getState) => { export const logout = () => (dispatch, getState) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
signOut().then((response) => { signOut().then((response) => {
const { logout_response, panel, session, user, data, token } = response.data; const { logout_response, error, userName, user, i18n, session, panel } = response.data;
if (logout_response === LOGOUT_RESPONSE) { if (logout_response === LOGOUT_RESPONSE) {
resetAuthToken(); resetAuthToken();
@ -91,27 +93,28 @@ export const logout = () => (dispatch, getState) => {
dispatch({ dispatch({
type: LOGOUT, type: LOGOUT,
value: { value: {
userName: user, userName: '',
user: {}, user: {},
token, token: '',
panel, panel: {},
session, session: {},
error: '' i18n: [],
error,
}, },
}); });
resolve(); resolve();
} else if (logout_response === LOGOUT_AS_RESPONSE) { } else if (logout_response === LOGOUT_AS_RESPONSE) {
const { token } = getState().session;
dispatch({ dispatch({
type: LOGGED_OUT_AS, type: LOGGED_OUT_AS,
value: { value: {
userName: user, userName,
user: data, user,
session, session,
panel, panel,
token, token: '',
error: '' i18n,
error,
}, },
}); });
@ -126,17 +129,18 @@ export const logout = () => (dispatch, getState) => {
}); });
} }
export const setToken = (token) => (dispatch, getState) => { export const checkAuthHandler = () => (dispatch, getState) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
checkAuth(token) checkAuth()
.then(res => { .then(res => {
const { user, data, session, panel, error } = res.data; const { user, data, session, panel, error, i18n, token } = res.data;
dispatch({ dispatch({
type: LOGIN, type: CHECK_AUTH,
value: { value: {
userName: user, userName: user,
user: data, user: data,
i18n,
session, session,
panel, panel,
token, token,
@ -144,7 +148,7 @@ export const setToken = (token) => (dispatch, getState) => {
} }
}); });
resolve(); resolve(token);
}) })
.catch(err => { .catch(err => {
reject(); reject();

View file

@ -1,5 +1,6 @@
export const LOGIN = 'LOGIN'; export const LOGIN = 'LOGIN';
export const LOGOUT = 'LOGOUT'; export const LOGOUT = 'LOGOUT';
export const LOGIN_AS = 'LOGIN_AS'; export const LOGIN_AS = 'LOGIN_AS';
export const CHECK_AUTH = 'CHECK_AUTH';
export const LOGGED_OUT_AS = 'LOGGED_OUT_AS'; export const LOGGED_OUT_AS = 'LOGGED_OUT_AS';
export const RESET_PASSWORD = 'RESET_PASSWORD'; export const RESET_PASSWORD = 'RESET_PASSWORD';

View file

@ -5,10 +5,11 @@ import Container from '../ControlPanel/Container/Container';
import { faFileDownload } from '@fortawesome/free-solid-svg-icons' import { faFileDownload } from '@fortawesome/free-solid-svg-icons'
import './Backup.scss'; import './Backup.scss';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { useSelector } from 'react-redux';
const Backup = props => { const Backup = props => {
const { data } = props; const { data } = props;
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const toggleFav = (starred) => { const toggleFav = (starred) => {
@ -24,7 +25,7 @@ const Backup = props => {
} }
const handleDelete = () => { const handleDelete = () => {
props.handleModal(data.delete_conf, `/delete/backup/?backup=${data.NAME}&token=${token}`); props.handleModal(data.delete_conf, `/api/v1/delete/backup/?backup=${data.NAME}`);
} }
return ( return (

View file

@ -7,14 +7,14 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Toolbar from 'src/components/MainNav/Toolbar/Toolbar'; import Toolbar from 'src/components/MainNav/Toolbar/Toolbar';
import Spinner from 'src/components/Spinner/Spinner'; import Spinner from 'src/components/Spinner/Spinner';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import { useDispatch } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import './style.scss'; import './style.scss';
const EditBackupExclusions = () => { const EditBackupExclusions = () => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const history = useHistory(); const history = useHistory();
const dispatch = useDispatch(); const dispatch = useDispatch();
const [state, setState] = useState({ const [state, setState] = useState({

View file

@ -1,16 +1,19 @@
import React from 'react'; import React from 'react';
import { useSelector } from 'react-redux';
import Container from '../../ControlPanel/Container/Container'; import Container from '../../ControlPanel/Container/Container';
import './style.scss'; import './style.scss';
const Exclusion = ({ data, focused }) => { const Exclusion = ({ data, focused }) => {
const { i18n } = useSelector(state => state.session);
const renderExclusionItems = () => { const renderExclusionItems = () => {
if (!Array.isArray(data.ITEMS)) { if (!Array.isArray(data.ITEMS)) {
for (let item in data.ITEMS) { for (let item in data.ITEMS) {
return <><b>{item}</b> &nbsp; {data.ITEMS[item]}<br /></>; return <><b>{item}</b> &nbsp; {data.ITEMS[item]}<br /></>;
} }
} else { } else {
return window.GLOBAL.App.i18n['no exclusions']; return i18n['no exclusions'];
} }
} }

View file

@ -5,9 +5,10 @@ import ListItem from '../../ControlPanel/ListItem/ListItem';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import './RestoreSetting.scss'; import './RestoreSetting.scss';
import { useSelector } from 'react-redux';
export default function RestoreSetting({ data, checkItemFunc = () => { }, restoreSetting = () => { } }) { export default function RestoreSetting({ data, checkItemFunc = () => { }, restoreSetting = () => { } }) {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const displayBackupDetailName = type => { const displayBackupDetailName = type => {
switch (type) { switch (type) {

View file

@ -1,3 +1,14 @@
$whiteBackground: #ececec;
$primary: #2c54ac;
$primaryLight: #d7dcef;
$primaryActive: #1e5cb2;
$secondary: #fcac04;
$secondaryLight: #f8b014;
$secondaryActive: #fdb51c;
$hoverButtonText: #2c54ac;
$activeButtonText: #fff;
$textColor: #555;
.backups-restore-settings { .backups-restore-settings {
.list-item { .list-item {
.r-col { .r-col {
@ -18,12 +29,12 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
color: #777; color: $textColor;
padding: 10px 15px; padding: 10px 15px;
text-decoration: none; text-decoration: none;
&:hover { &:hover {
background: rgb(145, 145, 145); background: $whiteBackground;
color: white; color: white;
svg { svg {
@ -33,7 +44,7 @@
} }
svg { svg {
color: #777; color: $textColor;
} }
} }
@ -43,7 +54,13 @@
} }
&:hover { &:hover {
background-color: #9fbf0c; color: $hoverButtonText;
background-color: $primaryLight;
}
&:hover {
color: $activeButtonText;
background-color: $primaryActive;
} }
} }
} }

View file

@ -17,7 +17,7 @@ import { Helmet } from 'react-helmet';
import './BackupRestoreSettings.scss'; import './BackupRestoreSettings.scss';
export default function BackupRestoreSettings(props) { export default function BackupRestoreSettings(props) {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token"); 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);
@ -153,6 +153,8 @@ export default function BackupRestoreSettings(props) {
setState({ setState({
...state, ...state,
totalAmount: result.data.totalAmount, totalAmount: result.data.totalAmount,
selection: [],
toggledAll: false,
loading: false loading: false
}); });
}) })
@ -165,7 +167,7 @@ export default function BackupRestoreSettings(props) {
acc.push({ acc.push({
type: cat, type: cat,
name: item, name: item,
restoreLinkParams: `?backup=${props.backup}&type=${cat.toLowerCase()}&object=${item}&token=${token}` restoreLinkParams: `?backup=${props.backup}&type=${cat.toLowerCase()}&object=${item}`
}); });
}); });

View file

@ -1,15 +1,22 @@
$whiteBackground: #ececec;
$primary: #2c54ac;
$primaryLight: #d7dcef;
$primaryActive: #1e5cb2;
$secondary: #fcac04;
$secondaryLight: #f8b014;
$secondaryActive: #fdb51c;
$hoverButtonText: #2c54ac;
$activeButtonText: #fff;
$textColor: #555; $textColor: #555;
$addButtonBackground: #9FBF0C;
$addButtonBackgroundHover: #C0E60F; $optionalButtonHover: $primary;
$optionalButtonHover: #9FBF0C; $optionalButtonActive: $primaryLight;
$optionalButtonActive: #c0e60f; $deleteButtonColorHover: #b00e5b;
$deleteButtonColorHover: #FF3438; $deleteButtonColorActive: #b11661;
$deleteButtonColorActive: #FF5F5F;
$backButtonBackground: #DFDEDD; $backButtonBackground: #DFDEDD;
$backButtonBackgroundHover: #999; $backButtonBackgroundHover: #999;
$transition: all 200ms cubic-bezier(0.4, 0.1, 0.5, 0.85); $transition: all 200ms cubic-bezier(0.4, 0.1, 0.5, 0.85);
$errorColor: #BE5ABF; $errorColor: #BE5ABF;
$successColor: $addButtonBackground;
.content .edit-template { .content .edit-template {
padding-bottom: 2rem; padding-bottom: 2rem;
@ -25,7 +32,7 @@ $successColor: $addButtonBackground;
div.error, div.error,
div.success { div.success {
width: fit-content; width: fit-content !important;
span { span {
font-weight: bold; font-weight: bold;
@ -47,10 +54,10 @@ $successColor: $addButtonBackground;
} }
span.ok-message { span.ok-message {
color: $successColor; color: $primary;
svg { svg {
color: $successColor; color: $primary;
} }
} }
} }
@ -84,15 +91,15 @@ $successColor: $addButtonBackground;
form { form {
button, button,
a { a {
color:#2C9491; color:$primary;
font-weight: bold; font-weight: bold;
&:hover { &:hover {
color: #ff6701; color: $secondaryLight;
} }
&:active { &:active {
color: #F7D616; color: $secondaryActive;
} }
} }
@ -139,14 +146,14 @@ $successColor: $addButtonBackground;
&:focus, &:focus,
&:active { &:active {
outline: none; outline: none;
border-color: #55C9C0; border-color: $primaryActive;
box-shadow: unset; box-shadow: unset;
} }
} }
textarea { textarea {
&:focus { &:focus {
background: #D7F9FF;; background: #D7F9FF;
} }
} }
@ -172,7 +179,7 @@ $successColor: $addButtonBackground;
&:focus, &:focus,
&:active { &:active {
box-shadow: unset; box-shadow: unset;
border-color: #55C9C0; border-color: $primaryActive;
background: #D7F9FF; background: #D7F9FF;
} }
} }
@ -221,12 +228,17 @@ $successColor: $addButtonBackground;
} }
.add { .add {
color: white; color: $activeButtonText;
background: $addButtonBackground; background: $primary;
&:hover { &:hover {
color: #555; color: $hoverButtonText;
background: $addButtonBackgroundHover; background: $primaryLight;
}
&:active {
color: $activeButtonText;
background: $primaryActive;
} }
} }
@ -258,7 +270,7 @@ $successColor: $addButtonBackground;
} }
.status { .status {
color: #9FBF0C; color: $primary;
font-size: 11px; font-size: 11px;
letter-spacing: 1px; letter-spacing: 1px;
text-transform: uppercase; text-transform: uppercase;

View file

@ -1,17 +1,11 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
const Checkbox = ({ name, id, title, defaultChecked = false, onChange = () => { }, checked }) => { const Checkbox = ({ name, id, title, defaultChecked = false, onChange = () => { }, checked }) => {
const [checkedState, setCheckedState] = useState(false); const [checkedState, setCheckedState] = useState(defaultChecked);
useEffect(() => { useEffect(() => {
if (!!checked) {
setCheckedState(checked); setCheckedState(checked);
} }, [checked]);
if (!!defaultChecked) {
setCheckedState(defaultChecked);
}
}, [checked, defaultChecked]);
const changeCheckbox = event => { const changeCheckbox = event => {
setCheckedState(event.target.checked); setCheckedState(event.target.checked);

View file

@ -1,7 +1,8 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
const NameServers = props => { const NameServers = props => {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const [state, setState] = useState({ const [state, setState] = useState({
nameServersAmount: [], nameServersAmount: [],
usersNS: [] usersNS: []

View file

@ -1,8 +1,9 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
const Password = ({ defaultValue, onChange = () => { }, id, name, title, showGenerationButton = true, ...props }) => { const Password = ({ defaultValue, onChange = () => { }, id, name, title, showGenerationButton = true, ...props }) => {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const [state, setState] = useState({ const [state, setState] = useState({
hidePassword: false, hidePassword: false,
generatedPassword: '' generatedPassword: ''

View file

@ -1,7 +1,8 @@
import React from 'react'; import React from 'react';
import { useSelector } from 'react-redux';
const SelectInput = ({ options = [], id, name, title, optionalTitle = '', selected = '', onChange = () => { }, disabled = false }) => { const SelectInput = ({ options = [], id, name, title, optionalTitle = '', selected = '', onChange = () => { }, disabled = false }) => {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const renderOptions = () => { const renderOptions = () => {
return options.map((option, index) => return options.map((option, index) =>

View file

@ -1,9 +1,10 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import './Hotkeys.scss'; import './Hotkeys.scss';
import { useSelector } from 'react-redux';
const Hotkeys = props => { const Hotkeys = props => {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
useEffect(() => { useEffect(() => {
window.addEventListener("keyup", toggleShortcutsLit); window.addEventListener("keyup", toggleShortcutsLit);

View file

@ -1,3 +1,5 @@
$secondary: #fcac04;
.hotkeys-list { .hotkeys-list {
position: fixed; position: fixed;
bottom: 0; bottom: 0;
@ -6,39 +8,36 @@
flex-direction: column; flex-direction: column;
transform: translateX(-45%); transform: translateX(-45%);
width: 53%; width: 53%;
background: rgba(50, 50, 50, 0.9); background: #222e44de;
font-size: 13px; font-size: 13px;
.head { .head {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
border-bottom: 1px solid #333; border-bottom: 1px solid $secondary;
.name { .name {
text-transform: uppercase; text-transform: uppercase;
padding: 5px 0 5px 10px; padding: 5px 0 5px 10px;
font-size: 12px; font-size: 12px;
font-weight: bold; font-weight: bold;
color: #ffcc00; color: $secondary;
letter-spacing: 2px; letter-spacing: 2px;
padding: 15px; padding: 15px;
} }
.close { .close {
padding: 12px; padding: 12px;
opacity: 1 !important;
svg { svg {
color: #a1a1a1; color: $secondary;
} }
&:hover { &:hover {
cursor: pointer; cursor: pointer;
background: black; background: #222e44;
}
&:active {
background: #55c9c0;
} }
} }
} }
@ -58,12 +57,12 @@
span.name { span.name {
margin-right: 15px; margin-right: 15px;
color: #48F4EF; color: $secondary;
font-weight: bold; font-weight: bold;
} }
span.description { span.description {
color: #929292; color: white;
} }
} }

View file

@ -1,24 +1,20 @@
import React, { Component } from 'react'; import React, { Component, useEffect, useState } from 'react';
import Container from '../Container/Container'; import Container from '../Container/Container';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { useSelector } from 'react-redux';
import './ListItem.scss'; import './ListItem.scss';
class ListItem extends Component { const ListItem = (props) => {
state = { const { i18n } = useSelector(state => state.session);
starred: false const [state, setState] = useState({ starred: false });
}
UNSAFE_componentWillMount() { useEffect(() => {
this.setState({ starred: this.props.starred === 1 }); if (props.hasOwnProperty('starred')) {
setState({ ...state, starred: Boolean(props.starred) });
} }
}, [props.starred]);
UNSAFE_componentWillReceiveProps(nextProps) { const printDate = date => {
this.setState({
starred: nextProps.starred === 1
});
}
printDate = date => {
if (date) { if (date) {
let newDate = new Date(date); let newDate = new Date(date);
let day = newDate.getDate(); let day = newDate.getDate();
@ -30,19 +26,18 @@ class ListItem extends Component {
} }
} }
toggleItem = () => { const toggleItem = () => {
this.props.checkItem(); props.checkItem();
} }
starItem = () => { const starItem = () => {
this.setState({ starred: !this.state.starred }, () => { setState({ ...state, starred: !state.starred });
this.props.toggleFav(this.state.starred); props.toggleFav(!state.starred);
});
} }
className = () => { const className = () => {
const { starred } = this.state; const { starred } = state;
const { checked, outdated, suspended, stopped, focused, sysInfo } = this.props; const { checked, outdated, suspended, stopped, focused, sysInfo } = props;
let className = 'list-item'; let className = 'list-item';
if (checked) { if (checked) {
@ -76,25 +71,23 @@ class ListItem extends Component {
return className; return className;
} }
render() {
return ( return (
<div className={this.className()} id={this.props.id}> <div className={className()} id={props.id}>
<Container className="l-col w-14"> <Container className="l-col w-14">
{this.printDate(this.props.date)} {printDate(props.date)}
<div className="text-status"> <div className="text-status">
<div className="checkbox"><input type="checkbox" onChange={(e) => this.toggleItem(e)} checked={this.props.checked} /></div> <div className="checkbox"><input type="checkbox" onChange={toggleItem} checked={props.checked} /></div>
{this.props.leftNameText} {props.leftNameText}
</div> </div>
<div className="star"> <div className="star">
<div className="checkbox"><input type="checkbox" onChange={(e) => this.toggleItem(e)} checked={this.props.checked} /></div> <div className="checkbox"><input type="checkbox" onChange={toggleItem} checked={props.checked} /></div>
<div onClick={this.starItem}><FontAwesomeIcon icon="star" /></div> <div onClick={starItem}><FontAwesomeIcon icon="star" /></div>
</div> </div>
{this.props.suspended && <div className='suspended'>{window.GLOBAL.App.i18n.suspended}</div>} {props.suspended && <div className='suspended'>{i18n.suspended}</div>}
</Container> </Container>
{this.props.children} {props.children}
</div> </div>
); );
} }
}
export default ListItem; export default ListItem;

View file

@ -1,3 +1,11 @@
$whiteBackground: #ececec;
$primary: #2c54ac;
$primaryLight: #2e5bb1;
$secondary: #fcac04;
$secondaryLight: #f8b014;
$secondaryActive: #fdb51c;
$textColor: #555;
.list-item { .list-item {
display: flex; display: flex;
justify-content: flex-start; justify-content: flex-start;
@ -63,12 +71,12 @@
} }
.list-item.starred { .list-item.starred {
border-left: 2px solid #ff6701; border-left: 2px solid $primary;
.l-col div.star { .l-col div.star {
div > svg { div > svg {
opacity: 1; opacity: 1;
color: #ff6701; color: $primary;
} }
} }
} }
@ -112,7 +120,13 @@
} }
.list-item.focused { .list-item.focused {
border-left: 2px solid #5edad0; border-left: 2px solid $secondaryLight;
.l-col div.star {
div > svg {
color: $secondaryLight;
}
}
.actions { .actions {
opacity: 1; opacity: 1;
@ -127,7 +141,7 @@
width: 25px; width: 25px;
height: 25px; height: 25px;
margin-left: 15px; margin-left: 15px;
background: #69a298; background: $secondaryLight;
color: white; color: white;
display: flex; display: flex;
justify-content: center; justify-content: center;

View file

@ -1,9 +1,10 @@
import React from 'react'; import React from 'react';
import { useSelector } from 'react-redux';
import './Modal.scss'; import './Modal.scss';
const { i18n } = window.GLOBAL.App;
const Modal = ({ show, text, onSave, onCancel, showSaveButton = true, showCancelButton = true }) => { const Modal = ({ show, text, onSave, onCancel, showSaveButton = true, showCancelButton = true }) => {
const { i18n } = useSelector(state => state.session);
return ( return (
<div> <div>
<div className={`modal fade ${show ? 'show' : ''}`} id="c-panel-modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true" style={{ display: show ? 'block' : 'none' }}> <div className={`modal fade ${show ? 'show' : ''}`} id="c-panel-modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true" style={{ display: show ? 'block' : 'none' }}>

View file

@ -1,3 +1,5 @@
$primary: #2c54ac;
div.modal { div.modal {
z-index: 2; z-index: 2;
} }
@ -11,8 +13,8 @@ div.content .modal .modal-content {
.modal-footer { .modal-footer {
.btn-primary { .btn-primary {
background: #9FBF0C; background: $primary;
border: 1px solid #9FBF0C; border: 1px solid $primary;
} }
} }
} }

View file

@ -8,13 +8,13 @@ import Toolbar from '../../MainNav/Toolbar/Toolbar';
import Generator from '../Generator/Generator'; import Generator from '../Generator/Generator';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import Spinner from '../../Spinner/Spinner'; import Spinner from '../../Spinner/Spinner';
import { useDispatch } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import './AddCronJob.scss'; import './AddCronJob.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
const AddCronJob = props => { const AddCronJob = props => {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const history = useHistory(); const history = useHistory();
const dispatch = useDispatch(); const dispatch = useDispatch();

View file

@ -4,10 +4,11 @@ import ListItem from '../ControlPanel/ListItem/ListItem';
import Container from '../ControlPanel/Container/Container'; import Container from '../ControlPanel/Container/Container';
import './CronJob.scss'; import './CronJob.scss';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { useSelector } from 'react-redux';
const CronJob = props => { const CronJob = props => {
const { data } = props; const { data } = props;
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const toggleFav = (starred) => { const toggleFav = (starred) => {
@ -24,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/?job=${data.NAME}&token=${token}`); props.handleModal(data.suspend_conf, `/${suspendedStatus}/cron/index.php?job=${data.NAME}`);
} }
const handleDelete = () => { const handleDelete = () => {
props.handleModal(data.delete_conf, `/delete/cron/?job=${data.NAME}&token=${token}`); props.handleModal(data.delete_conf, `/delete/cron/index.php?job=${data.NAME}`);
} }
return ( return (

View file

@ -8,7 +8,7 @@ import Spinner from '../../../components/Spinner/Spinner';
import Toolbar from '../../MainNav/Toolbar/Toolbar'; import Toolbar from '../../MainNav/Toolbar/Toolbar';
import Generator from '../Generator/Generator'; import Generator from '../Generator/Generator';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import { useDispatch } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import QS from 'qs'; import QS from 'qs';
import './EditCronJob.scss'; import './EditCronJob.scss';
@ -16,7 +16,7 @@ import { Helmet } from 'react-helmet';
const EditMail = props => { const EditMail = props => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const history = useHistory(); const history = useHistory();
const dispatch = useDispatch(); const dispatch = useDispatch();
const [state, setState] = useState({ const [state, setState] = useState({

View file

@ -6,10 +6,11 @@ import { Link, useHistory } from 'react-router-dom';
import QS from 'qs'; import QS from 'qs';
import './Generator.scss'; import './Generator.scss';
import { useSelector } from 'react-redux';
const Generator = props => { const Generator = props => {
const formElement = useRef(null); const formElement = useRef(null);
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const history = useHistory(); const history = useHistory();
const [state, setState] = useState({ const [state, setState] = useState({
activeTab: '1' activeTab: '1'

View file

@ -1,3 +1,14 @@
$whiteBackground: #ececec;
$primary: #2c54ac;
$primaryLight: #d7dcef;
$primaryActive: #1e5cb2;
$secondary: #fcac04;
$secondaryLight: #f8b014;
$secondaryActive: #fdb51c;
$hoverButtonText: #2c54ac;
$activeButtonText: #fff;
$textColor: #555;
.cron-job-generator { .cron-job-generator {
border: 1px solid #d9d9d9; border: 1px solid #d9d9d9;
padding: 1rem 1.5rem; padding: 1rem 1.5rem;
@ -17,16 +28,16 @@
text-decoration: none; text-decoration: none;
&:hover { &:hover {
color: #ff6701; color: $secondaryLight;
} }
&:active { &:active {
color: #55C9C0; color: $primaryActive;
} }
} }
a.active { a.active {
color: #ff6701; color: $secondaryActive;
} }
} }
@ -65,7 +76,7 @@
&:focus, &:focus,
&:active { &:active {
outline: none; outline: none;
border-color: #55C9C0; border-color: $primaryActive;
box-shadow: unset; box-shadow: unset;
} }
} }
@ -78,20 +89,20 @@
.form-actions { .form-actions {
button { button {
background: #55C9C0; background: $primary;
color: white; color: white;
border-radius: 3px; border-radius: 3px;
padding: .35rem 1.1rem; padding: .35rem 1.1rem;
font-size: 14px; font-size: 14px;
&:hover { &:hover {
color: #555; color: $hoverButtonText;
background: #5BD8CF; background: $primaryLight;
} }
&:active { &:active {
color: white; color: $activeButtonText;
background: #D1D70D; background: $primaryActive;
} }
} }
} }

View file

@ -1,8 +1,10 @@
import React from 'react'; import React from 'react';
import { dailyMinutesOptions, hoursOptions, dateOptions } from '../../../../ControlPanelService/GeneratorOptions'; import { useSelector } from 'react-redux';
import { generatorOptions } from '../../../../ControlPanelService/GeneratorOptions';
export default function FifthTabSelects() { export default function FifthTabSelects() {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const { dailyMinutesOptions, hoursOptions, dateOptions } = generatorOptions(i18n);
const renderDate = () => { const renderDate = () => {
return dateOptions.map((option, index) => <option key={index} value={option.value}>{option.name}</option>); return dateOptions.map((option, index) => <option key={index} value={option.value}>{option.name}</option>);

View file

@ -1,8 +1,10 @@
import React from 'react'; import React from 'react';
import { dailyMinutesOptions, hoursOptions } from '../../../../ControlPanelService/GeneratorOptions'; import { useSelector } from 'react-redux';
import { generatorOptions } from '../../../../ControlPanelService/GeneratorOptions';
export default function FourthTabSelects() { export default function FourthTabSelects() {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const { dailyMinutesOptions, hoursOptions } = generatorOptions(i18n);
const renderHours = () => { const renderHours = () => {
return hoursOptions.map((option, index) => <option key={index} value={option.value}>{option.name}</option>); return hoursOptions.map((option, index) => <option key={index} value={option.value}>{option.name}</option>);

View file

@ -1,8 +1,10 @@
import React from 'react'; import React from 'react';
import { hourlyMinutesOptions } from '../../../../ControlPanelService/GeneratorOptions'; import { useSelector } from 'react-redux';
import { generatorOptions } from '../../../../ControlPanelService/GeneratorOptions';
export default function SecondTabSelects() { export default function SecondTabSelects() {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const { hourlyMinutesOptions } = generatorOptions(i18n);
const renderOptions = () => { const renderOptions = () => {
return hourlyMinutesOptions.map((option, index) => <option key={index} value={option.value}>{option.name}</option>); return hourlyMinutesOptions.map((option, index) => <option key={index} value={option.value}>{option.name}</option>);

View file

@ -1,8 +1,10 @@
import React from 'react'; import React from 'react';
import { dailyMinutesOptions, hoursOptions } from '../../../../ControlPanelService/GeneratorOptions'; import { useSelector } from 'react-redux';
import { generatorOptions } from '../../../../ControlPanelService/GeneratorOptions';
export default function ThirdTabSelects() { export default function ThirdTabSelects() {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const { dailyMinutesOptions, hoursOptions } = generatorOptions(i18n);
const renderHours = () => { const renderHours = () => {
return hoursOptions.map((option, index) => <option key={index} value={option.value}>{option.name}</option>); return hoursOptions.map((option, index) => <option key={index} value={option.value}>{option.name}</option>);

View file

@ -1,8 +1,9 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { daysRunCommandsOptions, hoursRunCommandsOptions, minutesRunCommandsOptions, monthlyRunCommandOptions, weeklyRunCommandOptions } from '../../../../ControlPanelService/GeneratorOptions'; import { useSelector } from 'react-redux';
import { generatorOptions } from '../../../../ControlPanelService/GeneratorOptions';
const RunCommandSelect = props => { const RunCommandSelect = props => {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const [state, setState] = useState({ const [state, setState] = useState({
activeTab: '' activeTab: ''
@ -13,6 +14,8 @@ const RunCommandSelect = props => {
}, [props]); }, [props]);
const renderOptions = () => { const renderOptions = () => {
const { daysRunCommandsOptions, hoursRunCommandsOptions, minutesRunCommandsOptions, monthlyRunCommandOptions, weeklyRunCommandOptions } = generatorOptions(i18n);
switch (state.activeTab) { switch (state.activeTab) {
case '1': return minutesRunCommandsOptions.map(option => <option value={option.value}>{option.name}</option>); case '1': return minutesRunCommandsOptions.map(option => <option value={option.value}>{option.name}</option>);
case '2': return hoursRunCommandsOptions.map(option => <option value={option.value}>{option.name}</option>); case '2': return hoursRunCommandsOptions.map(option => <option value={option.value}>{option.name}</option>);

View file

@ -10,13 +10,13 @@ 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';
import Spinner from '../../Spinner/Spinner'; import Spinner from '../../Spinner/Spinner';
import { useDispatch } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import './AddDNSRecord.scss' import './AddDNSRecord.scss'
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
export default function AddDNSRecord(props) { export default function AddDNSRecord(props) {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const dispatch = useDispatch(); const dispatch = useDispatch();
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const history = useHistory(); const history = useHistory();

View file

@ -3,9 +3,10 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Container from '../ControlPanel/Container/Container'; import Container from '../ControlPanel/Container/Container';
import ListItem from '../ControlPanel/ListItem/ListItem'; import ListItem from '../ControlPanel/ListItem/ListItem';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { useSelector } from 'react-redux';
export default function DnsRecord({ data, domain, handleModal, ...props }) { export default function DnsRecord({ data, domain, handleModal, ...props }) {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const toggleFav = (starred) => { const toggleFav = (starred) => {
@ -21,7 +22,7 @@ export default function DnsRecord({ data, domain, handleModal, ...props }) {
} }
const handleDelete = () => { const handleDelete = () => {
handleModal(data.delete_conf, `/delete/dns/?domain=${domain}&record_id=${data.ID}&token=${token}`); handleModal(data.delete_conf, `/api/v1/delete/dns/?domain=${domain}&record_id=${data.ID}`);
} }
return ( return (

View file

@ -8,13 +8,13 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Spinner from '../../../components/Spinner/Spinner'; import Spinner from '../../../components/Spinner/Spinner';
import Toolbar from '../../MainNav/Toolbar/Toolbar'; import Toolbar from '../../MainNav/Toolbar/Toolbar';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import { useDispatch } 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';
export default function EditDNSRecord(props) { export default function EditDNSRecord(props) {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const dispatch = useDispatch(); const dispatch = useDispatch();
const history = useHistory(); const history = useHistory();
const [state, setState] = useState({ const [state, setState] = useState({
@ -72,13 +72,13 @@ export default function EditDNSRecord(props) {
} }
updatedRecord['v_domain'] = state.data.domain; updatedRecord['v_domain'] = state.data.domain;
updatedRecord['v_rec'] = state.data.record; updatedRecord['v_record_id'] = props.record_id;
updatedRecord['v_type'] = state.data.type; updatedRecord['v_type'] = state.data.type;
if (Object.keys(updatedRecord).length !== 0 && updatedRecord.constructor === Object) { if (Object.keys(updatedRecord).length !== 0 && updatedRecord.constructor === Object) {
setState({ ...state, loading: true }); setState({ ...state, loading: true });
updateDNS(updatedRecord, state.data.domain) 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, ok_msg } = result.data;
@ -131,7 +131,7 @@ export default function EditDNSRecord(props) {
<TextInput <TextInput
value={state.data.rec} value={state.data.rec}
title={i18n['Record']} title={i18n['Record']}
name="v_rec" name="v_record_id"
id="domain" id="domain"
disabled /> disabled />

View file

@ -8,13 +8,13 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Toolbar from '../../MainNav/Toolbar/Toolbar'; 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 } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import './AddDatabase.scss' import './AddDatabase.scss'
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
const AddDatabase = props => { const AddDatabase = props => {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const dispatch = useDispatch(); const dispatch = useDispatch();
const history = useHistory(); const history = useHistory();

View file

@ -3,10 +3,11 @@ import ListItem from '../ControlPanel/ListItem/ListItem';
import Container from '../ControlPanel/Container/Container'; import Container from '../ControlPanel/Container/Container';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { useSelector } from 'react-redux';
const Database = props => { const Database = props => {
const { data } = props; const { data } = props;
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const toggleFav = (starred) => { const toggleFav = (starred) => {
@ -23,11 +24,11 @@ const Database = 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}/db/?database=${data.NAME}&token=${token}`); props.handleModal(data.suspend_conf, `/api/v1/${suspendedStatus}/db/index.php?database=${data.NAME}`);
} }
const handleDelete = () => { const handleDelete = () => {
props.handleModal(data.delete_conf, `/delete/db/?database=${data.NAME}&token=${token}`); props.handleModal(data.delete_conf, `/api/v1/delete/db/index.php?database=${data.NAME}`);
} }
return ( return (

View file

@ -9,7 +9,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Spinner from '../../../components/Spinner/Spinner'; import Spinner from '../../../components/Spinner/Spinner';
import Toolbar from '../../MainNav/Toolbar/Toolbar'; import Toolbar from '../../MainNav/Toolbar/Toolbar';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import { useDispatch } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import QS from 'qs'; import QS from 'qs';
import './EditDatabase.scss'; import './EditDatabase.scss';
@ -17,7 +17,7 @@ import { Helmet } from 'react-helmet';
const EditDatabase = props => { const EditDatabase = props => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const history = useHistory(); const history = useHistory();
const dispatch = useDispatch(); const dispatch = useDispatch();
const [state, setState] = useState({ const [state, setState] = useState({

View file

@ -7,7 +7,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Toolbar from '../../MainNav/Toolbar/Toolbar'; 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 } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import './AddDomainNameSystem.scss'; import './AddDomainNameSystem.scss';
import AdvancedOptions from './AdvancedOptions/AdvancedOptions'; import AdvancedOptions from './AdvancedOptions/AdvancedOptions';
@ -15,7 +15,7 @@ import { addDomainNameSystem } from '../../../ControlPanelService/Dns';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
const AddDomainNameSystem = props => { const AddDomainNameSystem = props => {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const dispatch = useDispatch(); const dispatch = useDispatch();
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const history = useHistory(); const history = useHistory();

View file

@ -2,9 +2,10 @@ import React, { useEffect, useState } from 'react';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import './AdvancedOptions.scss'; import './AdvancedOptions.scss';
import { useSelector } from 'react-redux';
const AdvancedOptions = props => { const AdvancedOptions = props => {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const [state, setState] = useState({ const [state, setState] = useState({
nameServersAmount: [], nameServersAmount: [],
userNS: props.userNS userNS: props.userNS

View file

@ -4,10 +4,11 @@ import Container from '../ControlPanel/Container/Container';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import './DomainNameSystem.scss'; import './DomainNameSystem.scss';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { useSelector } from 'react-redux';
const DomainNameSystem = props => { const DomainNameSystem = props => {
const { data } = props; const { data } = props;
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const toggleFav = (starred) => { const toggleFav = (starred) => {
@ -24,11 +25,11 @@ const DomainNameSystem = 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}/dns?domain=${data.NAME}&token=${token}`); props.handleModal(data.suspend_conf, `/api/v1/${suspendedStatus}/dns/index.php?domain=${data.NAME}`);
} }
const handleDelete = () => { const handleDelete = () => {
props.handleModal(data.delete_conf, `/delete/dns?domain=${data.NAME}&token=${token}`); props.handleModal(data.delete_conf, `/api/v1/delete/dns/index.php?domain=${data.NAME}`);
} }
return ( return (

View file

@ -8,7 +8,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Spinner from '../../../components/Spinner/Spinner'; import Spinner from '../../../components/Spinner/Spinner';
import Toolbar from '../../MainNav/Toolbar/Toolbar'; import Toolbar from '../../MainNav/Toolbar/Toolbar';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import { useDispatch } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import QS from 'qs'; import QS from 'qs';
import './EditDomainNameSystem.scss'; import './EditDomainNameSystem.scss';
@ -16,7 +16,7 @@ import { Helmet } from 'react-helmet';
const EditDomainNameSystem = props => { const EditDomainNameSystem = props => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const history = useHistory(); const history = useHistory();
const dispatch = useDispatch(); const dispatch = useDispatch();
const [state, setState] = useState({ const [state, setState] = useState({

View file

@ -8,14 +8,14 @@ import { addFirewall } from '../../../ControlPanelService/Firewalls';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Toolbar from '../../MainNav/Toolbar/Toolbar'; import Toolbar from '../../MainNav/Toolbar/Toolbar';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import { useDispatch } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import './AddFirewall.scss'; import './AddFirewall.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
const AddFirewall = props => { const AddFirewall = props => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const dispatch = useDispatch(); const dispatch = useDispatch();
const history = useHistory(); const history = useHistory();
const [state, setState] = useState({ const [state, setState] = useState({

View file

@ -6,11 +6,11 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Spinner from 'src/components/Spinner/Spinner'; import Spinner from 'src/components/Spinner/Spinner';
import Toolbar from '../../../MainNav/Toolbar/Toolbar'; import Toolbar from '../../../MainNav/Toolbar/Toolbar';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import { useDispatch } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
const AddBanIP = () => { const AddBanIP = () => {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const userLanguage = localStorage.getItem("language"); const userLanguage = localStorage.getItem("language");
const history = useHistory(); const history = useHistory();
const dispatch = useDispatch(); const dispatch = useDispatch();

View file

@ -2,9 +2,10 @@ import React from 'react';
import ListItem from 'src/components/ControlPanel/ListItem/ListItem'; import ListItem from 'src/components/ControlPanel/ListItem/ListItem';
import Container from 'src/components/ControlPanel/Container/Container'; import Container from 'src/components/ControlPanel/Container/Container';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { useSelector } from 'react-redux';
const Ban = ({ data, ...props }) => { const Ban = ({ data, ...props }) => {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const checkItem = () => { const checkItem = () => {
@ -12,7 +13,7 @@ const Ban = ({ data, ...props }) => {
} }
const handleDelete = () => { const handleDelete = () => {
props.handleModal(data.delete_conf, `/api/delete/firewall/banlist/?ip=${data.NAME}&chain=${data.CHAIN}&token=${token}`); props.handleModal(data.delete_conf, `/api/v1/delete/firewall/banlist/?ip=${data.NAME}&chain=${data.CHAIN}`);
} }
return ( return (

View file

@ -8,7 +8,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Spinner from '../../../components/Spinner/Spinner'; import Spinner from '../../../components/Spinner/Spinner';
import Toolbar from '../../MainNav/Toolbar/Toolbar'; import Toolbar from '../../MainNav/Toolbar/Toolbar';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import { useDispatch } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import QS from 'qs'; import QS from 'qs';
import './EditFirewall.scss'; import './EditFirewall.scss';
@ -16,7 +16,7 @@ import { Helmet } from 'react-helmet';
const EditFirewall = props => { const EditFirewall = props => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const history = useHistory(); const history = useHistory();
const dispatch = useDispatch(); const dispatch = useDispatch();
const [state, setState] = useState({ const [state, setState] = useState({

View file

@ -4,10 +4,11 @@ import Container from '../ControlPanel/Container/Container';
import ListItem from '../ControlPanel/ListItem/ListItem'; import ListItem from '../ControlPanel/ListItem/ListItem';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import './Firewall.scss'; import './Firewall.scss';
import { useSelector } from 'react-redux';
const Firewall = ({ data, ...props }) => { const Firewall = ({ data, ...props }) => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const toggleFav = (starred) => { const toggleFav = (starred) => {
if (starred) { if (starred) {
@ -23,11 +24,11 @@ const Firewall = ({ data, ...props }) => {
const handleSuspend = () => { const handleSuspend = () => {
let suspendedStatus = data.SUSPENDED === 'yes' ? 'unsuspend' : 'suspend'; let suspendedStatus = data.SUSPENDED === 'yes' ? 'unsuspend' : 'suspend';
props.handleModal(data.suspend_conf, `/${suspendedStatus}/firewall/?rule=${data.NAME}&token=${token}`); props.handleModal(data.suspend_conf, `/api/v1/${suspendedStatus}/firewall/index.php?rule=${data.NAME}`);
} }
const handleDelete = () => { const handleDelete = () => {
props.handleModal(data.delete_conf, `/delete/firewall/?rule=${data.NAME}&token=${token}`); props.handleModal(data.delete_conf, `/api/v1/delete/firewall/index.php?rule=${data.NAME}`);
} }
return ( return (

View file

@ -13,7 +13,7 @@ import { Helmet } from 'react-helmet';
import QueryString from 'qs'; import QueryString from 'qs';
export default function ForgotPassword() { export default function ForgotPassword() {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const dispatch = useDispatch(); const dispatch = useDispatch();
const history = useHistory(); const history = useHistory();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
@ -43,7 +43,7 @@ export default function ForgotPassword() {
return; return;
} }
if (session.token) { if (session.token && session.userName) {
history.push('/list/user/'); history.push('/list/user/');
} }
}, [session]); }, [session]);
@ -120,7 +120,7 @@ export default function ForgotPassword() {
<form onSubmit={submitHandler}> <form onSubmit={submitHandler}>
<div className="c1"> <div className="c1">
<Link to="/"> <Link to="/">
<img src="https://r5.vestacp.com:8083/images/vesta_logo.png" alt="Logo" /> <img src="/images/logo.png" alt="Logo" />
</Link> </Link>
</div> </div>
<div className="c2"> <div className="c2">

View file

@ -1,52 +1,127 @@
import React from 'react'; import React, { useEffect } from 'react';
import './Hotkeys.scss' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { useSelector } from 'react-redux';
import './Hotkeys.scss';
function style(style) { const Hotkeys = props => {
if (style === "inactive") { const { i18n } = useSelector(state => state.session);
return "none";
} else { useEffect(() => {
return "block"; window.addEventListener("keyup", toggleShortcutsLit);
return () => window.removeEventListener("keyup", toggleShortcutsLit);
}, [props.reference]);
const toggleShortcutsLit = event => {
let isSearchInputFocused = document.querySelector('input:focus') || document.querySelector('textarea:focus');
if (event.keyCode === 72 && !isSearchInputFocused) {
props.toggleHotkeys();
} }
} }
const Hotkeys = (props) => {
const { i18n } = window.GLOBAL.App;
return ( return (
<div className="panel panel-default" style={{ display: style(props.style) }}> <div className="hotkeys-list hide" ref={props.reference}>
<div className="panel-heading"> <div className="head">
<h2>Shortcuts</h2> <div className="name">{i18n.Shortcuts}</div>
<button type="button" className="close" onClick={props.close} > <div className="close" onClick={() => props.toggleHotkeys()}><FontAwesomeIcon icon="times" /></div>
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<div className="panel-body"> <div className="body">
<ul> <ul>
<li><span className="shortcut">u</span> {i18n.Upload}</li> <li>
<li><span className="shortcut">n</span> {i18n['New File']}</li> <span className="name">u</span>
<li><span className="shortcut">F7</span> {i18n['New Folder']}</li> <span className="description">{i18n['Upload']}</span>
<li><span className="shortcut">d</span> {i18n.Download}</li> </li>
<li><span className="shortcut">F2 / Shift + F6</span> {i18n.Rename}</li> <li>
<li><span className="shortcut">m</span> {i18n.Move}</li> <span className="name">n</span>
<li><span className="shortcut">F5</span> {i18n.Copy}</li> <span className="description">{i18n['New Fille']}</span>
<li><span className="shortcut">F8 / Del</span> {i18n.Delete}</li> </li>
<li><span className="shortcut">F2</span> {i18n['Save File (in text editor)']}</li> <li>
<li><span className="shortcut">h</span> {i18n[['Display/Close shortcuts']]}</li> <span className="name">F7</span>
<li><span className="shortcut">Esc</span> {i18n['Close Popup / Cancel']}</li> <span className="description">{i18n['New Folder']}</span>
<li><span className="shortcut">F10</span> Close Preview / Editor</li> </li>
<li>
<span className="name">d</span>
<span className="description">{i18n['Download']}</span>
</li>
<li className="space-top">
<span className="name">F2 / Shift + F6</span>
<span className="description">{i18n['Rename']}</span>
</li>
<li>
<span className="name">m</span>
<span className="description">{i18n['Move']}</span>
</li>
<li>
<span className="name">F5</span>
<span className="description">{i18n['Copy']}</span>
</li>
<li>
<span className="name">F5</span>
<span className="description">{i18n['Copy']}</span>
</li>
<li>
<span className="name">F8 / Del</span>
<span className="description">{i18n['Delete']}</span>
</li>
<li>
<span className="name">F2</span>
<span className="description">{i18n['Save File (in text editor)']}</span>
</li>
<li>
<span className="name">h</span>
<span className="description">{i18n['Display/Close shortcuts']}</span>
</li>
<li>
<span className="name">Esc</span>
<span className="description">{i18n['Close Popup / Cancel']}</span>
</li>
<li>
<span className="name">F10</span>
<span className="description">{i18n['Close Preview / Editor']}</span>
</li>
</ul> </ul>
<ul> <ul>
<li><span className="shortcut">&#8593;</span> {i18n['Move Cursor Up']}</li> <li>
<li><span className="shortcut">&#8595;</span> {i18n['Move Cursor Down']}</li> <span className="name">&#8593;</span>
<li><span className="shortcut">&#8592;</span> {i18n['Switch to Left Tab']}</li> <span className="description">{i18n['Move Cursor Up']}</span>
<li><span className="shortcut">&#8594;</span> {i18n['Switch to Right Tab']}</li> </li>
<li><span className="shortcut">a</span> {i18n.Archive}</li> <li>
<li><span className="shortcut">Tab</span> {i18n['Switch Tab']}</li> <span className="name">&#8595;</span>
<li><span className="shortcut">Enter</span> {i18n['Open File / Enter Directory']}</li> <span className="description">{i18n['Move Cursor Down']}</span>
<li><span className="shortcut">F4</span>{i18n['Edit File']}</li> </li>
<li><span className="shortcut">Backspace</span> {i18n['Go to Parent Directory']}</li> <li>
<li><span className="shortcut">Ctr + Click</span> {i18n['Add File to the Current Selection']}</li> <span className="name">&#8592;</span>
<li><span className="shortcut">Shift + Cursor up/down</span> {i18n['Select Bunch of Files']}</li> <span className="description">{i18n['Switch to Left Tab']}</span>
</li>
<li>
<span className="name">&#8594;</span>
<span className="description">{i18n['Switch to Right Tab']}</span>
</li>
<li>
<span className="name">a</span>
<span className="description">{i18n['Archive']}</span>
</li>
<li>
<span className="name">Enter</span>
<span className="description">{i18n['Open File / Enter Directory']}</span>
</li>
<li>
<span className="name">F4</span>
<span className="description">{i18n['Edit File']}</span>
</li>
<li>
<span className="name">Backspace</span>
<span className="description">{i18n['Go to Parent Directory']}</span>
</li>
<li>
<span className="name">Ctr + Click</span>
<span className="description">{i18n['Add File to the Current Selection']}</span>
</li>
<li>
<span className="name">Shift + Cursor up/down</span>
<span className="description">{i18n['Select Bunch of Files']}</span>
</li>
</ul> </ul>
</div> </div>
</div> </div>

View file

@ -1,72 +1,78 @@
.panel { $secondary: #fcac04;
margin: 0;
position: absolute; .hotkeys-list {
right: 30%; position: fixed;
bottom: 0; bottom: 0;
width: 40%; right: 0;
font-size: 15px; display: flex;
background: #38383891; flex-direction: column;
transform: translateX(-45%);
width: 53%;
background: #222e44de;
font-size: 13px;
.panel-heading { .head {
background: #474646b0;
text-align: center;
color: #ffcc00;
padding: 10px;
.close {
position: absolute;
color: white;
right: 10px;
top: 10px;
opacity: 1;
&:hover,&:focus{
color: #333;
outline: none;
text-decoration: none;
cursor: pointer;
}
}
}
.panel-body {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
background: rgba(56,56,56,0.4); align-items: center;
border-bottom: 1px solid $secondary;
ul { .name {
width: 50%; text-transform: uppercase;
color: white; padding: 5px 0 5px 10px;
font-size: 12px;
li { font-weight: bold;
list-style-type: none; color: $secondary;
margin-bottom: 10px; letter-spacing: 2px;
padding: 15px;
.shortcut {
color: #48F4EF;
}
}
}
}
} }
.hotkeys-button { .close {
color: white; padding: 12px;
background: rgb(170, 166, 166); opacity: 1 !important;
position: absolute;
right: 5px;
bottom: 5px;
width: 40px;
height: 38px;
text-align: center;
border-radius: 30px;
cursor: pointer;
svg { svg {
margin-top: 7px; color: $secondary;
} }
&:hover { &:hover {
background: #aacc0d; cursor: pointer;
background: #222e44;
} }
} }
}
.body {
display: flex;
ul {
padding: 25px 10px;
margin: 0;
width: 50%;
list-style: none;
margin-left: 3rem;
li {
padding: 5px;
span.name {
margin-right: 15px;
color: $secondary;
font-weight: bold;
}
span.description {
color: white;
}
}
li.space-top {
padding-top: 30px;
}
}
}
}
.hide {
display: none;
}

View file

@ -17,7 +17,7 @@ import { Helmet } from 'react-helmet';
const AddInternetProtocol = props => { const AddInternetProtocol = props => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const session = useSelector(state => state.session); const session = useSelector(state => state.session);
const dispatch = useDispatch(); const dispatch = useDispatch();
const history = useHistory(); const history = useHistory();

View file

@ -10,7 +10,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Spinner from '../../../components/Spinner/Spinner'; import Spinner from '../../../components/Spinner/Spinner';
import Toolbar from '../../MainNav/Toolbar/Toolbar'; import Toolbar from '../../MainNav/Toolbar/Toolbar';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import { useDispatch } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import QS from 'qs'; import QS from 'qs';
import './EditInternetProtocol.scss'; import './EditInternetProtocol.scss';
@ -18,7 +18,7 @@ import { Helmet } from 'react-helmet';
const EditInternetProtocol = () => { const EditInternetProtocol = () => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const history = useHistory(); const history = useHistory();
const dispatch = useDispatch(); const dispatch = useDispatch();
const [state, setState] = useState({ const [state, setState] = useState({

View file

@ -4,10 +4,11 @@ import Container from '../ControlPanel/Container/Container';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import './InternetProtocol.scss'; import './InternetProtocol.scss';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { useSelector } from 'react-redux';
const InternetProtocol = props => { const InternetProtocol = props => {
const { data } = props; const { data } = props;
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const toggleFav = (starred) => { const toggleFav = (starred) => {
@ -23,7 +24,7 @@ const InternetProtocol = props => {
} }
const handleDelete = () => { const handleDelete = () => {
props.handleModal(data.delete_conf, `/delete/ip/?ip=${data.NAME}&token=${token}`); props.handleModal(data.delete_conf, `/api/v1/delete/ip/?ip=${data.NAME}`);
} }
return ( return (

View file

@ -70,7 +70,7 @@ class DirectoryList extends Component {
} }
isHomeDirectory = () => { isHomeDirectory = () => {
return this.props.path === window.GLOBAL.ROOT_DIR; return this.props.path === this.props.rootDir;
} }
toggleActiveList = () => { toggleActiveList = () => {

View file

@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faJs, faCss3, faPhp, faHtml5, faSass } from '@fortawesome/free-brands-svg-icons'; import { faJs, faCss3, faPhp, faHtml5, faSass } from '@fortawesome/free-brands-svg-icons';
import './Row.scss'; import './Row.scss';
import { connect } from 'react-redux';
class Row extends Component { class Row extends Component {
static propTypes = { static propTypes = {
@ -121,9 +122,8 @@ class Row extends Component {
let date = new Date(fDate), let date = new Date(fDate),
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
appMonths = window.GLOBAL.App.i18n,
getDay = date.getDate(), getDay = date.getDate(),
getMonth = appMonths[months[date.getMonth()]]; getMonth = this.props.session.i18n[months[date.getMonth()]];
return (<span className="date">{getMonth} {getDay}</span>); return (<span className="date">{getMonth} {getDay}</span>);
} }
@ -188,4 +188,10 @@ class Row extends Component {
} }
} }
export default withRouter(Row); function mapStateToProps(state) {
return {
session: state.session
}
}
export default connect(mapStateToProps)(withRouter(Row));

View file

@ -1,3 +1,14 @@
$whiteBackground: #ececec;
$primary: #2c54ac;
$primaryLight: #d7dcef;
$primaryActive: #1e5cb2;
$secondary: #fcac04;
$secondaryLight: #f8b014;
$secondaryActive: #fdb51c;
$hoverButtonText: #2c54ac;
$activeButtonText: #fff;
$textColor: #555;
.list .list-container ul li svg { .list .list-container ul li svg {
width: 25px; width: 25px;
vertical-align: top; vertical-align: top;
@ -126,7 +137,7 @@
} }
.list .list-container ul li .fOwner { .list .list-container ul li .fOwner {
color: #81A64F; color: #896417;
font-style: italic; font-style: italic;
width: 50px; width: 50px;
font-size: 12px; font-size: 12px;
@ -134,7 +145,7 @@
} }
.value { .value {
color: #44a8b3; color: $primary;
} }
.unit { .unit {

View file

@ -1,3 +1,14 @@
$whiteBackground: #ececec;
$primary: #2c54ac;
$primaryLight: #d7dcef;
$primaryActive: #1e5cb2;
$secondary: #fcac04;
$secondaryLight: #f8b014;
$secondaryActive: #fdb51c;
$hoverButtonText: #2c54ac;
$activeButtonText: #fff;
$textColor: #555;
.login-page { .login-page {
display: flex; display: flex;
justify-content: center; justify-content: center;
@ -45,11 +56,15 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
width: 30%; width: 35%;
img {
width: 110%;
}
} }
.c2 { .c2 {
width: 70%; width: 65%;
margin-left: 3.5rem; margin-left: 3.5rem;
.forgot-password { .forgot-password {
@ -60,8 +75,8 @@
} }
button[type="submit"] { button[type="submit"] {
background-color: #9FBF0C; background-color: $primary;
border: 1px solid #9FBF0C; border: 1px solid $primary;
padding: 1px 16px 3px; padding: 1px 16px 3px;
font-size: 13px;; font-size: 13px;;
width: 100px; width: 100px;
@ -70,9 +85,15 @@
border-radius: 3px; border-radius: 3px;
&:hover { &:hover {
border: 1px solid #C0E60F; color: $primary;
background-color: #C0E60F; border: 1px solid $primaryLight;
color: #555; background-color: $primaryLight;
}
&:active {
color: #fafafa;
border: 1px solid $primary;
background-color: $primary;
} }
.disabled { .disabled {

View file

@ -11,7 +11,7 @@ import './Login.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
export default function LoginForm() { export default function LoginForm() {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const dispatch = useDispatch(); const dispatch = useDispatch();
const history = useHistory(); const history = useHistory();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
@ -28,7 +28,7 @@ export default function LoginForm() {
return; return;
} }
if (session.token) { if (session.token && session.userName) {
history.push('/list/user/'); history.push('/list/user/');
} }
}, [session]); }, [session]);
@ -57,7 +57,7 @@ export default function LoginForm() {
return ( return (
<div className="login-page"> <div className="login-page">
<Helmet> <Helmet>
<title>{`Vesta - ${i18n.LOGIN}`}</title> <title>{`Vesta - ${i18n.LOGIN ?? 'LOGIN'}`}</title>
</Helmet> </Helmet>
{loading && <Spinner />} {loading && <Spinner />}
<div className="login-form-wrapper"> <div className="login-form-wrapper">
@ -65,24 +65,24 @@ export default function LoginForm() {
<form onSubmit={submitHandler}> <form onSubmit={submitHandler}>
<div className="c1"> <div className="c1">
<Link to="/"> <Link to="/">
<img src="https://r5.vestacp.com:8083/images/vesta_logo.png" alt="Logo" /> <img src="/images/logo.png" alt="Logo" />
</Link> </Link>
</div> </div>
<div className="c2"> <div className="c2">
<TextInput <TextInput
onChange={changeInputHandler} onChange={changeInputHandler}
title={i18n['Username']} title={i18n['Username'] ?? 'Username'}
value={formValues.user} value={formValues.user}
name="user" name="user"
id="user" /> id="user" />
<TextInput <TextInput
onChange={changeInputHandler} onChange={changeInputHandler}
title={i18n['Password']} title={i18n['Password'] ?? 'Password'}
value={formValues.password} value={formValues.password}
optionalTitle={( optionalTitle={(
<Link className="forgot-password" tabIndex="-1" to="/reset"> <Link className="forgot-password" tabIndex="-1" to="/reset">
{i18n['forgot password']} {i18n['forgot password'] ?? 'forgot password'}
</Link> </Link>
)} )}
name="password" name="password"
@ -90,7 +90,7 @@ export default function LoginForm() {
id="password" /> id="password" />
<button type="submit" disabled={loading} className={loading ? 'disabled' : ''}> <button type="submit" disabled={loading} className={loading ? 'disabled' : ''}>
{i18n['Log in']} {i18n['Log in'] ?? 'Log in'}
</button> </button>
<div className="error-message">{errorMessage}</div> <div className="error-message">{errorMessage}</div>

View file

@ -7,13 +7,13 @@ import { addMail } from '../../../ControlPanelService/Mail';
import Toolbar from '../../MainNav/Toolbar/Toolbar'; 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 } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import './AddMail.scss' import './AddMail.scss'
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
const AddMail = props => { const AddMail = props => {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const dispatch = useDispatch(); const dispatch = useDispatch();
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const history = useHistory(); const history = useHistory();

View file

@ -8,7 +8,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Spinner from '../../../components/Spinner/Spinner'; import Spinner from '../../../components/Spinner/Spinner';
import Toolbar from '../../MainNav/Toolbar/Toolbar'; import Toolbar from '../../MainNav/Toolbar/Toolbar';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import { useDispatch } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import QS from 'qs'; import QS from 'qs';
import './EditMail.scss'; import './EditMail.scss';
@ -16,7 +16,7 @@ import { Helmet } from 'react-helmet';
const EditMail = props => { const EditMail = props => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const history = useHistory(); const history = useHistory();
const dispatch = useDispatch(); const dispatch = useDispatch();
const [state, setState] = useState({ const [state, setState] = useState({

View file

@ -4,10 +4,11 @@ import Container from '../ControlPanel/Container/Container';
import ListItem from '../ControlPanel/ListItem/ListItem'; import ListItem from '../ControlPanel/ListItem/ListItem';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import './Mail.scss'; import './Mail.scss';
import { useSelector } from 'react-redux';
const Mail = props => { const Mail = props => {
const { data } = props; const { data } = props;
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const printStat = (stat, text) => { const printStat = (stat, text) => {
if (text === 'no') { if (text === 'no') {
@ -31,11 +32,11 @@ const Mail = 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}/mail?domain=${data.NAME}&token=${token}`); props.handleModal(data.suspend_conf, `/api/v1/${suspendedStatus}/mail/index.php?domain=${data.NAME}`);
} }
const handleDelete = () => { const handleDelete = () => {
props.handleModal(data.delete_conf, `/delete/mail?domain=${data.NAME}&token=${token}`); props.handleModal(data.delete_conf, `/api/v1/delete/mail/index.php?domain=${data.NAME}`);
} }
return ( return (

View file

@ -13,13 +13,13 @@ import MailInfoBlock from '../MailInfoBlock/MailInfoBlock';
import Toolbar from '../../MainNav/Toolbar/Toolbar'; 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 } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import './AddMailAccount.scss'; import './AddMailAccount.scss';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
export default function AddMailAccount(props) { export default function AddMailAccount(props) {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const dispatch = useDispatch(); const dispatch = useDispatch();
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const history = useHistory(); const history = useHistory();

View file

@ -6,20 +6,20 @@ import TextInput from 'src/components/ControlPanel/AddItemLayout/Form/TextInput/
import Password from 'src/components/ControlPanel/AddItemLayout/Form/Password/Password'; import Password from 'src/components/ControlPanel/AddItemLayout/Form/Password/Password';
import TextArea from 'src/components/ControlPanel/AddItemLayout/Form/TextArea/TextArea'; import TextArea from 'src/components/ControlPanel/AddItemLayout/Form/TextArea/TextArea';
import Checkbox from 'src/components/ControlPanel/AddItemLayout/Form/Checkbox/Checkbox'; import Checkbox from 'src/components/ControlPanel/AddItemLayout/Form/Checkbox/Checkbox';
import { addMailAccount, editMailAccount, getMailAccountInfo } from '../../../ControlPanelService/Mail'; import { editMailAccount, getMailAccountInfo } from '../../../ControlPanelService/Mail';
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 MailInfoBlock from '../MailInfoBlock/MailInfoBlock'; import MailInfoBlock from '../MailInfoBlock/MailInfoBlock';
import Toolbar from '../../MainNav/Toolbar/Toolbar'; 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 } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
export default function EditMailAccount(props) { export default function EditMailAccount(props) {
const [autoreplyChecked, setAutoreplyChecked] = useState(false); const [autoreplyChecked, setAutoreplyChecked] = useState(false);
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const dispatch = useDispatch(); const dispatch = useDispatch();
const history = useHistory(); const history = useHistory();
const [state, setState] = useState({ const [state, setState] = useState({

View file

@ -3,10 +3,11 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Container from '../ControlPanel/Container/Container'; import Container from '../ControlPanel/Container/Container';
import ListItem from '../ControlPanel/ListItem/ListItem'; import ListItem from '../ControlPanel/ListItem/ListItem';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { useSelector } from 'react-redux';
export default function MailAccount(props) { export default function MailAccount(props) {
const { data, domain } = props; const { data, domain } = props;
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const printStat = (stat, text) => { const printStat = (stat, text) => {
if (text === 'no') { if (text === 'no') {
@ -30,11 +31,11 @@ export default function MailAccount(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}/mail?domain=${domain}&account=${data.NAME}&token=${token}`); props.handleModal(data.suspend_conf, `/api/v1/${suspendedStatus}/mail/index.php?domain=${domain}&account=${data.NAME}`);
} }
const handleDelete = () => { const handleDelete = () => {
props.handleModal(data.delete_conf, `/delete/mail?domain=${domain}&account=${data.NAME}&token=${token}`); props.handleModal(data.delete_conf, `/api/v1/delete/mail/index.php?domain=${domain}&account=${data.NAME}`);
} }
return ( return (

View file

@ -5,7 +5,7 @@ import { mailInfoBlockSelectOptions } from 'src/ControlPanelService/Mail';
import './MailInfoBlock.scss'; import './MailInfoBlock.scss';
export default function MailInfoBlock({ webMail, hostName, domain, password }) { export default function MailInfoBlock({ webMail, hostName, domain, password }) {
const { i18n } = window.GLOBAL.App; const { i18n } = useSelector(state => state.session);
const [selectedOption, setSelectedOption] = useState(''); const [selectedOption, setSelectedOption] = useState('');
const { userName } = useSelector(state => state.session); const { userName } = useSelector(state => state.session);
const [state, setState] = useState({ const [state, setState] = useState({
@ -40,7 +40,8 @@ export default function MailInfoBlock({ webMail, hostName, domain, password }) {
}, [selectedOption]); }, [selectedOption]);
const renderSelectOptions = () => { const renderSelectOptions = () => {
return mailInfoBlockSelectOptions.map(option => const options = mailInfoBlockSelectOptions(i18n);
return options.map(option =>
<option key={option.type} value={option.type}>{option.value}</option> <option key={option.type} value={option.type}>{option.value}</option>
); );
} }

View file

@ -6,17 +6,34 @@ import MobileTopNav from '../MainNav/Mobile/MobileTopNav';
import Menu from '../MainNav/Stat-menu/Menu'; import Menu from '../MainNav/Stat-menu/Menu';
import Panel from '../MainNav/Panel/Panel'; import Panel from '../MainNav/Panel/Panel';
import './MainNav.scss'; import './MainNav.scss';
import { useHistory } from 'react-router';
import Spinner from '../Spinner/Spinner';
const MainNav = props => { const MainNav = () => {
const history = useHistory();
const [loading, setLoading] = useState(true);
const [state, setState] = useState({ const [state, setState] = useState({
menuHeight: 135, menuHeight: 135,
tabs: [],
showTopNav: false showTopNav: false
}); });
const { activeElement, focusedElement, menuTabs } = useSelector(state => state.mainNavigation); const { userName, user, session: { look } } = useSelector(state => state.session);
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();
useEffect(() => {
if (!userName || !Object.entries(user).length) {
return history.push('/login');
}
const tabs = look ? userMenuTabs : adminMenuTabs;
setState({ ...state, tabs });
setLoading(false);
}, [userName, user, history]);
const controlFocusedTabWithCallback = useCallback(event => { const controlFocusedTabWithCallback = useCallback(event => {
let isSearchInputFocused = document.querySelector('input:focus') || document.querySelector('textarea:focus') || document.querySelector('textarea:focus'); let isSearchInputFocused = document.querySelector('input:focus') || document.querySelector('textarea:focus') || document.querySelector('textarea:focus');
let currentActiveTabPositionInArray; let currentActiveTabPositionInArray;
@ -32,9 +49,9 @@ const MainNav = props => {
if (!focusedElement) { if (!focusedElement) {
dispatch(addFocusedElement(activeElement)); dispatch(addFocusedElement(activeElement));
currentActiveTabPositionInArray = menuTabs.indexOf(activeElement); currentActiveTabPositionInArray = state.tabs.indexOf(activeElement);
} else { } else {
currentActiveTabPositionInArray = menuTabs.indexOf(focusedElement); currentActiveTabPositionInArray = state.tabs.indexOf(focusedElement);
} }
} }
@ -43,14 +60,14 @@ const MainNav = props => {
} }
if (event.keyCode === 37) { if (event.keyCode === 37) {
let newFocusedMenuTab = handleLeftArrowKey(menuTabs, currentActiveTabPositionInArray); let newFocusedMenuTab = handleLeftArrowKey(state.tabs, currentActiveTabPositionInArray);
dispatch(addFocusedElement(newFocusedMenuTab)); dispatch(addFocusedElement(newFocusedMenuTab));
} else if (event.keyCode === 39) { } else if (event.keyCode === 39) {
let newFocusedMenuTab = handleRightArrowKey(menuTabs, currentActiveTabPositionInArray); let newFocusedMenuTab = handleRightArrowKey(state.tabs, currentActiveTabPositionInArray);
dispatch(addFocusedElement(newFocusedMenuTab)); dispatch(addFocusedElement(newFocusedMenuTab));
} else if (event.keyCode === 13) { } else if (event.keyCode === 13) {
if (!controlPanelFocusedElement && focusedElement) { if (!controlPanelFocusedElement && focusedElement && (focusedElement !== activeElement)) {
props.history.push({ pathname: focusedElement }); history.push({ pathname: focusedElement });
dispatch(addActiveElement(focusedElement)); dispatch(addActiveElement(focusedElement));
dispatch(removeFocusedElement()); dispatch(removeFocusedElement());
} }
@ -74,7 +91,7 @@ const MainNav = props => {
}, [activeElement]); }, [activeElement]);
useEffect(() => { useEffect(() => {
dispatch(addActiveElement(props.history.location.pathname)); dispatch(addActiveElement(history.location.pathname));
}, []); }, []);
const handleLeftArrowKey = (array, indexInArray) => { const handleLeftArrowKey = (array, indexInArray) => {
@ -149,8 +166,14 @@ const MainNav = props => {
return ( return (
<div className="main-nav"> <div className="main-nav">
{
loading
? <Spinner />
: (<>
<Panel showTopNav={showTopNav} visibleNav={state.showTopNav} /> <Panel showTopNav={showTopNav} visibleNav={state.showTopNav} />
{topNavigation()} {topNavigation()}
</>)
}
</div> </div>
); );
} }

View file

@ -1,3 +1,5 @@
$secondaryLight: #f8b014;
.mobile-top-nav-wrapper.hide { .mobile-top-nav-wrapper.hide {
opacity: 0; opacity: 0;
} }
@ -58,7 +60,7 @@
padding: 2px; padding: 2px;
&:hover { &:hover {
color: #ff6701; color: $secondaryLight;
} }
} }
} }

View file

@ -0,0 +1,9 @@
import React from 'react';
export default function Bell(props) {
return (
<svg width="24px" height="24px" viewBox="0 0 24 24" id="_24x24_On_Light_Notification" data-name="24x24/On Light/Notification" xmlns="http://www.w3.org/2000/svg">
<rect id="view-box" width="24" height="24" fill="none" />
<path id="Shape" d="M6,17v-.5H2.25A2.253,2.253,0,0,1,0,14.25v-.382a2.542,2.542,0,0,1,1.415-2.289A1.248,1.248,0,0,0,2.1,10.572l.446-4.91a6.225,6.225,0,0,1,12.4,0l.446,4.91a1.26,1.26,0,0,0,.686,1.005,2.547,2.547,0,0,1,1.418,2.29v.382a2.252,2.252,0,0,1-2.25,2.25H11.5V17A2.75,2.75,0,0,1,6,17Zm1.5,0A1.25,1.25,0,0,0,10,17v-.5H7.5ZM4.045,5.8,3.6,10.708A2.738,2.738,0,0,1,2.089,12.92a1.055,1.055,0,0,0-.589.949v.382A.751.751,0,0,0,2.25,15h13A.751.751,0,0,0,16,14.25v-.382a1.054,1.054,0,0,0-.586-.948A2.739,2.739,0,0,1,13.9,10.708L13.456,5.8a4.725,4.725,0,0,0-9.411,0Z" transform="translate(3.25 2.25)" fill="#f8b014" />
</svg>);
}

View file

@ -0,0 +1,9 @@
import React from 'react';
export default function BellUnread(props) {
return (<svg width="24px" height="24px" viewBox="0 0 24 24" id="_24x24_On_Light_Notification-Alert" data-name="24x24/On Light/Notification-Alert" xmlns="http://www.w3.org/2000/svg">
<rect id="view-box" width="24" height="24" fill="none" />
<path id="Shape" d="M6,17v-.5H2.25A2.253,2.253,0,0,1,0,14.25v-.382a2.542,2.542,0,0,1,1.415-2.289A1.247,1.247,0,0,0,2.1,10.572l.446-4.91A6.227,6.227,0,0,1,10.618.286a5.477,5.477,0,0,0-.635,1.374A4.794,4.794,0,0,0,8.75,1.5,4.7,4.7,0,0,0,4.045,5.8L3.6,10.708A2.739,2.739,0,0,1,2.089,12.92a1.055,1.055,0,0,0-.589.949v.382A.751.751,0,0,0,2.25,15h13A.751.751,0,0,0,16,14.25v-.382a1.053,1.053,0,0,0-.586-.948A2.739,2.739,0,0,1,13.9,10.708l-.2-2.18a5.473,5.473,0,0,0,1.526.221l.166,1.822a1.26,1.26,0,0,0,.686,1.005,2.547,2.547,0,0,1,1.418,2.29v.382a2.252,2.252,0,0,1-2.25,2.25H11.5V17A2.75,2.75,0,0,1,6,17Zm1.5,0A1.25,1.25,0,0,0,10,17v-.5H7.5ZM15.047,6.744A3.486,3.486,0,0,1,13.5,6.28L13.456,5.8a4.7,4.7,0,0,0-1.648-3.185,3.5,3.5,0,0,1,.61-1.417A6.221,6.221,0,0,1,14.95,5.662l.1,1.081v0Z" transform="translate(3.25 2.25)" fill="#f8b014" />
<path id="Shape-2" data-name="Shape" d="M3.5,7A3.5,3.5,0,1,1,7,3.5,3.5,3.5,0,0,1,3.5,7Z" transform="translate(15 2)" fill="#f8b014" />
</svg>);
}

View file

@ -1,31 +1,38 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { getAppNotifications, deleteNotification } from '../../../../ControlPanelService/Notifications'; import { getAppNotifications, deleteNotification } from 'src/ControlPanelService/Notifications';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { addNotifications } from 'src/actions/Notification/notificationActions';
import Bell from './Bell';
import BellUnread from './BellUnread';
import { useDispatch, useSelector } from 'react-redux';
import './Notifications.scss'; import './Notifications.scss';
const Notifications = () => { const Notifications = () => {
const [notifications, setNotifications] = useState([]); const { i18n } = useSelector(state => state.session);
const [loading, setLoading] = useState(true); const { notifications } = useSelector(state => state.notifications);
const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
useEffect(() => { useEffect(() => {
fetchData(); fetchData();
}, []); }, []);
const fetchData = () => { const fetchData = () => {
setLoading(true);
getAppNotifications() getAppNotifications()
.then(res => { .then(res => {
if (res.data) {
const result = []; const result = [];
for (let notification in res.data) { for (let notification in res.data.result) {
result.push(res.data[notification]); result.push(res.data.result[notification]);
} }
setNotifications(result); dispatch(addNotifications(result));
setLoading(false);
})
.catch(err => {
console.error(err);
setLoading(false); setLoading(false);
}
}) })
.catch(err => console.error(err))
} }
const removeNotification = id => { const removeNotification = id => {
@ -40,20 +47,20 @@ const Notifications = () => {
if (notifications.length) { if (notifications.length) {
return notifications.map(item => { return notifications.map(item => {
return ( return (
<React.Fragment> <>
<div className="dropdown-item"> <div className="dropdown-item">
<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 dangerouslySetInnerHTML={{ __html: item.NOTICE }}></div>
<div className="dropdown-divider"></div> <div className="dropdown-divider"></div>
</React.Fragment> </>
); );
}); });
} else { } else {
return ( return (
<div className="dropdown-item" style={{ cursor: 'default', marginBottom: '10' }}> <div className="dropdown-item" style={{ cursor: 'default', marginBottom: '10' }}>
<span className="title">{window.GLOBAL.App.Constants.NOTIFICATIONS_EMPTY}</span> <span className="title">{i18n['no notifications']}</span>
</div> </div>
); );
} }
@ -63,7 +70,11 @@ const Notifications = () => {
<div className="btn-group"> <div className="btn-group">
<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">
<FontAwesomeIcon icon="bell" /> {
notifications.length
? <BellUnread />
: <Bell />
}
</div> </div>
</button> </button>
<div className="dropdown-menu"> <div className="dropdown-menu">

View file

@ -1,3 +1,17 @@
$whiteBackground: #ececec;
$primary: #2c54ac;
$primaryLight: #d7dcef;
$primaryActive: #1e5cb2;
$secondary: #fcac04;
$secondaryLight: #f8b014;
$secondaryActive: #fdb51c;
$hoverButtonText: #2c54ac;
$activeButtonText: #fff;
$notifications: #e49d45;
$notificationsLight: #de9234;
$notificationsActive: #6f4e2b;
$textColor: #555;
.top-panel .profile-menu { .top-panel .profile-menu {
div { div {
width: auto; width: auto;
@ -38,7 +52,10 @@
max-height: 75vh; max-height: 75vh;
overflow: auto; overflow: auto;
cursor: default; cursor: default;
background: #454545; background: #222e44;
border: 1px solid #fcac04;
border-width: 1px 0 0 0;
box-shadow: rgb(34, 46, 68) 0px 0px 10px -1px;
> div { > div {
cursor: default; cursor: default;
@ -65,18 +82,18 @@
width: 100%; width: 100%;
padding: 10px 0 0 10px; padding: 10px 0 0 10px;
text-align: left; text-align: left;
color: #C4DA5E; color: $secondary;
} }
span.delete-notification { span.delete-notification {
width: 10px; width: 10px;
height: 10px; height: 10px;
background: #C4DA5E; background: $secondary;
border-radius: 50%; border-radius: 50%;
cursor: pointer; cursor: pointer;
&:hover { &:hover {
border: 2px solid #C4DA5E; border: 2px solid $secondaryLight;
background: transparent; background: transparent;
} }
} }
@ -94,10 +111,10 @@
a { a {
display: contents; display: contents;
color: #5ABDB5; color: $notifications;
&:hover { &:hover {
color: #2CA99B; color: $notificationsLight;
} }
} }
} }

View file

@ -9,7 +9,7 @@ import { Link, useHistory } from "react-router-dom";
import './Panel.scss'; import './Panel.scss';
const Panel = props => { const Panel = props => {
const { i18n } = window.GLOBAL.App; const { i18n, userName, session: { look, user } } = useSelector(state => state.session);
const session = useSelector(state => state.session); const session = useSelector(state => state.session);
const { activeElement, focusedElement } = useSelector(state => state.mainNavigation); const { activeElement, focusedElement } = useSelector(state => state.mainNavigation);
const dispatch = useDispatch(); const dispatch = useDispatch();
@ -29,7 +29,7 @@ const Panel = props => {
} }
} }
const className = activeName => { const className = (activeName, extraClass = '') => {
let className = 'top-link'; let className = 'top-link';
if (activeName === activeElement) { if (activeName === activeElement) {
@ -40,12 +40,14 @@ const Panel = props => {
className += ' focus'; className += ' focus';
} }
return className; return className + ` ${extraClass}`;
} }
const handleState = (tab, event) => { const handleState = (tab, event) => {
event.preventDefault(); if (`${window.location.pathname}${window.location.search}` === tab) {
history.push(tab); return event.preventDefault();
}
dispatch(addActiveElement(tab)); dispatch(addActiveElement(tab));
} }
@ -67,45 +69,65 @@ const Panel = props => {
<div className="panel-wrapper"> <div className="panel-wrapper">
{loading && <Spinner />} {loading && <Spinner />}
<div className="top-panel"> <div className={`top-panel ${user ? '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/'))}>
<div className="logo-img"></div> <div>
<img src="/images/white_logo.png" alt="Logo" />
</div>
</Link> </Link>
</div> </div>
{userName === 'admin' && (<>
<div className={className("/list/package/")}> <div className={className("/list/package/")}>
<button onClick={event => handleState("/list/package/", event)} onKeyPress={event => event.preventDefault()}>{i18n.Packages}</button> <Link to="/list/package/" onClick={event => handleState("/list/package/", event)} onKeyPress={event => event.preventDefault()}>{i18n.Packages}</Link>
</div> </div>
<div className={className("/list/ip/")}> <div className={className("/list/ip/")}>
<button onClick={event => handleState("/list/ip/", event)} onKeyPress={event => event.preventDefault()}>{i18n.IP}</button> <Link to="/list/ip/" onClick={event => handleState("/list/ip/", event)} onKeyPress={event => event.preventDefault()}>{i18n.IP}</Link>
</div> </div>
<div className={className("/list/rrd/")}> <div className={className("/list/rrd/")}>
<button onClick={event => handleState("/list/rrd/", event)} onKeyPress={event => event.preventDefault()}>{i18n.Graphs}</button> <Link to="/list/rrd/" onClick={event => handleState("/list/rrd/", event)} onKeyPress={event => event.preventDefault()}>{i18n.Graphs}</Link>
</div> </div>
</>)}
<div className={className("/list/stats/")}> <div className={className("/list/stats/")}>
<button onClick={event => handleState("/list/stats/", event)} onKeyPress={event => event.preventDefault()}>{i18n.Statistics}</button> <Link to="/list/stats/" onClick={event => handleState("/list/stats/", event)} onKeyPress={event => event.preventDefault()}>{i18n.Statistics}</Link>
</div> </div>
<div className={className("/list/log/")}> <div className={className("/list/log/")}>
<button onClick={event => handleState("/list/log/", event)} onKeyPress={event => event.preventDefault()}>{i18n.Log}</button> <Link to="/list/log/" onClick={event => handleState("/list/log/", event)} onKeyPress={event => event.preventDefault()}>{i18n.Log}</Link>
</div> </div>
{userName === 'admin' && (<>
<div className={className("/list/updates/")}> <div className={className("/list/updates/")}>
<button onClick={event => handleState("/list/updates/", event)} onKeyPress={event => event.preventDefault()}>{i18n.Updates}</button> <Link to="/list/updates/" onClick={event => handleState("/list/updates/", event)} onKeyPress={event => event.preventDefault()}>{i18n.Updates}</Link>
</div> </div>
{session.session.FIREWALL_SYSTEM && <div className={className("/list/firewall/")}> {session.session.FIREWALL_SYSTEM && <div className={className("/list/firewall/")}>
<button onClick={event => handleState("/list/firewall/", event)} onKeyPress={event => event.preventDefault()}>{i18n.Firewall}</button> <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="fm"> </>)}
<a href="/list/directory/">{i18n['File Manager']}</a> {session.session.FILEMANAGER_KEY && <div className={className("/list/directory/", "fm")}>
<Link to="/list/directory/">{i18n['File Manager']}</Link>
</div>} </div>}
{session.session.SOFTACULOUS === "yes" && <div><a href="/list/softaculous/">{i18n.Apps}</a> {session.session.SOFTACULOUS === "yes" && <div className={className("/softaculous/")}><a href="/softaculous/">{i18n.Apps ?? 'Apps'}</a>
</div>} </div>}
{userName === 'admin' && (
<div className={className("/list/server/")}> <div className={className("/list/server/")}>
<button onClick={event => handleState("/list/server/", event)} onKeyPress={event => event.preventDefault()}>{i18n.Server}</button></div> <Link to="/list/server/" onClick={event => handleState("/list/server/", event)} onKeyPress={event => event.preventDefault()}>{i18n.Server}</Link>
</div>
)}
</div> </div>
<div className="container profile-menu"> <div className="container profile-menu">
<Notifications /> <Notifications />
<div><Link to={`/edit/user?user=${session.userName}`}>{session.userName}</Link></div> <div>
<Link to={`/edit/user?user=${session.userName}`}>
{look
? <div className="long-username">
<span>{user}</span>
<FontAwesomeIcon icon="long-arrow-alt-right" />
<span>{look}</span>
</div>
: session.userName
}
</Link>
</div>
<div><button onClick={signOut}>{i18n['Log out']}</button></div> <div><button onClick={signOut}>{i18n['Log out']}</button></div>
</div> </div>
</div> </div>

View file

@ -1,3 +1,14 @@
$whiteBackground: #ececec;
$primary: #2c54ac;
$primaryLight: #d7dcef;
$primaryActive: #1e5cb2;
$secondary: #fcac04;
$secondaryLight: #f8b014;
$secondaryActive: #fdb51c;
$hoverButtonText: #2c54ac;
$activeButtonText: #fff;
$textColor: #555;
.top-panel.small-device { .top-panel.small-device {
display: none; display: none;
} }
@ -10,7 +21,7 @@
width: 100%; width: 100%;
text-align: center; text-align: center;
color: white; color: white;
background: #111; background: #222e44;
height: 34px; height: 34px;
align-items: center; align-items: center;
padding: 0 13%; padding: 0 13%;
@ -22,13 +33,10 @@
width: 80%; width: 80%;
height: 100%; height: 100%;
.logo .logo-img { .logo div {
background-image: url("/images/sprite.png?1446554103"); img {
background-position: -117px -57px; width: 82%;
background-repeat: no-repeat; }
height: 22px;
width: 70px;
margin-left: -2px;
&:hover { &:hover {
background-color: transparent; background-color: transparent;
@ -65,7 +73,7 @@
background: white; background: white;
a, button { a, button {
color: #f79b44; color: $secondary;
font-weight: bold; font-weight: bold;
&:hover { &:hover {
@ -73,13 +81,13 @@
} }
&:active { &:active {
background: #ff6701; background: $secondaryActive;
color: white; color: white;
} }
} }
&:hover { &:hover {
background: #f79b44; background: $secondaryLight;
} }
} }
} }
@ -91,9 +99,11 @@
div { div {
width: 7rem; width: 7rem;
height: 100%; height: 100%;
transform: translateX(-5px);
padding-right: 5px;
&:hover { &:hover {
background: #f79b44; background: $secondaryLight;
} }
} }
@ -113,8 +123,7 @@
.top-link.focus { .top-link.focus {
a, button { a, button {
color: #5edad0; color: $secondaryActive;
text-decoration: underline;
} }
} }
} }
@ -129,20 +138,21 @@
div.bell { div.bell {
width: auto; width: auto;
color: #C0E60E; color: $secondary;
padding: 3px 0;
svg { svg {
border-radius: 30px; border-radius: 30px;
width: 25px; width: 100%;
height: 25px; height: 100%;
padding: 5px; padding: 3px;
&:hover { &:hover {
background: rgba(255, 255, 255, 0.4); background: #79522294;
} }
&:hover { &:active {
background: #c0e6198a; background: #866032;
} }
} }
} }
@ -152,11 +162,11 @@
font-weight: 700; font-weight: 700;
&:hover { &:hover {
color: #ffd62e; color: $secondaryLight;
} }
&:active { &:active {
color: #f79b44; color: $secondaryActive;
} }
} }
@ -167,11 +177,40 @@
font-weight: 100; font-weight: 100;
&:hover { &:hover {
color: #C0E60E; color: $secondaryLight;
} }
&:active { &:active {
color: #ffd62e; color: $secondaryActive;
}
}
}
}
.top-panel.long-profile {
.left-menu {
width: 75%;
}
.profile-menu {
width: 25%;
> div + div {
width: max-content;
}
.long-username {
display: flex;
justify-content: center;
align-items: center;
width: auto;
> span:nth-child(1) {
margin-right: 5px;
}
> span:nth-child(3) {
margin-left: 5px;
} }
} }
} }

View file

@ -1,7 +1,7 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { addActiveElement } from '../../../actions/MainNavigation/mainNavigationActions'; import { addActiveElement } from '../../../actions/MainNavigation/mainNavigationActions';
import { useSelector, useDispatch } from "react-redux"; import { useSelector, useDispatch } from "react-redux";
import { useHistory } from "react-router-dom"; import { Link } from "react-router-dom";
import './Menu.scss'; import './Menu.scss';
@ -26,12 +26,9 @@ const style = ({ menuHeight, mobile }) => {
} }
const Menu = props => { const Menu = props => {
const session = useSelector(state => state.session);
const { activeElement, focusedElement } = useSelector(state => state.mainNavigation); const { activeElement, focusedElement } = useSelector(state => state.mainNavigation);
const { user } = useSelector(state => state.session); const { user, i18n, session: { look } } = useSelector(state => state.session);
const { i18n } = window.GLOBAL.App;
const dispatch = useDispatch(); const dispatch = useDispatch();
const history = useHistory();
useEffect(() => { useEffect(() => {
if (user.LANGUAGE) { if (user.LANGUAGE) {
@ -40,8 +37,10 @@ const Menu = props => {
}, [user]); }, [user]);
const handleState = (tab, event) => { const handleState = (tab, event) => {
event.preventDefault(); if (`${window.location.pathname}${window.location.search}` === tab) {
history.push(tab); return event.preventDefault();
}
dispatch(addActiveElement(tab)); dispatch(addActiveElement(tab));
} }
@ -49,73 +48,96 @@ const Menu = props => {
return `stat ${activeName === activeElement && 'l-active'} ${activeName === focusedElement && 'focus'}`; return `stat ${activeName === activeElement && 'l-active'} ${activeName === focusedElement && 'focus'}`;
} }
const sizeFormatter = (bytes, decimals) => {
if (!bytes) return null;
if (bytes === "0") {
return <span className="value">0 <span className="unit">b</span></span>;
}
let k = 1024,
dm = decimals <= 0 ? 0 : decimals || 2,
sizes = ['b', 'kb', 'Mb', 'GB'],
i = Math.floor(Math.log(bytes) / Math.log(k));
return (<span className="value">{parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} <span className="unit">{sizes[i]}</span></span>);
}
return ( return (
<div className="menu-wrapper"> <div className="menu-wrapper">
<div className={className(props.menuHeight)} style={{ height: style(props) }}> <div className={className(props.menuHeight)} style={{ height: style(props) }}>
<div className={statClassName("/list/user/")}> <div className={statClassName("/list/user/")}>
<button onClick={event => handleState("/list/user/", event)} onKeyPress={event => event.preventDefault()}> <Link to="/list/user/" onClick={event => handleState("/list/user/", event)} onKeyPress={event => event.preventDefault()}>
<h3>{i18n.USER}</h3> <h3>{i18n.USER}</h3>
<div className="stats"> <div className="stats">
{
look
? (<>
<div><span>{i18n.Disk}:</span> <span>{sizeFormatter(user.U_DISK)}</span></div>
<div><span>{i18n.Bandwidth}:</span> <span>{sizeFormatter(user.U_BANDWIDTH)}</span></div>
</>)
: (<>
<div><span>{i18n.users}:</span> <span>{user.U_USERS}</span></div> <div><span>{i18n.users}:</span> <span>{user.U_USERS}</span></div>
<div><span>{i18n.spnd}:</span> <span>{user.SUSPENDED_USERS}</span></div> <div><span>{i18n.spnd}:</span> <span>{user.SUSPENDED_USERS}</span></div>
</>)
}
</div> </div>
</button> </Link>
</div> </div>
<div className={statClassName("/list/web/")}> <div className={statClassName("/list/web/")}>
<button onClick={event => handleState("/list/web/", event)} onKeyPress={event => event.preventDefault()}> <Link to="/list/web/" onClick={event => handleState("/list/web/", event)} onKeyPress={event => event.preventDefault()}>
<h3>{i18n.WEB}</h3> <h3>{i18n.WEB}</h3>
<div className="stats"> <div className="stats">
<div><span>{i18n.domains}:</span> <span>{user.U_WEB_DOMAINS}</span></div> <div><span>{i18n.domains}:</span> <span>{user.U_WEB_DOMAINS}</span></div>
<div><span>{i18n.aliases}:</span> <span>{user.U_WEB_ALIASES}</span></div> <div><span>{i18n.aliases}:</span> <span>{user.U_WEB_ALIASES}</span></div>
<div><span>{i18n.spnd}:</span> <span>{user.SUSPENDED_WEB}</span></div> <div><span>{i18n.spnd}:</span> <span>{user.SUSPENDED_WEB}</span></div>
</div> </div>
</button> </Link>
</div> </div>
<div className={statClassName("/list/dns/")}> <div className={statClassName("/list/dns/")}>
<button onClick={event => handleState("/list/dns/", event)} onKeyPress={event => event.preventDefault()}> <Link to="/list/dns/" onClick={event => handleState("/list/dns/", event)} onKeyPress={event => event.preventDefault()}>
<h3>{i18n.DNS}</h3> <h3>{i18n.DNS}</h3>
<div className="stats"> <div className="stats">
<div><span>{i18n.domains}:</span> <span>{user.U_DNS_DOMAINS}</span></div> <div><span>{i18n.domains}:</span> <span>{user.U_DNS_DOMAINS}</span></div>
<div><span>{i18n.records}:</span> <span>{user.U_DNS_RECORDS}</span></div> <div><span>{i18n.records}:</span> <span>{user.U_DNS_RECORDS}</span></div>
<div><span>{i18n.spnd}:</span> <span>{user.SUSPENDED_DNS}</span></div> <div><span>{i18n.spnd}:</span> <span>{user.SUSPENDED_DNS}</span></div>
</div> </div>
</button> </Link>
</div> </div>
<div className={statClassName("/list/mail/")}> <div className={statClassName("/list/mail/")}>
<button onClick={event => handleState("/list/mail/", event)} onKeyPress={event => event.preventDefault()}> <Link to="/list/mail/" onClick={event => handleState("/list/mail/", event)} onKeyPress={event => event.preventDefault()}>
<h3>{i18n.MAIL}</h3> <h3>{i18n.MAIL}</h3>
<div className="stats"> <div className="stats">
<div><span>{i18n.domains}:</span> <span>{user.U_MAIL_DOMAINS}</span></div> <div><span>{i18n.domains}:</span> <span>{user.U_MAIL_DOMAINS}</span></div>
<div><span>{i18n.accounts}:</span> <span>{user.U_MAIL_ACCOUNTS}</span></div> <div><span>{i18n.accounts}:</span> <span>{user.U_MAIL_ACCOUNTS}</span></div>
<div><span>{i18n.spnd}:</span> <span>{user.SUSPENDED_MAIL}</span></div> <div><span>{i18n.spnd}:</span> <span>{user.SUSPENDED_MAIL}</span></div>
</div> </div>
</button> </Link>
</div> </div>
<div className={statClassName("/list/db/")}> <div className={statClassName("/list/db/")}>
<button onClick={event => handleState("/list/db/", event)} onKeyPress={event => event.preventDefault()}> <Link to="/list/db/" onClick={event => handleState("/list/db/", event)} onKeyPress={event => event.preventDefault()}>
<h3>{i18n.DB}</h3> <h3>{i18n.DB}</h3>
<div className="stats"> <div className="stats">
<div><span>{i18n.databases}:</span> <span>{user.U_DATABASES}</span></div> <div><span>{i18n.databases}:</span> <span>{user.U_DATABASES}</span></div>
<div><span>{i18n.spnd}:</span> <span>{user.SUSPENDED_DB}</span></div> <div><span>{i18n.spnd}:</span> <span>{user.SUSPENDED_DB}</span></div>
</div> </div>
</button> </Link>
</div> </div>
<div className={statClassName("/list/cron/")}> <div className={statClassName("/list/cron/")}>
<button onClick={event => handleState("/list/cron/", event)} onKeyPress={event => event.preventDefault()}> <Link to="/list/cron/" onClick={event => handleState("/list/cron/", event)} onKeyPress={event => event.preventDefault()}>
<h3>{i18n.CRON}</h3> <h3>{i18n.CRON}</h3>
<div className="stats"> <div className="stats">
<div><span>{i18n.jobs}:</span> <span>{user.U_CRON_JOBS}</span></div> <div><span>{i18n.jobs}:</span> <span>{user.U_CRON_JOBS}</span></div>
<div><span>{i18n.spnd}:</span> <span>{user.SUSPENDED_CRON}</span></div> <div><span>{i18n.spnd}:</span> <span>{user.SUSPENDED_CRON}</span></div>
</div> </div>
</button> </Link>
</div> </div>
<div className={statClassName("/list/backup/") + ' last'}> <div className={statClassName("/list/backup/") + ' last'}>
<button onClick={event => handleState("/list/backup/", event)} onKeyPress={event => event.preventDefault()}> <Link to="/list/backup/" onClick={event => handleState("/list/backup/", event)} onKeyPress={event => event.preventDefault()}>
<h3>{i18n.BACKUP}</h3> <h3>{i18n.BACKUP}</h3>
<div className="stats"> <div className="stats">
<div><span>{i18n.backups}:</span> <span>{user.U_BACKUPS}</span></div> <div><span>{i18n.backups}:</span> <span>{user.U_BACKUPS}</span></div>
</div> </div>
</button> </Link>
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,3 +1,14 @@
$whiteBackground: #ececec;
$primary: #2c54ac;
$primaryLight: #d7dcef;
$primaryActive: #1e5cb2;
$secondary: #fcac04;
$secondaryLight: #f8b014;
$secondaryActive: #fdb51c;
$hoverButtonText: #2c54ac;
$activeButtonText: #fff;
$textColor: #555;
.menu-wrapper { .menu-wrapper {
position: fixed; position: fixed;
width: 100%; width: 100%;
@ -71,10 +82,10 @@
&:hover { &:hover {
cursor: pointer; cursor: pointer;
border-bottom: 3px solid #ff6701; border-bottom: 3px solid $secondaryLight;
h3 { h3 {
color: #ff6701; color: $secondary;
} }
.stats { .stats {
@ -83,10 +94,10 @@
} }
&:active { &:active {
border-color: #f72b44; border-color: $secondaryActive;
h3 { h3 {
color: #f72b44; color: $secondary;
} }
} }
@ -102,20 +113,20 @@
} }
.l-active { .l-active {
border-bottom: 3px solid #ff6701; border-bottom: 3px solid $primary;
h3 { h3 {
color: #ff6701; color: $primary;
font-size: 18px; font-size: 18px;
margin-bottom: 25px; margin-bottom: 25px;
} }
} }
.stat.focus { .stat.focus {
border-bottom: 3px solid #5edad0 !important; border-bottom: 3px solid $secondaryLight !important;
a, h3 { a, h3 {
color: #36B3A9 !important; color: $secondaryLight !important;
} }
} }
} }
@ -203,7 +214,7 @@
} }
.stat.l-active { .stat.l-active {
background: #ff67010d; background: #fdac020d;
} }
} }
} }

View file

@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import { useSelector } from 'react-redux';
import './Checkbox.scss'; import './Checkbox.scss';
function toggleAll(props, e) { function toggleAll(props, e) {
@ -6,13 +7,15 @@ function toggleAll(props, e) {
} }
const Checkbox = (props) => { const Checkbox = (props) => {
const { i18n } = useSelector(state => state.session);
return ( return (
<div className="input-group-prepend"> <div className="input-group-prepend">
<div className="input-group-text"> <div className="input-group-text">
<input type="checkbox" onChange={(e) => toggleAll(props, e)} aria-label="Checkbox for following text input" id="checkbox" checked={props.toggled} /> <input type="checkbox" onChange={(e) => toggleAll(props, e)} aria-label="Checkbox for following text input" id="checkbox" checked={props.toggled} />
</div> </div>
<span className="input-group-text"> <span className="input-group-text">
<label htmlFor="checkbox">{window.GLOBAL.App.i18n['toggle all']}</label> <label htmlFor="checkbox">{i18n['toggle all']}</label>
</span> </span>
</div> </div>
); );

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