diff --git a/app/css/all.css b/app/css/all.css index 023eb15b..6553afa5 100644 --- a/app/css/all.css +++ b/app/css/all.css @@ -16,6 +16,10 @@ License: GNU General Public License v3.0 h4.mt-3 { margin-left: 0.5rem; } } +.sidebar.toggled .nav-item .nav-link { + padding: 0.65rem 1rem; +} + .sidebar-brand-text { text-transform: none; color: #212529; @@ -52,7 +56,11 @@ License: GNU General Public License v3.0 .info-item-xs { font-size: 0.7rem; - margin-left: 0.3rem; + margin-left: 0.75rem; +} + +.sb-status { + margin-left: 0.75rem!important; } .info-item-wifi { @@ -235,3 +243,22 @@ button > i.fas { font-size: 1.3rem; } +.was-validated .form-control:valid, +.was-validated .form-control:invalid { + background-position: center right calc(.375em + .4875rem); +} + +.was-validated .form-control:invalid { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); + background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} + +.was-validated .form-control:valid { + background-size: calc(0.6em + 0.375rem) calc(0.6em + 0.375rem); +} + +.input-group>.input-group-append:not(:last-child)>.btn { + border-top-right-radius: 0.35rem; + border-bottom-right-radius: 0.35rem; +} + diff --git a/app/css/material-dark.php b/app/css/material-dark.php index 524d5e4d..e14ccea0 100644 --- a/app/css/material-dark.php +++ b/app/css/material-dark.php @@ -627,3 +627,18 @@ a.scroll-to-top.rounded i.fas.fa-angle-up { padding: 5px; box-sizing: border-box; } + +.was-validated .form-control:valid, +.was-validated .form-control:invalid { + background-position: center right calc(.375em + .4875rem); +} + +.was-validated .form-control:invalid { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); + background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} + +.was-validated .form-control:valid { + background-size: calc(0.6em + 0.375rem) calc(0.6em + 0.375rem); +} + diff --git a/app/css/material-light.php b/app/css/material-light.php index 0a87f825..8ee6804e 100644 --- a/app/css/material-light.php +++ b/app/css/material-light.php @@ -633,3 +633,18 @@ a.scroll-to-top.rounded i.fas.fa-angle-up { padding: 5px; box-sizing: border-box; } + +.was-validated .form-control:valid, +.was-validated .form-control:invalid { + background-position: center right calc(.375em + .4875rem); +} + +.was-validated .form-control:invalid { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); + background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} + +.was-validated .form-control:valid { + background-size: calc(0.6em + 0.375rem) calc(0.6em + 0.375rem); +} + diff --git a/app/js/custom.js b/app/js/custom.js index 3c2a45f4..6c929c26 100644 --- a/app/js/custom.js +++ b/app/js/custom.js @@ -241,6 +241,7 @@ function loadInterfaceDHCPSelect() { $('#chkstatic').closest('.btn').button('toggle').blur(); $('#chkstatic').blur(); $('#chkfallback').prop('disabled', true); + $('#dhcp-iface').removeAttr('disabled'); } else { $('#chkdhcp').closest('.btn').button('toggle'); $('#chkdhcp').closest('.btn').button('toggle').blur(); @@ -249,6 +250,7 @@ function loadInterfaceDHCPSelect() { } if (jsonData.FallbackEnabled || $('#chkdhcp').is(':checked')) { $('#dhcp-iface').prop('disabled', true); + setDhcpFieldsDisabled(); } }); } @@ -259,6 +261,7 @@ function setDHCPToggles(state) { } if ($('#dhcp-iface').is(':checked') && !state) { $('#dhcp-iface').prop('checked', state); + setDhcpFieldsDisabled(); } $('#chkfallback').prop('disabled', state); $('#dhcp-iface').prop('disabled', !state); @@ -365,7 +368,15 @@ $('#js-sys-reboot, #js-sys-shutdown').on('click', function (e) { }); $(document).ready(function(){ - $("#PanelManual").hide(); + $("#PanelManual").hide(); + $('.ip_address').mask('0ZZ.0ZZ.0ZZ.0ZZ', { + translation: { + 'Z': { + pattern: /[0-9]/, optional: true + } + }, + placeholder: "___.___.___.___" + }); }); $('#wg-upload,#wg-manual').on('click', function (e) { @@ -542,6 +553,77 @@ window.addEventListener('load', function() { }); }, false); +// DHCP or Static IP option group +$('#chkstatic').on('change', function() { + if (this.checked) { + setStaticFieldsEnabled(); + } +}); + +$('#chkdhcp').on('change', function() { + this.checked ? setStaticFieldsDisabled() : null; +}); + + +$('input[name="dhcp-iface"]').change(function() { + if ($('input[name="dhcp-iface"]:checked').val() == '1') { + setDhcpFieldsEnabled(); + } else { + setDhcpFieldsDisabled(); + } +}); + + +function setStaticFieldsEnabled() { + $('#txtipaddress').prop('required', true); + $('#txtsubnetmask').prop('required', true); + $('#txtgateway').prop('required', true); + + $('#txtipaddress').removeAttr('disabled'); + $('#txtsubnetmask').removeAttr('disabled'); + $('#txtgateway').removeAttr('disabled'); +} + +function setStaticFieldsDisabled() { + $('#txtipaddress').prop('disabled', true); + $('#txtsubnetmask').prop('disabled', true); + $('#txtgateway').prop('disabled', true); + + $('#txtipaddress').removeAttr('required'); + $('#txtsubnetmask').removeAttr('required'); + $('#txtgateway').removeAttr('required'); +} + +function setDhcpFieldsEnabled() { + $('#txtrangestart').prop('required', true); + $('#txtrangeend').prop('required', true); + $('#txtrangeleasetime').prop('required', true); + $('#cbxrangeleasetimeunits').prop('required', true); + + $('#txtrangestart').removeAttr('disabled'); + $('#txtrangeend').removeAttr('disabled'); + $('#txtrangeleasetime').removeAttr('disabled'); + $('#cbxrangeleasetimeunits').removeAttr('disabled'); + $('#txtdns1').removeAttr('disabled'); + $('#txtdns2').removeAttr('disabled'); + $('#txtmetric').removeAttr('disabled'); +} + +function setDhcpFieldsDisabled() { + $('#txtrangestart').removeAttr('required'); + $('#txtrangeend').removeAttr('required'); + $('#txtrangeleasetime').removeAttr('required'); + $('#cbxrangeleasetimeunits').removeAttr('required'); + + $('#txtrangestart').prop('disabled', true); + $('#txtrangeend').prop('disabled', true); + $('#txtrangeleasetime').prop('disabled', true); + $('#cbxrangeleasetimeunits').prop('disabled', true); + $('#txtdns1').prop('disabled', true); + $('#txtdns2').prop('disabled', true); + $('#txtmetric').prop('disabled', true); +} + // Static Array method Array.range = (start, end) => Array.from({length: (end - start)}, (v, k) => k + start); diff --git a/dist/jquery-mask/jquery.mask.min.js b/dist/jquery-mask/jquery.mask.min.js new file mode 100644 index 00000000..1f22376e --- /dev/null +++ b/dist/jquery-mask/jquery.mask.min.js @@ -0,0 +1,19 @@ +// jQuery Mask Plugin v1.14.16 +// github.com/igorescobar/jQuery-Mask-Plugin +var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.findInternal=function(a,n,f){a instanceof String&&(a=String(a));for(var p=a.length,k=0;k
g?h=10*d:e>=h&&e!==g?c.maskDigitPosMapOld[h]||(e=h,h=h-(k-l)-a,c.maskDigitPosMap[h]&&(h=e)):h>e&&(h=h+(l-k)+f)}return h},behaviour:function(d){d=
+d||window.event;c.invalid=[];var e=b.data("mask-keycode");if(-1===a.inArray(e,l.byPassKeys)){e=c.getMasked();var h=c.getCaret(),g=b.data("mask-previus-value")||"";setTimeout(function(){c.setCaret(c.calculateCaretPosition(g))},a.jMaskGlobals.keyStrokeCompensation);c.val(e);c.setCaret(h);return c.callbacks(d)}},getMasked:function(a,b){var h=[],f=void 0===b?c.val():b+"",g=0,k=d.length,n=0,p=f.length,m=1,r="push",u=-1,w=0;b=[];if(e.reverse){r="unshift";m=-1;var x=0;g=k-1;n=p-1;var A=function(){return-1<
+g&&-1
'.PHP_EOL;
+ $errors[] = _('Invalid interface name.');
}
if (!filter_var($_POST['StaticIP'], FILTER_VALIDATE_IP) && !empty($_POST['StaticIP'])) {
- $errors .= _('Invalid static IP address.').'
'.PHP_EOL;
+ $errors[] = _('Invalid static IP address.');
}
if (!filter_var($_POST['SubnetMask'], FILTER_VALIDATE_IP) && !empty($_POST['SubnetMask'])) {
- $errors .= _('Invalid subnet mask.').'
'.PHP_EOL;
+ $errors[] = _('Invalid subnet mask.');
}
if (!filter_var($_POST['DefaultGateway'], FILTER_VALIDATE_IP) && !empty($_POST['DefaultGateway'])) {
- $errors .= _('Invalid default gateway.').'
'.PHP_EOL;
+ $errors[] = _('Invalid default gateway.');
}
if (($_POST['dhcp-iface'] == "1")) {
if (!filter_var($_POST['RangeStart'], FILTER_VALIDATE_IP) && !empty($_POST['RangeStart'])) {
- $errors .= _('Invalid DHCP range start.').'
'.PHP_EOL;
+ $errors[] = _('Invalid DHCP range start.');
}
if (!filter_var($_POST['RangeEnd'], FILTER_VALIDATE_IP) && !empty($_POST['RangeEnd'])) {
- $errors .= _('Invalid DHCP range end.').'
'.PHP_EOL;
+ $errors[] = _('Invalid DHCP range end.');
}
if (!ctype_digit($_POST['RangeLeaseTime']) && $_POST['RangeLeaseTimeUnits'] !== 'i') {
- $errors .= _('Invalid DHCP lease time, not a number.').'
'.PHP_EOL;
+ $errors[] = _('Invalid DHCP lease time, not a number.');
}
if (!in_array($_POST['RangeLeaseTimeUnits'], array('m', 'h', 'd', 'i'))) {
- $errors .= _('Unknown DHCP lease time unit.').'
'.PHP_EOL;
+ $errors[] = _('Unknown DHCP lease time unit.');
}
if ($_POST['Metric'] !== '' && !ctype_digit($_POST['Metric'])) {
- $errors .= _('Invalid metric value, not a number.').'
'.PHP_EOL;
+ $errors[] = _('Invalid metric value, not a number.');
}
}
return $errors;
diff --git a/includes/functions.php b/includes/functions.php
index cbc28f96..78d12bae 100755
--- a/includes/functions.php
+++ b/includes/functions.php
@@ -435,18 +435,25 @@ function GetDistString($input, $string, $offset, $separator)
}
/**
- *
- * @param array $arrConfig
+ * Parses a configuration file
+ * Options and values are mapped with "=" characters
+ * Optional $wg flag is used for parsing WireGuard .conf files
+ * @param array $arrConfig
+ * @param boolean $wg
* @return $config
*/
-function ParseConfig($arrConfig)
+function ParseConfig($arrConfig, $wg = false)
{
$config = array();
foreach ($arrConfig as $line) {
$line = trim($line);
if ($line == "" || $line[0] == "#") {
- $config[$option] = null;
- continue;
+ if ($wg) {
+ $config[$option] = null;
+ continue;
+ } else {
+ continue;
+ }
}
if (strpos($line, "=") !== false) {
diff --git a/includes/sidebar.php b/includes/sidebar.php
index 13558354..34545fc0 100755
--- a/includes/sidebar.php
+++ b/includes/sidebar.php
@@ -10,15 +10,15 @@