Merge pull request #2070 from serghey-rodin/release/react-integration

React integration ready for v1.0.0 release.
This commit is contained in:
Serghey Rodin 2021-10-22 17:57:08 +03:00 committed by GitHub
commit c520eb283a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
213 changed files with 2699 additions and 1713 deletions

View file

@ -3,12 +3,10 @@
<head>
<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="theme-color" content="#000000" />
<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>
</head>

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,12 +1,11 @@
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 webApiUri = '/list/mail/mail.php';
const addMailApiUri = '/api/add/mail/index.php';
const mailInfoUri = '/api/edit/mail/index.php';
const updateMailUri = '/api/edit/mail/index.php';
const webApiUri = '/api/v1/list/mail/index.php';
const addMailApiUri = '/api/v1/add/mail/index.php';
const mailInfoUri = '/api/v1/edit/mail/index.php';
const updateMailUri = '/api/v1/edit/mail/index.php';
export const getMailList = () => {
return axios.get(BASE_URL + webApiUri);
@ -23,30 +22,34 @@ export const getMailAccountInfo = (domain, account) => {
export const bulkAction = (action, domainNameSystems) => {
const formData = new FormData();
formData.append("action", action);
formData.append("token", token);
formData.append("token", getAuthToken());
domainNameSystems.forEach(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 = []) => {
const formData = new FormData();
formData.append("action", action);
formData.append("token", token);
formData.append("token", getAuthToken());
formData.append("domain", domain);
accounts.forEach(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 => {
return axios.get(BASE_URL + uri);
return axios.get(BASE_URL + uri, {
params: {
token: getAuthToken()
}
});
}
export const addMail = data => {
@ -83,7 +86,7 @@ export const getMailInfo = domain => {
return axios.get(BASE_URL + mailInfoUri, {
params: {
domain,
token
token: getAuthToken()
}
});
}
@ -98,12 +101,12 @@ export const updateMail = (data, domain) => {
return axios.post(BASE_URL + updateMailUri, formDataObject, {
params: {
domain,
token
token: getAuthToken()
}
});
}
export const mailInfoBlockSelectOptions = [
export const mailInfoBlockSelectOptions = i18n => [
{
value: i18n['Use server hostname'],
type: 'hostname',

View file

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

View file

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

View file

@ -1,12 +1,12 @@
import axios from "axios";
const BASE_URL = window.location.origin;
const webApiUri = '/list/rrd/rrd.php';
const webApiUri = '/api/v1/list/rrd/index.php';
export const getRrdList = () => {
return axios.get(BASE_URL + webApiUri);
}
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";
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 = '') => {
const formData = new FormData();

View file

@ -1,4 +1,5 @@
import axios from "axios";
import { getAuthToken } from "src/utils/token";
const BASE_URL = window.location.origin;
const webApiUri = '/search/search.php';
@ -8,5 +9,9 @@ export const getSearchResultsList = term => {
}
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 { getAuthToken } from "src/utils/token";
const BASE_URL = window.location.origin;
const token = localStorage.getItem("token");
const webApiUri = '/list/server/server.php';
const serverAdditionalInfoUri = '/api/edit/server/index.php';
const webApiUri = '/api/v1/list/server/index.php';
const serverAdditionalInfoUri = '/api/v1/edit/server/index.php';
export const getServersList = () => {
return axios.get(BASE_URL + webApiUri);
@ -12,23 +12,27 @@ export const getServersList = () => {
export const bulkAction = (action, services) => {
const formData = new FormData();
formData.append("action", action);
formData.append("token", token);
formData.append("token", getAuthToken());
services.forEach(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 => {
return axios.get(BASE_URL + uri);
return axios.get(BASE_URL + uri, {
params: {
token: getAuthToken()
}
});
}
export const getServerAdditionalInfo = () => {
return axios.get(BASE_URL + serverAdditionalInfoUri, {
params: {
token
token: getAuthToken()
}
});
}
@ -40,19 +44,19 @@ export const updateService = (data, uri = '') => {
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: {
token
token: getAuthToken()
}
});
}
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 => {
return axios.get(`${BASE_URL}/list/server/server.php?${service}`);
return axios.get(`${BASE_URL}${webApiUri}?${service}`);
}
export const services = [

View file

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

View file

@ -1,9 +1,9 @@
import axios from "axios";
import { getAuthToken } from "src/utils/token";
const deleteAutoUpdateUri = '/delete/cron/autoupdate/';
const addAutoUpdateUri = '/add/cron/autoupdate/';
const webApiUri = '/list/updates/updates.php';
const token = localStorage.getItem("token");
const webApiUri = '/api/v1/list/updates/index.php';
const BASE_URL = window.location.origin;
export const getUpdatesList = () => {
@ -13,23 +13,35 @@ export const getUpdatesList = () => {
export const bulkAction = (action, updates) => {
const formData = new FormData();
formData.append("action", action);
formData.append("token", token);
formData.append("token", getAuthToken());
updates.forEach(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 => {
return axios.get(`${BASE_URL}${uri}?token=${token}`);
return axios.get(BASE_URL + uri, {
params: {
token: getAuthToken()
}
});
}
export const enableAutoUpdate = () => {
return axios.get(`${BASE_URL}${addAutoUpdateUri}?token=${token}`);
return axios.get(`${BASE_URL}${addAutoUpdateUri}`, {
params: {
token: getAuthToken()
}
});
};
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";
const BASE_URL = window.location.origin;
const userNSApiUri = '/api/list-user-ns.php';
const userNSApiUri = '/api/v1/list-user-ns.php';
export const getUserNS = () => {
return axios.get(BASE_URL + userNSApiUri);

View file

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

View file

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

View file

@ -3,5 +3,5 @@ import axios from "axios";
const BASE_URL = window.location.origin;
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 QueryString from "qs";
const server = window.location.origin + "/file_manager/fm_api.php?";
export function validateAction(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")) {
localStorage.setItem("lastUser", currentUser);
localStorage.setItem("activeWindow", "left");
localStorage.setItem("leftListPath", window.GLOBAL.ROOT_DIR);
localStorage.setItem("rightListPath", window.GLOBAL.ROOT_DIR);
localStorage.setItem("leftListPath", rootDir);
localStorage.setItem("rightListPath", rootDir);
return;
}
if (localStorage.getItem("activeWindow") === null || localStorage.getItem("leftListPath") === null || localStorage.getItem("rightListPath") === null) {
let path = history.location.search.substring(6).split('/');
localStorage.setItem("activeWindow", "left");
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 { resetAuthToken, setAuthToken } from 'src/utils/token';
import { resetPassword } from 'src/ControlPanelService/ResetPassword';
import { resetAuthToken, setAuthToken } from 'src/utils/token';
const LOGOUT_RESPONSE = 'logged_out';
const LOGOUT_AS_RESPONSE = 'logged_out_as';
export const login = (user, password) => dispatch => {
return new Promise((resolve, reject) => {
signIn(user, password).then((response) => {
const { error, session, token, panel, data, user } = response.data;
signIn({ user, password }).then((response) => {
const { error, session, token, panel, data, user, i18n } = response.data;
if (token) setAuthToken(token);
dispatch({
type: LOGIN,
value: {
token: data ? token : '',
token: token || '',
panel,
session,
i18n: i18n || {},
userName: user,
user: data,
error
},
});
resolve(response.data);
resolve(token);
}, (error) => {
reject(error);
});
@ -34,7 +36,6 @@ export const reset = ({ user = '', code = '', password = '', password_confirm =
return new Promise((resolve, reject) => {
resetPassword(user, code, password, password_confirm).then((response) => {
const { error, session, token, panel, user } = response.data;
if (token) setAuthToken(token);
dispatch({
type: RESET_PASSWORD,
@ -47,7 +48,7 @@ export const reset = ({ user = '', code = '', password = '', password_confirm =
error
},
});
resolve(response.data);
resolve(token);
}, (error) => {
reject(error);
});
@ -57,22 +58,23 @@ export const reset = ({ user = '', code = '', password = '', password_confirm =
export const loginAs = username => dispatch => {
return new Promise((resolve, reject) => {
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);
dispatch({
type: LOGIN,
value: {
token,
panel,
session,
userName: user,
user: data,
error,
},
i18n,
session,
panel,
token,
error
}
});
resolve(response.data);
resolve(token);
}, (error) => {
console.error(error);
reject();
@ -83,7 +85,7 @@ export const loginAs = username => dispatch => {
export const logout = () => (dispatch, getState) => {
return new Promise((resolve, reject) => {
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) {
resetAuthToken();
@ -91,27 +93,28 @@ export const logout = () => (dispatch, getState) => {
dispatch({
type: LOGOUT,
value: {
userName: user,
userName: '',
user: {},
token,
panel,
session,
error: ''
token: '',
panel: {},
session: {},
i18n: [],
error,
},
});
resolve();
} else if (logout_response === LOGOUT_AS_RESPONSE) {
const { token } = getState().session;
dispatch({
type: LOGGED_OUT_AS,
value: {
userName: user,
user: data,
userName,
user,
session,
panel,
token,
error: ''
token: '',
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) => {
checkAuth(token)
checkAuth()
.then(res => {
const { user, data, session, panel, error } = res.data;
const { user, data, session, panel, error, i18n, token } = res.data;
dispatch({
type: LOGIN,
type: CHECK_AUTH,
value: {
userName: user,
user: data,
i18n,
session,
panel,
token,
@ -144,7 +148,7 @@ export const setToken = (token) => (dispatch, getState) => {
}
});
resolve();
resolve(token);
})
.catch(err => {
reject();

View file

@ -1,5 +1,6 @@
export const LOGIN = 'LOGIN';
export const LOGOUT = 'LOGOUT';
export const LOGIN_AS = 'LOGIN_AS';
export const CHECK_AUTH = 'CHECK_AUTH';
export const LOGGED_OUT_AS = 'LOGGED_OUT_AS';
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 './Backup.scss';
import { Link } from 'react-router-dom';
import { useSelector } from 'react-redux';
const Backup = props => {
const { data } = props;
const { i18n } = window.GLOBAL.App;
const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token");
const toggleFav = (starred) => {
@ -24,7 +25,7 @@ const Backup = props => {
}
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 (

View file

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

View file

@ -1,16 +1,19 @@
import React from 'react';
import { useSelector } from 'react-redux';
import Container from '../../ControlPanel/Container/Container';
import './style.scss';
const Exclusion = ({ data, focused }) => {
const { i18n } = useSelector(state => state.session);
const renderExclusionItems = () => {
if (!Array.isArray(data.ITEMS)) {
for (let item in data.ITEMS) {
return <><b>{item}</b> &nbsp; {data.ITEMS[item]}<br /></>;
}
} 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 './RestoreSetting.scss';
import { useSelector } from 'react-redux';
export default function RestoreSetting({ data, checkItemFunc = () => { }, restoreSetting = () => { } }) {
const { i18n } = window.GLOBAL.App;
const { i18n } = useSelector(state => state.session);
const displayBackupDetailName = 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 {
.list-item {
.r-col {
@ -18,12 +29,12 @@
display: flex;
justify-content: center;
align-items: center;
color: #777;
color: $textColor;
padding: 10px 15px;
text-decoration: none;
&:hover {
background: rgb(145, 145, 145);
background: $whiteBackground;
color: white;
svg {
@ -33,7 +44,7 @@
}
svg {
color: #777;
color: $textColor;
}
}
@ -43,7 +54,13 @@
}
&: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';
export default function BackupRestoreSettings(props) {
const { i18n } = window.GLOBAL.App;
const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token");
const { controlPanelFocusedElement } = useSelector(state => state.controlPanelContent);
const { focusedElement } = useSelector(state => state.mainNavigation);
@ -153,6 +153,8 @@ export default function BackupRestoreSettings(props) {
setState({
...state,
totalAmount: result.data.totalAmount,
selection: [],
toggledAll: false,
loading: false
});
})
@ -165,7 +167,7 @@ export default function BackupRestoreSettings(props) {
acc.push({
type: cat,
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;
$addButtonBackground: #9FBF0C;
$addButtonBackgroundHover: #C0E60F;
$optionalButtonHover: #9FBF0C;
$optionalButtonActive: #c0e60f;
$deleteButtonColorHover: #FF3438;
$deleteButtonColorActive: #FF5F5F;
$optionalButtonHover: $primary;
$optionalButtonActive: $primaryLight;
$deleteButtonColorHover: #b00e5b;
$deleteButtonColorActive: #b11661;
$backButtonBackground: #DFDEDD;
$backButtonBackgroundHover: #999;
$transition: all 200ms cubic-bezier(0.4, 0.1, 0.5, 0.85);
$errorColor: #BE5ABF;
$successColor: $addButtonBackground;
.content .edit-template {
padding-bottom: 2rem;
@ -25,7 +32,7 @@ $successColor: $addButtonBackground;
div.error,
div.success {
width: fit-content;
width: fit-content !important;
span {
font-weight: bold;
@ -47,10 +54,10 @@ $successColor: $addButtonBackground;
}
span.ok-message {
color: $successColor;
color: $primary;
svg {
color: $successColor;
color: $primary;
}
}
}
@ -84,15 +91,15 @@ $successColor: $addButtonBackground;
form {
button,
a {
color:#2C9491;
color:$primary;
font-weight: bold;
&:hover {
color: #ff6701;
color: $secondaryLight;
}
&:active {
color: #F7D616;
color: $secondaryActive;
}
}
@ -139,14 +146,14 @@ $successColor: $addButtonBackground;
&:focus,
&:active {
outline: none;
border-color: #55C9C0;
border-color: $primaryActive;
box-shadow: unset;
}
}
textarea {
&:focus {
background: #D7F9FF;;
background: #D7F9FF;
}
}
@ -172,7 +179,7 @@ $successColor: $addButtonBackground;
&:focus,
&:active {
box-shadow: unset;
border-color: #55C9C0;
border-color: $primaryActive;
background: #D7F9FF;
}
}
@ -221,12 +228,17 @@ $successColor: $addButtonBackground;
}
.add {
color: white;
background: $addButtonBackground;
color: $activeButtonText;
background: $primary;
&:hover {
color: #555;
background: $addButtonBackgroundHover;
color: $hoverButtonText;
background: $primaryLight;
}
&:active {
color: $activeButtonText;
background: $primaryActive;
}
}
@ -258,7 +270,7 @@ $successColor: $addButtonBackground;
}
.status {
color: #9FBF0C;
color: $primary;
font-size: 11px;
letter-spacing: 1px;
text-transform: uppercase;

View file

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

View file

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

View file

@ -1,8 +1,9 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import React, { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
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({
hidePassword: false,
generatedPassword: ''

View file

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

View file

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

View file

@ -1,3 +1,5 @@
$secondary: #fcac04;
.hotkeys-list {
position: fixed;
bottom: 0;
@ -6,39 +8,36 @@
flex-direction: column;
transform: translateX(-45%);
width: 53%;
background: rgba(50, 50, 50, 0.9);
background: #222e44de;
font-size: 13px;
.head {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #333;
border-bottom: 1px solid $secondary;
.name {
text-transform: uppercase;
padding: 5px 0 5px 10px;
font-size: 12px;
font-weight: bold;
color: #ffcc00;
color: $secondary;
letter-spacing: 2px;
padding: 15px;
}
.close {
padding: 12px;
opacity: 1 !important;
svg {
color: #a1a1a1;
color: $secondary;
}
&:hover {
cursor: pointer;
background: black;
}
&:active {
background: #55c9c0;
background: #222e44;
}
}
}
@ -58,12 +57,12 @@
span.name {
margin-right: 15px;
color: #48F4EF;
color: $secondary;
font-weight: bold;
}
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 { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { useSelector } from 'react-redux';
import './ListItem.scss';
class ListItem extends Component {
state = {
starred: false
}
const ListItem = (props) => {
const { i18n } = useSelector(state => state.session);
const [state, setState] = useState({ starred: false });
UNSAFE_componentWillMount() {
this.setState({ starred: this.props.starred === 1 });
useEffect(() => {
if (props.hasOwnProperty('starred')) {
setState({ ...state, starred: Boolean(props.starred) });
}
}, [props.starred]);
UNSAFE_componentWillReceiveProps(nextProps) {
this.setState({
starred: nextProps.starred === 1
});
}
printDate = date => {
const printDate = date => {
if (date) {
let newDate = new Date(date);
let day = newDate.getDate();
@ -30,19 +26,18 @@ class ListItem extends Component {
}
}
toggleItem = () => {
this.props.checkItem();
const toggleItem = () => {
props.checkItem();
}
starItem = () => {
this.setState({ starred: !this.state.starred }, () => {
this.props.toggleFav(this.state.starred);
});
const starItem = () => {
setState({ ...state, starred: !state.starred });
props.toggleFav(!state.starred);
}
className = () => {
const { starred } = this.state;
const { checked, outdated, suspended, stopped, focused, sysInfo } = this.props;
const className = () => {
const { starred } = state;
const { checked, outdated, suspended, stopped, focused, sysInfo } = props;
let className = 'list-item';
if (checked) {
@ -76,25 +71,23 @@ class ListItem extends Component {
return className;
}
render() {
return (
<div className={this.className()} id={this.props.id}>
<div className={className()} id={props.id}>
<Container className="l-col w-14">
{this.printDate(this.props.date)}
{printDate(props.date)}
<div className="text-status">
<div className="checkbox"><input type="checkbox" onChange={(e) => this.toggleItem(e)} checked={this.props.checked} /></div>
{this.props.leftNameText}
<div className="checkbox"><input type="checkbox" onChange={toggleItem} checked={props.checked} /></div>
{props.leftNameText}
</div>
<div className="star">
<div className="checkbox"><input type="checkbox" onChange={(e) => this.toggleItem(e)} checked={this.props.checked} /></div>
<div onClick={this.starItem}><FontAwesomeIcon icon="star" /></div>
<div className="checkbox"><input type="checkbox" onChange={toggleItem} checked={props.checked} /></div>
<div onClick={starItem}><FontAwesomeIcon icon="star" /></div>
</div>
{this.props.suspended && <div className='suspended'>{window.GLOBAL.App.i18n.suspended}</div>}
{props.suspended && <div className='suspended'>{i18n.suspended}</div>}
</Container>
{this.props.children}
{props.children}
</div>
);
}
}
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 {
display: flex;
justify-content: flex-start;
@ -63,12 +71,12 @@
}
.list-item.starred {
border-left: 2px solid #ff6701;
border-left: 2px solid $primary;
.l-col div.star {
div > svg {
opacity: 1;
color: #ff6701;
color: $primary;
}
}
}
@ -112,7 +120,13 @@
}
.list-item.focused {
border-left: 2px solid #5edad0;
border-left: 2px solid $secondaryLight;
.l-col div.star {
div > svg {
color: $secondaryLight;
}
}
.actions {
opacity: 1;
@ -127,7 +141,7 @@
width: 25px;
height: 25px;
margin-left: 15px;
background: #69a298;
background: $secondaryLight;
color: white;
display: flex;
justify-content: center;

View file

@ -1,9 +1,10 @@
import React from 'react';
import { useSelector } from 'react-redux';
import './Modal.scss';
const { i18n } = window.GLOBAL.App;
const Modal = ({ show, text, onSave, onCancel, showSaveButton = true, showCancelButton = true }) => {
const { i18n } = useSelector(state => state.session);
return (
<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' }}>

View file

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

View file

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

View file

@ -4,10 +4,11 @@ import ListItem from '../ControlPanel/ListItem/ListItem';
import Container from '../ControlPanel/Container/Container';
import './CronJob.scss';
import { Link } from 'react-router-dom';
import { useSelector } from 'react-redux';
const CronJob = props => {
const { data } = props;
const { i18n } = window.GLOBAL.App;
const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token");
const toggleFav = (starred) => {
@ -24,11 +25,11 @@ const CronJob = props => {
const handleSuspend = () => {
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 = () => {
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 (

View file

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

View file

@ -6,10 +6,11 @@ import { Link, useHistory } from 'react-router-dom';
import QS from 'qs';
import './Generator.scss';
import { useSelector } from 'react-redux';
const Generator = props => {
const formElement = useRef(null);
const { i18n } = window.GLOBAL.App;
const { i18n } = useSelector(state => state.session);
const history = useHistory();
const [state, setState] = useState({
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 {
border: 1px solid #d9d9d9;
padding: 1rem 1.5rem;
@ -17,16 +28,16 @@
text-decoration: none;
&:hover {
color: #ff6701;
color: $secondaryLight;
}
&:active {
color: #55C9C0;
color: $primaryActive;
}
}
a.active {
color: #ff6701;
color: $secondaryActive;
}
}
@ -65,7 +76,7 @@
&:focus,
&:active {
outline: none;
border-color: #55C9C0;
border-color: $primaryActive;
box-shadow: unset;
}
}
@ -78,20 +89,20 @@
.form-actions {
button {
background: #55C9C0;
background: $primary;
color: white;
border-radius: 3px;
padding: .35rem 1.1rem;
font-size: 14px;
&:hover {
color: #555;
background: #5BD8CF;
color: $hoverButtonText;
background: $primaryLight;
}
&:active {
color: white;
background: #D1D70D;
color: $activeButtonText;
background: $primaryActive;
}
}
}

View file

@ -1,8 +1,10 @@
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() {
const { i18n } = window.GLOBAL.App;
const { i18n } = useSelector(state => state.session);
const { dailyMinutesOptions, hoursOptions, dateOptions } = generatorOptions(i18n);
const renderDate = () => {
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 { dailyMinutesOptions, hoursOptions } from '../../../../ControlPanelService/GeneratorOptions';
import { useSelector } from 'react-redux';
import { generatorOptions } from '../../../../ControlPanelService/GeneratorOptions';
export default function FourthTabSelects() {
const { i18n } = window.GLOBAL.App;
const { i18n } = useSelector(state => state.session);
const { dailyMinutesOptions, hoursOptions } = generatorOptions(i18n);
const renderHours = () => {
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 { hourlyMinutesOptions } from '../../../../ControlPanelService/GeneratorOptions';
import { useSelector } from 'react-redux';
import { generatorOptions } from '../../../../ControlPanelService/GeneratorOptions';
export default function SecondTabSelects() {
const { i18n } = window.GLOBAL.App;
const { i18n } = useSelector(state => state.session);
const { hourlyMinutesOptions } = generatorOptions(i18n);
const renderOptions = () => {
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 { dailyMinutesOptions, hoursOptions } from '../../../../ControlPanelService/GeneratorOptions';
import { useSelector } from 'react-redux';
import { generatorOptions } from '../../../../ControlPanelService/GeneratorOptions';
export default function ThirdTabSelects() {
const { i18n } = window.GLOBAL.App;
const { i18n } = useSelector(state => state.session);
const { dailyMinutesOptions, hoursOptions } = generatorOptions(i18n);
const renderHours = () => {
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 { daysRunCommandsOptions, hoursRunCommandsOptions, minutesRunCommandsOptions, monthlyRunCommandOptions, weeklyRunCommandOptions } from '../../../../ControlPanelService/GeneratorOptions';
import { useSelector } from 'react-redux';
import { generatorOptions } from '../../../../ControlPanelService/GeneratorOptions';
const RunCommandSelect = props => {
const { i18n } = window.GLOBAL.App;
const { i18n } = useSelector(state => state.session);
const [state, setState] = useState({
activeTab: ''
@ -13,6 +14,8 @@ const RunCommandSelect = props => {
}, [props]);
const renderOptions = () => {
const { daysRunCommandsOptions, hoursRunCommandsOptions, minutesRunCommandsOptions, monthlyRunCommandOptions, weeklyRunCommandOptions } = generatorOptions(i18n);
switch (state.activeTab) {
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>);

View file

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

View file

@ -3,9 +3,10 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Container from '../ControlPanel/Container/Container';
import ListItem from '../ControlPanel/ListItem/ListItem';
import { Link } from 'react-router-dom';
import { useSelector } from 'react-redux';
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 toggleFav = (starred) => {
@ -21,7 +22,7 @@ export default function DnsRecord({ data, domain, handleModal, ...props }) {
}
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 (

View file

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

View file

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

View file

@ -3,10 +3,11 @@ import ListItem from '../ControlPanel/ListItem/ListItem';
import Container from '../ControlPanel/Container/Container';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Link } from 'react-router-dom';
import { useSelector } from 'react-redux';
const Database = props => {
const { data } = props;
const { i18n } = window.GLOBAL.App;
const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token");
const toggleFav = (starred) => {
@ -23,11 +24,11 @@ const Database = props => {
const handleSuspend = () => {
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 = () => {
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 (

View file

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

View file

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

View file

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

View file

@ -4,10 +4,11 @@ import Container from '../ControlPanel/Container/Container';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import './DomainNameSystem.scss';
import { Link } from 'react-router-dom';
import { useSelector } from 'react-redux';
const DomainNameSystem = props => {
const { data } = props;
const { i18n } = window.GLOBAL.App;
const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token");
const toggleFav = (starred) => {
@ -24,11 +25,11 @@ const DomainNameSystem = props => {
const handleSuspend = () => {
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 = () => {
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 (

View file

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

View file

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

View file

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

View file

@ -2,9 +2,10 @@ import React from 'react';
import ListItem from 'src/components/ControlPanel/ListItem/ListItem';
import Container from 'src/components/ControlPanel/Container/Container';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { useSelector } from 'react-redux';
const Ban = ({ data, ...props }) => {
const { i18n } = window.GLOBAL.App;
const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token");
const checkItem = () => {
@ -12,7 +13,7 @@ const Ban = ({ data, ...props }) => {
}
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 (

View file

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

View file

@ -4,10 +4,11 @@ import Container from '../ControlPanel/Container/Container';
import ListItem from '../ControlPanel/ListItem/ListItem';
import { Link } from 'react-router-dom';
import './Firewall.scss';
import { useSelector } from 'react-redux';
const Firewall = ({ data, ...props }) => {
const token = localStorage.getItem("token");
const { i18n } = window.GLOBAL.App;
const { i18n } = useSelector(state => state.session);
const toggleFav = (starred) => {
if (starred) {
@ -23,11 +24,11 @@ const Firewall = ({ data, ...props }) => {
const handleSuspend = () => {
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 = () => {
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 (

View file

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

View file

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

View file

@ -1,72 +1,78 @@
.panel {
margin: 0;
position: absolute;
right: 30%;
$secondary: #fcac04;
.hotkeys-list {
position: fixed;
bottom: 0;
width: 40%;
font-size: 15px;
background: #38383891;
right: 0;
display: flex;
flex-direction: column;
transform: translateX(-45%);
width: 53%;
background: #222e44de;
font-size: 13px;
.panel-heading {
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 {
.head {
display: flex;
justify-content: space-between;
background: rgba(56,56,56,0.4);
align-items: center;
border-bottom: 1px solid $secondary;
ul {
width: 50%;
color: white;
li {
list-style-type: none;
margin-bottom: 10px;
.shortcut {
color: #48F4EF;
}
}
}
}
.name {
text-transform: uppercase;
padding: 5px 0 5px 10px;
font-size: 12px;
font-weight: bold;
color: $secondary;
letter-spacing: 2px;
padding: 15px;
}
.hotkeys-button {
color: white;
background: rgb(170, 166, 166);
position: absolute;
right: 5px;
bottom: 5px;
width: 40px;
height: 38px;
text-align: center;
border-radius: 30px;
cursor: pointer;
.close {
padding: 12px;
opacity: 1 !important;
svg {
margin-top: 7px;
color: $secondary;
}
&: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 token = localStorage.getItem("token");
const { i18n } = window.GLOBAL.App;
const { i18n } = useSelector(state => state.session);
const session = useSelector(state => state.session);
const dispatch = useDispatch();
const history = useHistory();

View file

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

View file

@ -4,10 +4,11 @@ import Container from '../ControlPanel/Container/Container';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import './InternetProtocol.scss';
import { Link } from 'react-router-dom';
import { useSelector } from 'react-redux';
const InternetProtocol = props => {
const { data } = props;
const { i18n } = window.GLOBAL.App;
const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token");
const toggleFav = (starred) => {
@ -23,7 +24,7 @@ const InternetProtocol = props => {
}
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 (

View file

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

View file

@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faJs, faCss3, faPhp, faHtml5, faSass } from '@fortawesome/free-brands-svg-icons';
import './Row.scss';
import { connect } from 'react-redux';
class Row extends Component {
static propTypes = {
@ -121,9 +122,8 @@ class Row extends Component {
let date = new Date(fDate),
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
appMonths = window.GLOBAL.App.i18n,
getDay = date.getDate(),
getMonth = appMonths[months[date.getMonth()]];
getMonth = this.props.session.i18n[months[date.getMonth()]];
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 {
width: 25px;
vertical-align: top;
@ -126,7 +137,7 @@
}
.list .list-container ul li .fOwner {
color: #81A64F;
color: #896417;
font-style: italic;
width: 50px;
font-size: 12px;
@ -134,7 +145,7 @@
}
.value {
color: #44a8b3;
color: $primary;
}
.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 {
display: flex;
justify-content: center;
@ -45,11 +56,15 @@
display: flex;
justify-content: center;
align-items: center;
width: 30%;
width: 35%;
img {
width: 110%;
}
}
.c2 {
width: 70%;
width: 65%;
margin-left: 3.5rem;
.forgot-password {
@ -60,8 +75,8 @@
}
button[type="submit"] {
background-color: #9FBF0C;
border: 1px solid #9FBF0C;
background-color: $primary;
border: 1px solid $primary;
padding: 1px 16px 3px;
font-size: 13px;;
width: 100px;
@ -70,9 +85,15 @@
border-radius: 3px;
&:hover {
border: 1px solid #C0E60F;
background-color: #C0E60F;
color: #555;
color: $primary;
border: 1px solid $primaryLight;
background-color: $primaryLight;
}
&:active {
color: #fafafa;
border: 1px solid $primary;
background-color: $primary;
}
.disabled {

View file

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

View file

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

View file

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

View file

@ -4,10 +4,11 @@ import Container from '../ControlPanel/Container/Container';
import ListItem from '../ControlPanel/ListItem/ListItem';
import { Link } from 'react-router-dom';
import './Mail.scss';
import { useSelector } from 'react-redux';
const Mail = props => {
const { data } = props;
const { i18n } = window.GLOBAL.App;
const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token");
const printStat = (stat, text) => {
if (text === 'no') {
@ -31,11 +32,11 @@ const Mail = props => {
const handleSuspend = () => {
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 = () => {
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 (

View file

@ -13,13 +13,13 @@ import MailInfoBlock from '../MailInfoBlock/MailInfoBlock';
import Toolbar from '../../MainNav/Toolbar/Toolbar';
import { useHistory } from 'react-router-dom';
import Spinner from '../../Spinner/Spinner';
import { useDispatch } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import './AddMailAccount.scss';
import { Helmet } from 'react-helmet';
export default function AddMailAccount(props) {
const { i18n } = window.GLOBAL.App;
const { i18n } = useSelector(state => state.session);
const dispatch = useDispatch();
const token = localStorage.getItem("token");
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 TextArea from 'src/components/ControlPanel/AddItemLayout/Form/TextArea/TextArea';
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 { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import MailInfoBlock from '../MailInfoBlock/MailInfoBlock';
import Toolbar from '../../MainNav/Toolbar/Toolbar';
import { useHistory } from 'react-router-dom';
import Spinner from '../../Spinner/Spinner';
import { useDispatch } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import { Helmet } from 'react-helmet';
export default function EditMailAccount(props) {
const [autoreplyChecked, setAutoreplyChecked] = useState(false);
const token = localStorage.getItem("token");
const { i18n } = window.GLOBAL.App;
const { i18n } = useSelector(state => state.session);
const dispatch = useDispatch();
const history = useHistory();
const [state, setState] = useState({

View file

@ -3,10 +3,11 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Container from '../ControlPanel/Container/Container';
import ListItem from '../ControlPanel/ListItem/ListItem';
import { Link } from 'react-router-dom';
import { useSelector } from 'react-redux';
export default function MailAccount(props) {
const { data, domain } = props;
const { i18n } = window.GLOBAL.App;
const { i18n } = useSelector(state => state.session);
const token = localStorage.getItem("token");
const printStat = (stat, text) => {
if (text === 'no') {
@ -30,11 +31,11 @@ export default function MailAccount(props) {
const handleSuspend = () => {
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 = () => {
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 (

View file

@ -5,7 +5,7 @@ import { mailInfoBlockSelectOptions } from 'src/ControlPanelService/Mail';
import './MailInfoBlock.scss';
export default function MailInfoBlock({ webMail, hostName, domain, password }) {
const { i18n } = window.GLOBAL.App;
const { i18n } = useSelector(state => state.session);
const [selectedOption, setSelectedOption] = useState('');
const { userName } = useSelector(state => state.session);
const [state, setState] = useState({
@ -40,7 +40,8 @@ export default function MailInfoBlock({ webMail, hostName, domain, password }) {
}, [selectedOption]);
const renderSelectOptions = () => {
return mailInfoBlockSelectOptions.map(option =>
const options = mailInfoBlockSelectOptions(i18n);
return options.map(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 Panel from '../MainNav/Panel/Panel';
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({
menuHeight: 135,
tabs: [],
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 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 => {
let isSearchInputFocused = document.querySelector('input:focus') || document.querySelector('textarea:focus') || document.querySelector('textarea:focus');
let currentActiveTabPositionInArray;
@ -32,9 +49,9 @@ const MainNav = props => {
if (!focusedElement) {
dispatch(addFocusedElement(activeElement));
currentActiveTabPositionInArray = menuTabs.indexOf(activeElement);
currentActiveTabPositionInArray = state.tabs.indexOf(activeElement);
} else {
currentActiveTabPositionInArray = menuTabs.indexOf(focusedElement);
currentActiveTabPositionInArray = state.tabs.indexOf(focusedElement);
}
}
@ -43,14 +60,14 @@ const MainNav = props => {
}
if (event.keyCode === 37) {
let newFocusedMenuTab = handleLeftArrowKey(menuTabs, currentActiveTabPositionInArray);
let newFocusedMenuTab = handleLeftArrowKey(state.tabs, currentActiveTabPositionInArray);
dispatch(addFocusedElement(newFocusedMenuTab));
} else if (event.keyCode === 39) {
let newFocusedMenuTab = handleRightArrowKey(menuTabs, currentActiveTabPositionInArray);
let newFocusedMenuTab = handleRightArrowKey(state.tabs, currentActiveTabPositionInArray);
dispatch(addFocusedElement(newFocusedMenuTab));
} else if (event.keyCode === 13) {
if (!controlPanelFocusedElement && focusedElement) {
props.history.push({ pathname: focusedElement });
if (!controlPanelFocusedElement && focusedElement && (focusedElement !== activeElement)) {
history.push({ pathname: focusedElement });
dispatch(addActiveElement(focusedElement));
dispatch(removeFocusedElement());
}
@ -74,7 +91,7 @@ const MainNav = props => {
}, [activeElement]);
useEffect(() => {
dispatch(addActiveElement(props.history.location.pathname));
dispatch(addActiveElement(history.location.pathname));
}, []);
const handleLeftArrowKey = (array, indexInArray) => {
@ -149,8 +166,14 @@ const MainNav = props => {
return (
<div className="main-nav">
{
loading
? <Spinner />
: (<>
<Panel showTopNav={showTopNav} visibleNav={state.showTopNav} />
{topNavigation()}
</>)
}
</div>
);
}

View file

@ -1,3 +1,5 @@
$secondaryLight: #f8b014;
.mobile-top-nav-wrapper.hide {
opacity: 0;
}
@ -58,7 +60,7 @@
padding: 2px;
&: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 { getAppNotifications, deleteNotification } from '../../../../ControlPanelService/Notifications';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { getAppNotifications, deleteNotification } from 'src/ControlPanelService/Notifications';
import { addNotifications } from 'src/actions/Notification/notificationActions';
import Bell from './Bell';
import BellUnread from './BellUnread';
import { useDispatch, useSelector } from 'react-redux';
import './Notifications.scss';
const Notifications = () => {
const [notifications, setNotifications] = useState([]);
const [loading, setLoading] = useState(true);
const { i18n } = useSelector(state => state.session);
const { notifications } = useSelector(state => state.notifications);
const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
useEffect(() => {
fetchData();
}, []);
const fetchData = () => {
setLoading(true);
getAppNotifications()
.then(res => {
if (res.data) {
const result = [];
for (let notification in res.data) {
result.push(res.data[notification]);
for (let notification in res.data.result) {
result.push(res.data.result[notification]);
}
setNotifications(result);
dispatch(addNotifications(result));
setLoading(false);
})
.catch(err => {
console.error(err);
setLoading(false);
}
})
.catch(err => console.error(err))
}
const removeNotification = id => {
@ -40,20 +47,20 @@ const Notifications = () => {
if (notifications.length) {
return notifications.map(item => {
return (
<React.Fragment>
<>
<div className="dropdown-item">
<span className="title"><b>{item.TOPIC}</b></span>
<span className="delete-notification" onClick={() => removeNotification(item.ID)}></span>
</div>
<div dangerouslySetInnerHTML={{ __html: item.NOTICE }}></div>
<div className="dropdown-divider"></div>
</React.Fragment>
</>
);
});
} else {
return (
<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>
);
}
@ -63,7 +70,11 @@ const Notifications = () => {
<div className="btn-group">
<button type="button" className="btn btn-danger dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<div className="bell">
<FontAwesomeIcon icon="bell" />
{
notifications.length
? <BellUnread />
: <Bell />
}
</div>
</button>
<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 {
div {
width: auto;
@ -38,7 +52,10 @@
max-height: 75vh;
overflow: auto;
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 {
cursor: default;
@ -65,18 +82,18 @@
width: 100%;
padding: 10px 0 0 10px;
text-align: left;
color: #C4DA5E;
color: $secondary;
}
span.delete-notification {
width: 10px;
height: 10px;
background: #C4DA5E;
background: $secondary;
border-radius: 50%;
cursor: pointer;
&:hover {
border: 2px solid #C4DA5E;
border: 2px solid $secondaryLight;
background: transparent;
}
}
@ -94,10 +111,10 @@
a {
display: contents;
color: #5ABDB5;
color: $notifications;
&:hover {
color: #2CA99B;
color: $notificationsLight;
}
}
}

View file

@ -9,7 +9,7 @@ import { Link, useHistory } from "react-router-dom";
import './Panel.scss';
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 { activeElement, focusedElement } = useSelector(state => state.mainNavigation);
const dispatch = useDispatch();
@ -29,7 +29,7 @@ const Panel = props => {
}
}
const className = activeName => {
const className = (activeName, extraClass = '') => {
let className = 'top-link';
if (activeName === activeElement) {
@ -40,12 +40,14 @@ const Panel = props => {
className += ' focus';
}
return className;
return className + ` ${extraClass}`;
}
const handleState = (tab, event) => {
event.preventDefault();
history.push(tab);
if (`${window.location.pathname}${window.location.search}` === tab) {
return event.preventDefault();
}
dispatch(addActiveElement(tab));
}
@ -67,45 +69,65 @@ const Panel = props => {
<div className="panel-wrapper">
{loading && <Spinner />}
<div className="top-panel">
<div className={`top-panel ${user ? 'long-profile' : ''}`}>
<div className="container left-menu">
<div className="logo">
<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>
</div>
{userName === 'admin' && (<>
<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 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 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 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 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>
{userName === 'admin' && (<>
<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>
{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>}
{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>}
{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>}
{userName === 'admin' && (
<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 className="container profile-menu">
<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>
</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 {
display: none;
}
@ -10,7 +21,7 @@
width: 100%;
text-align: center;
color: white;
background: #111;
background: #222e44;
height: 34px;
align-items: center;
padding: 0 13%;
@ -22,13 +33,10 @@
width: 80%;
height: 100%;
.logo .logo-img {
background-image: url("/images/sprite.png?1446554103");
background-position: -117px -57px;
background-repeat: no-repeat;
height: 22px;
width: 70px;
margin-left: -2px;
.logo div {
img {
width: 82%;
}
&:hover {
background-color: transparent;
@ -65,7 +73,7 @@
background: white;
a, button {
color: #f79b44;
color: $secondary;
font-weight: bold;
&:hover {
@ -73,13 +81,13 @@
}
&:active {
background: #ff6701;
background: $secondaryActive;
color: white;
}
}
&:hover {
background: #f79b44;
background: $secondaryLight;
}
}
}
@ -91,9 +99,11 @@
div {
width: 7rem;
height: 100%;
transform: translateX(-5px);
padding-right: 5px;
&:hover {
background: #f79b44;
background: $secondaryLight;
}
}
@ -113,8 +123,7 @@
.top-link.focus {
a, button {
color: #5edad0;
text-decoration: underline;
color: $secondaryActive;
}
}
}
@ -129,20 +138,21 @@
div.bell {
width: auto;
color: #C0E60E;
color: $secondary;
padding: 3px 0;
svg {
border-radius: 30px;
width: 25px;
height: 25px;
padding: 5px;
width: 100%;
height: 100%;
padding: 3px;
&:hover {
background: rgba(255, 255, 255, 0.4);
background: #79522294;
}
&:hover {
background: #c0e6198a;
&:active {
background: #866032;
}
}
}
@ -152,11 +162,11 @@
font-weight: 700;
&:hover {
color: #ffd62e;
color: $secondaryLight;
}
&:active {
color: #f79b44;
color: $secondaryActive;
}
}
@ -167,11 +177,40 @@
font-weight: 100;
&:hover {
color: #C0E60E;
color: $secondaryLight;
}
&: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 { addActiveElement } from '../../../actions/MainNavigation/mainNavigationActions';
import { useSelector, useDispatch } from "react-redux";
import { useHistory } from "react-router-dom";
import { Link } from "react-router-dom";
import './Menu.scss';
@ -26,12 +26,9 @@ const style = ({ menuHeight, mobile }) => {
}
const Menu = props => {
const session = useSelector(state => state.session);
const { activeElement, focusedElement } = useSelector(state => state.mainNavigation);
const { user } = useSelector(state => state.session);
const { i18n } = window.GLOBAL.App;
const { user, i18n, session: { look } } = useSelector(state => state.session);
const dispatch = useDispatch();
const history = useHistory();
useEffect(() => {
if (user.LANGUAGE) {
@ -40,8 +37,10 @@ const Menu = props => {
}, [user]);
const handleState = (tab, event) => {
event.preventDefault();
history.push(tab);
if (`${window.location.pathname}${window.location.search}` === tab) {
return event.preventDefault();
}
dispatch(addActiveElement(tab));
}
@ -49,73 +48,96 @@ const Menu = props => {
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 (
<div className="menu-wrapper">
<div className={className(props.menuHeight)} style={{ height: style(props) }}>
<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>
<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.spnd}:</span> <span>{user.SUSPENDED_USERS}</span></div>
</>)
}
</div>
</button>
</Link>
</div>
<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>
<div className="stats">
<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.spnd}:</span> <span>{user.SUSPENDED_WEB}</span></div>
</div>
</button>
</Link>
</div>
<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>
<div className="stats">
<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.spnd}:</span> <span>{user.SUSPENDED_DNS}</span></div>
</div>
</button>
</Link>
</div>
<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>
<div className="stats">
<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.spnd}:</span> <span>{user.SUSPENDED_MAIL}</span></div>
</div>
</button>
</Link>
</div>
<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>
<div className="stats">
<div><span>{i18n.databases}:</span> <span>{user.U_DATABASES}</span></div>
<div><span>{i18n.spnd}:</span> <span>{user.SUSPENDED_DB}</span></div>
</div>
</button>
</Link>
</div>
<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>
<div className="stats">
<div><span>{i18n.jobs}:</span> <span>{user.U_CRON_JOBS}</span></div>
<div><span>{i18n.spnd}:</span> <span>{user.SUSPENDED_CRON}</span></div>
</div>
</button>
</Link>
</div>
<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>
<div className="stats">
<div><span>{i18n.backups}:</span> <span>{user.U_BACKUPS}</span></div>
</div>
</button>
</Link>
</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 {
position: fixed;
width: 100%;
@ -71,10 +82,10 @@
&:hover {
cursor: pointer;
border-bottom: 3px solid #ff6701;
border-bottom: 3px solid $secondaryLight;
h3 {
color: #ff6701;
color: $secondary;
}
.stats {
@ -83,10 +94,10 @@
}
&:active {
border-color: #f72b44;
border-color: $secondaryActive;
h3 {
color: #f72b44;
color: $secondary;
}
}
@ -102,20 +113,20 @@
}
.l-active {
border-bottom: 3px solid #ff6701;
border-bottom: 3px solid $primary;
h3 {
color: #ff6701;
color: $primary;
font-size: 18px;
margin-bottom: 25px;
}
}
.stat.focus {
border-bottom: 3px solid #5edad0 !important;
border-bottom: 3px solid $secondaryLight !important;
a, h3 {
color: #36B3A9 !important;
color: $secondaryLight !important;
}
}
}
@ -203,7 +214,7 @@
}
.stat.l-active {
background: #ff67010d;
background: #fdac020d;
}
}
}

View file

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

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