const assetsPath = "../assets/";
const api = new APIClient();
const toastContainer = $('.toast-container');
let renderTableCell = (function () {
function renderTitle(title) {
return title.replace('_', ' ').replace(/(\b\w)/g, char => char.toUpperCase())
.replace('Ip', 'IP ')
.replace('Dns', 'DNS ')
.replace('Mtu', 'MTU');
}
function renderSwitch(data, disable=false) {
let enabled = data == true;
let active = enabled ? ' active' : '';
let disabled = disable ? 'disabled' : '';
return ' ';
}
function renderBadge(data) {
return '' + data + '';
}
return {
renderTitle,
renderSwitch,
renderBadge
}
})();
$(function() {
'use strict';
var dt_basic_table = $('.datatables-basic');
// DataTable with buttons
// --------------------------------------------------------------------
if (dt_basic_table.length) {
try {
var dt_basic = dt_basic_table.DataTable({
ajax: function(data, callback, settings) {
settings.sAjaxDataProp = '';
api.servers.getAll()
.then(function(response) {
callback(response);
})
.catch(function(error) {
console.error(error);
callback([]);
});
},
columns: [
{ data: '' },
{ data: 'isEnabled' },
{ data: 'name' },
{ data: 'ipAddress' },
{ data: 'listenPort'},
{ data: 'ipPool' },
{ data: 'dnsAddress' },
{ data: '' }
],
columnDefs: [
{
// For Responsive
targets: 0,
className: 'dtr-control',
orderable: false,
responsivePriority: 2,
searchable: false,
render: function(data, type, full, meta) {
return '';
}
},
{
// Enablity Switch
targets: 1,
orderable: false,
searchable: false,
render: function(data, type, full, meta) {
return renderTableCell.renderSwitch(data);
}
},
{
// Name and Online status
targets: 2,
responsivePriority: 1
},
{
// IP Address
responsivePriority: 3,
targets: 3
},
{
// Port
responsivePriority: 4,
targets: 4
},
{
// IP Pool
targets: 5
},
{
// DNS
targets: 6,
render: function(data, type, full, meta) {
return renderTableCell.renderBadge(data);
}
},
{
// Actions
targets: -1, // Last
title: 'Actions',
orderable: false,
searchable: false,
className: 'action-buttons',
render: function(data, type, full, meta) {
return (
'' +
'' +
''
);
}
}
],
order: [[2, 'desc']],
dom: '<"card-header"<"dt-action-buttons text-end"B>><"d-flex justify-content-between align-items-center row"<"col-sm-12 col-md-6"l><"col-sm-12 col-md-6"f>>t<"d-flex justify-content-between row"<"col-sm-12 col-md-6"i><"col-sm-12 col-md-6"p>>',
displayLength: 10,
lengthMenu: [5, 10, 25, 50, 75, 100],
buttons: {
dom: {
button: {
tag: 'button',
className: 'btn'
}
},
buttons: [
{
extend: 'collection',
className: 'btn-primary dropdown-toggle me-2',
text: 'Export',
buttons: [
{
extend: 'copy',
text: 'Copy',
className: 'dropdown-item'
},
{
extend: 'csv',
text: 'CSV',
className: 'dropdown-item',
exportOptions: { columns: [3, 4, 5, 6, 7] }
},
{
text: 'JSON',
className: 'dropdown-item',
action: function ( e, dt, button, config ) {
let array = [];
let data = dt.rows().data();
$.each(data, function(i) {
array.push(data[i]);
});
$.fn.dataTable.fileSave(
new Blob([JSON.stringify(array, null, 2)]),
'wg-servers.json'
);
}
},
{
text: 'Backup',
className: 'dropdown-item'
}
]
},
{
text: ' Add New Server',
className: 'btn-success create-new',
attr: {
"data-bs-toggle": "offcanvas",
"data-bs-target": "#offcanvasAddServer"
}
}
]
},
responsive: {
details: {
display: $.fn.dataTable.Responsive.display.modal({
header: function(row) {
var data = row.data();
return 'Details of ' + data['name'];
}
}),
type: 'column',
renderer: function(api, rowIdx, columns) {
var data = $.map(columns, function(col, i) {
return col.title !== '' // ? Do not show row in modal popup if title is blank (for check box)
? '
' +
'' +
col.title +
':' +
' | ' +
'' +
col.data +
' | ' +
'
'
: '';
}).join('');
let output = data ? $('').append(data) : false;
return output;
}
}
},
language: {
"emptyTable": "No servers found"
},
initComplete: function(settings, json) {
const result = Object.values(json).reduce(
(acc, currentItem) => {
acc.totalItems++;
if (currentItem.isEnabled) {
acc.activeItems++;
}
if (currentItem.running) {
acc.runningItems++;
} else {
acc.notRunningItems++;
}
return acc;
},
{ totalItems: 0, activeItems: 0, runningItems: 0, notRunningItems: 0 }
);
const totalItems = result.totalItems;
const activeItems = result.activeItems;
const runningItems = result.runningItems;
const notRunningItems = result.notRunningItems;
$('#servers-total').text(totalItems);
$('#servers-active').text(activeItems);
$('#servers-running').text(runningItems);
$('#servers-not-running').text(notRunningItems);
dt_basic.on('click', 'a.item-details', function (e) {
let tr = e.target.closest('tr');
let row = dt_basic.row(tr)
let rowData = row.data();
var data = $.map(rowData, function(value, key) {
if (key !== '') // ? Do not show row in modal popup if title is blank (for check box)
{
let tdValue = '';
switch (key) {
case 'enabled':
tdValue = renderTableCell.renderSwitch(value, true);
break;
case 'dns_address':
tdValue = renderTableCell.renderBadge(value);
break;
default:
tdValue = value;
break;
}
return '' +
'' +
renderTableCell.renderTitle(key) +
' | ' +
'' +
tdValue +
' | ' +
'
'
}
else {
return '';
}
}).join('');
let body = data ? $('').append(data) : false;
$('#DetailsModal .modal-body').html(body);
$('#DetailsModal .modal-title').html('Details of ' + row.data()["name"]);
const detailsModal = new bootstrap.Modal('#DetailsModal');
detailsModal.show();
});
dt_basic.on('click', 'a.item-edit', function (e) {
let tr = e.target.closest('tr');
let row = dt_basic.row(tr)
let rowData = row.data();
$.map(rowData, function(value, key) {
key = key.replace('_', '-');
let field = $('#offcanvasEditServer #edit-' + key);
if (key == 'inheritDNS' || key == 'useIPPool')
console.log(`${key}\t => ${value}`);
switch (key) {
case 'ipAddress':
let ipAddress = value.split('/')[0];
let ipRange = value.split('/')[1];
$('#offcanvasEditServer #edit-ip-address').val(ipAddress);
$('#offcanvasEditServer #edit-ip-cidr').val(ipRange);
break;
case 'inheritDNS':
$('#offcanvasEditServer #edit-dns-dynamic').prop('checked', value);
$('#offcanvasEditServer #edit-dns-server').prop('disabled', value);
break;
case 'dnsAddress':
$('#offcanvasEditServer #edit-dns-server').val(value);
break;
case 'useIPPool':
$('#offcanvasEditServer #edit-static-addressing').prop('checked', !value);
$('#offcanvasEditServer #edit-pool').prop('disabled', !value);
break;
case 'ipPool':
$(`#offcanvasEditServer #edit-pool option[data-value="${value}"]`).prop("selected", true);
break;
case 'listenPort':
$('#offcanvasEditServer #edit-port').val(value);
break;
case 'privateKey':
$('#offcanvasEditServer #edit-private-key').val(value);
break;
case 'publicKey':
$('#offcanvasEditServer #edit-public-key').val(value);
break;
default:
field.val(value);
break;
}
});
});
dt_basic.on('click', 'a.item-delete', function (e) {
let tr = e.target.closest('tr');
let row = dt_basic.row(tr)
let rowData = row.data();
let serverId = rowData['id'];
$('#removeForm input[name="ID"]').val(serverId);
});
dt_basic.on('click', 'button.item-activation', function (e) {
let tr = e.target.closest('tr');
let row = dt_basic.row(tr)
let rowData = row.data();
let serverId = rowData['id'];
let enabled = rowData['isEnabled'];
console.log(`${serverId}: ${enabled}`);
api.servers.activate(serverId, {enabled: enabled}).then(data => {
const toastMSG = new toastMessage("Activate Server", data.body, data.title, data.background);
const toastElement = toastMSG.getElement();
toastContainer.append(toastElement);
bootstrap.Toast.getOrCreateInstance(toastElement).show();
}).catch(err => {
console.error(err);
}).finally(() => {
dt_basic.ajax.reload();
});
});
}
});
}
catch(err) {
console.log(err);
alert(err);
}
}
// Load IP Pools
api.pools.getAll().then(pools => {
pools.forEach(pool => {
$("#add-pool").append(``);
$("#edit-pool").append(``);
});
});
// Toggle dynamic inputs
toggleDynamicInput($('#add-dns-dynamic'), $('#add-dns-server'));
toggleDynamicInput($('#edit-dns-dynamic'), $('#edit-dns-server'));
toggleDynamicInput($('#add-static-addressing'), $('#add-pool'));
toggleDynamicInput($('#edit-static-addressing'), $('#edit-pool'));
// FormValidation
// Add server form
$('#addServerForm').on('submit', e => {
let data = new FormData(e.target);
api.servers.create({
name: data.get('Name'),
port: data.get('Port'),
mtu: data.get('MTU'),
privateKey: data.get('PrivateKey'),
ipAddress: `${data.get('IPAddress')}/${data.get('IPCidr')}`,
useIPPool: data.get('UseIPPool') != 'on',
ipPoolId: data.get('IPPoolId'),
inheritDNS: data.get('InheritDNS') == 'on',
dnsAddress: data.get('DNSAddress'),
enabled: true
}).then(data => {
const toastMSG = new toastMessage("Create Server", data.body, data.title, data.background);
const toastElement = toastMSG.getElement();
toastContainer.append(toastElement);
bootstrap.Toast.getOrCreateInstance(toastElement).show();
}).catch(err => {
console.error(err);
}).finally(() => {
dt_basic.ajax.reload();
});
});
// Edit server form
$('#editServerForm').on('submit', e => {
let data = new FormData(e.target);
api.servers.update(data.get('ID'), {
name: data.get('Name') || null,
port: data.get('Port'),
mtu: data.get('MTU'),
privateKey: data.get('PrivateKey') || null,
ipAddress: `${data.get('IPAddress')}/${data.get('IPCidr')}` || null,
useIPPool: data.get('UseIPPool') != 'on',
ipPoolId: data.get('IPPoolId'),
inheritDNS: data.get('InheritDNS') == 'on',
dnsAddress: data.get('DNSAddress') || null
}).then(data => {
const toastMSG = new toastMessage("Update Server", data.body, data.title, data.background);
const toastElement = toastMSG.getElement();
toastContainer.append(toastElement);
bootstrap.Toast.getOrCreateInstance(toastElement).show();
}).catch(err => {
console.error(err);
}).finally(() => {
dt_basic.ajax.reload();
});
});
// Delete server form
$('#removeForm').on('submit', e => {
let data = new FormData(e.target);
api.servers.delete(data.get('ID')).then(data => {
const toastMSG = new toastMessage("Delete Server", data.body, data.title, data.background);
const toastElement = toastMSG.getElement();
toastContainer.append(toastElement);
bootstrap.Toast.getOrCreateInstance(toastElement).show();
}).catch(err => {
console.error(err);
return;
}).finally(() => {
dt_basic.ajax.reload();
new bootstrap.Modal('#RemoveModal').hide();
});
});
});
function toggleDynamicInput(checkbox, element) {
checkbox.on('change', function() {
element.prop('disabled', checkbox.is(':checked'));
});
}