diff options
Diffstat (limited to 'modules/luci-base/htdocs/luci-static/resources')
5 files changed, 206 insertions, 22 deletions
diff --git a/modules/luci-base/htdocs/luci-static/resources/cbi.js b/modules/luci-base/htdocs/luci-static/resources/cbi.js index 9728e03e12..aef64d577e 100644 --- a/modules/luci-base/htdocs/luci-static/resources/cbi.js +++ b/modules/luci-base/htdocs/luci-static/resources/cbi.js @@ -657,7 +657,11 @@ String.prototype.format = function() for (i = 0; (i < units.length) && (val > mf); i++) val /= mf; - subst = (i ? val.toFixed(pr) : val) + units[i]; + if (i) + subst = val.toFixed(pr) + units[i] + (mf == 1024 ? 'i' : ''); + else + subst = val + ' '; + pMinLength = null; break; } diff --git a/modules/luci-base/htdocs/luci-static/resources/form.js b/modules/luci-base/htdocs/luci-static/resources/form.js index fbdd73e55e..4016007742 100644 --- a/modules/luci-base/htdocs/luci-static/resources/form.js +++ b/modules/luci-base/htdocs/luci-static/resources/form.js @@ -2489,6 +2489,8 @@ var CBITableSection = CBITypedSection.extend(/** @lends LuCI.form.TableSection.p config_name = this.uciconfig || this.map.config, max_cols = isNaN(this.max_cols) ? this.children.length : this.max_cols, has_more = max_cols < this.children.length, + drag_sort = this.sortable && !('ontouchstart' in window), + touch_sort = this.sortable && ('ontouchstart' in window), sectionEl = E('div', { 'id': 'cbi-%s-%s'.format(config_name, this.sectiontype), 'class': 'cbi-section cbi-tblsection', @@ -2517,14 +2519,16 @@ var CBITableSection = CBITypedSection.extend(/** @lends LuCI.form.TableSection.p 'id': 'cbi-%s-%s'.format(config_name, cfgsections[i]), 'class': 'tr cbi-section-table-row', 'data-sid': cfgsections[i], - 'draggable': this.sortable ? true : null, - 'mousedown': this.sortable ? L.bind(this.handleDragInit, this) : null, - 'dragstart': this.sortable ? L.bind(this.handleDragStart, this) : null, - 'dragover': this.sortable ? L.bind(this.handleDragOver, this) : null, - 'dragenter': this.sortable ? L.bind(this.handleDragEnter, this) : null, - 'dragleave': this.sortable ? L.bind(this.handleDragLeave, this) : null, - 'dragend': this.sortable ? L.bind(this.handleDragEnd, this) : null, - 'drop': this.sortable ? L.bind(this.handleDrop, this) : null, + 'draggable': (drag_sort || touch_sort) ? true : null, + 'mousedown': drag_sort ? L.bind(this.handleDragInit, this) : null, + 'dragstart': drag_sort ? L.bind(this.handleDragStart, this) : null, + 'dragover': drag_sort ? L.bind(this.handleDragOver, this) : null, + 'dragenter': drag_sort ? L.bind(this.handleDragEnter, this) : null, + 'dragleave': drag_sort ? L.bind(this.handleDragLeave, this) : null, + 'dragend': drag_sort ? L.bind(this.handleDragEnd, this) : null, + 'drop': drag_sort ? L.bind(this.handleDrop, this) : null, + 'touchmove': touch_sort ? L.bind(this.handleTouchMove, this) : null, + 'touchend': touch_sort ? L.bind(this.handleTouchEnd, this) : null, 'data-title': (sectionname && (!this.anonymous || this.sectiontitle)) ? sectionname : null, 'data-section-id': cfgsections[i] }); @@ -2797,6 +2801,160 @@ var CBITableSection = CBITypedSection.extend(/** @lends LuCI.form.TableSection.p }, /** @private */ + determineBackgroundColor: function(node) { + var r = 255, g = 255, b = 255; + + while (node) { + var s = window.getComputedStyle(node), + c = (s.getPropertyValue('background-color') || '').replace(/ /g, ''); + + if (c != '' && c != 'transparent' && c != 'rgba(0,0,0,0)') { + if (/^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/i.test(c)) { + r = parseInt(RegExp.$1, 16); + g = parseInt(RegExp.$2, 16); + b = parseInt(RegExp.$3, 16); + } + else if (/^rgba?\(([0-9]+),([0-9]+),([0-9]+)[,)]$/.test(c)) { + r = +RegExp.$1; + g = +RegExp.$2; + b = +RegExp.$3; + } + + break; + } + + node = node.parentNode; + } + + return [ r, g, b ]; + }, + + /** @private */ + handleTouchMove: function(ev) { + if (!ev.target.classList.contains('drag-handle')) + return; + + var touchLoc = ev.targetTouches[0], + rowBtn = ev.target, + rowElem = dom.parent(rowBtn, '.tr'), + htmlElem = document.querySelector('html'), + dragHandle = document.querySelector('.touchsort-element'), + viewportHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); + + if (!dragHandle) { + var rowRect = rowElem.getBoundingClientRect(), + btnRect = rowBtn.getBoundingClientRect(), + paddingLeft = btnRect.left - rowRect.left, + paddingRight = rowRect.right - btnRect.right, + colorBg = this.determineBackgroundColor(rowElem), + colorFg = (colorBg[0] * 0.299 + colorBg[1] * 0.587 + colorBg[2] * 0.114) > 186 ? [ 0, 0, 0 ] : [ 255, 255, 255 ]; + + dragHandle = E('div', { 'class': 'touchsort-element' }, [ + E('strong', [ rowElem.getAttribute('data-title') ]), + rowBtn.cloneNode(true) + ]); + + Object.assign(dragHandle.style, { + position: 'absolute', + boxShadow: '0 0 3px rgba(%d, %d, %d, 1)'.format(colorFg[0], colorFg[1], colorFg[2]), + background: 'rgba(%d, %d, %d, 0.8)'.format(colorBg[0], colorBg[1], colorBg[2]), + top: rowRect.top + 'px', + left: rowRect.left + 'px', + width: rowRect.width + 'px', + height: (rowBtn.offsetHeight + 4) + 'px' + }); + + Object.assign(dragHandle.firstElementChild.style, { + position: 'absolute', + lineHeight: dragHandle.style.height, + whiteSpace: 'nowrap', + overflow: 'hidden', + textOverflow: 'ellipsis', + left: (paddingRight > paddingLeft) ? '' : '5px', + right: (paddingRight > paddingLeft) ? '5px' : '', + width: (Math.max(paddingLeft, paddingRight) - 10) + 'px' + }); + + Object.assign(dragHandle.lastElementChild.style, { + position: 'absolute', + top: '2px', + left: paddingLeft + 'px', + width: rowBtn.offsetWidth + 'px' + }); + + document.body.appendChild(dragHandle); + + rowElem.classList.remove('flash'); + rowBtn.blur(); + } + + dragHandle.style.top = (touchLoc.pageY - (parseInt(dragHandle.style.height) / 2)) + 'px'; + + rowElem.parentNode.querySelectorAll('[draggable]').forEach(function(tr, i, trs) { + var trRect = tr.getBoundingClientRect(), + yTop = trRect.top + window.scrollY, + yBottom = trRect.bottom + window.scrollY, + yMiddle = yTop + ((yBottom - yTop) / 2); + + tr.classList.remove('drag-over-above', 'drag-over-below'); + + if ((i == 0 || touchLoc.pageY >= yTop) && touchLoc.pageY <= yMiddle) + tr.classList.add('drag-over-above'); + else if ((i == (trs.length - 1) || touchLoc.pageY <= yBottom) && touchLoc.pageY > yMiddle) + tr.classList.add('drag-over-below'); + }); + + /* prevent standard scrolling and scroll page when drag handle is + * moved very close (~30px) to the viewport edge */ + + ev.preventDefault(); + + if (touchLoc.clientY < 30) + window.requestAnimationFrame(function() { htmlElem.scrollTop -= 30 }); + else if (touchLoc.clientY > viewportHeight - 30) + window.requestAnimationFrame(function() { htmlElem.scrollTop += 30 }); + }, + + /** @private */ + handleTouchEnd: function(ev) { + var rowElem = dom.parent(ev.target, '.tr'), + htmlElem = document.querySelector('html'), + dragHandle = document.querySelector('.touchsort-element'), + targetElem = rowElem.parentNode.querySelector('.drag-over-above, .drag-over-below'), + viewportHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); + + if (!dragHandle) + return; + + if (targetElem) { + var isBelow = targetElem.classList.contains('drag-over-below'); + + rowElem.parentNode.insertBefore(rowElem, isBelow ? targetElem.nextElementSibling : targetElem); + + this.map.data.move( + this.uciconfig || this.map.config, + rowElem.getAttribute('data-sid'), + targetElem.getAttribute('data-sid'), + isBelow); + + window.requestAnimationFrame(function() { + var rowRect = rowElem.getBoundingClientRect(); + + if (rowRect.top < 50) + htmlElem.scrollTop = (htmlElem.scrollTop + rowRect.top - 50); + else if (rowRect.bottom > viewportHeight - 50) + htmlElem.scrollTop = (htmlElem.scrollTop + viewportHeight - 50 - rowRect.height); + + rowElem.classList.add('flash'); + }); + + targetElem.classList.remove('drag-over-above', 'drag-over-below'); + } + + document.body.removeChild(dragHandle); + }, + + /** @private */ handleModalCancel: function(modalMap, ev) { return Promise.resolve(ui.hideModal()); }, diff --git a/modules/luci-base/htdocs/luci-static/resources/network.js b/modules/luci-base/htdocs/luci-static/resources/network.js index 17dd055e25..2a402bcd57 100644 --- a/modules/luci-base/htdocs/luci-static/resources/network.js +++ b/modules/luci-base/htdocs/luci-static/resources/network.js @@ -1005,9 +1005,10 @@ Network = baseclass.extend(/** @lends LuCI.network.prototype */ { */ deleteNetwork: function(name) { var requireFirewall = Promise.resolve(L.require('firewall')).catch(function() {}), + loadDHCP = L.resolveDefault(uci.load('dhcp')), network = this.instantiateNetwork(name); - return Promise.all([ requireFirewall, initNetworkState() ]).then(function(res) { + return Promise.all([ requireFirewall, loadDHCP, initNetworkState() ]).then(function(res) { var uciInterface = uci.get('network', name), firewall = res[0]; @@ -1020,19 +1021,23 @@ Network = baseclass.extend(/** @lends LuCI.network.prototype */ { uci.remove('luci', s['.name']); }); - uci.sections('network', 'alias', function(s) { - if (s.interface == name) - uci.remove('network', s['.name']); - }); + uci.sections('network', null, function(s) { + switch (s['.type']) { + case 'alias': + case 'route': + case 'route6': + if (s.interface == name) + uci.remove('network', s['.name']); - uci.sections('network', 'route', function(s) { - if (s.interface == name) - uci.remove('network', s['.name']); - }); + break; - uci.sections('network', 'route6', function(s) { - if (s.interface == name) - uci.remove('network', s['.name']); + case 'rule': + case 'rule6': + if (s.in == name || s.out == name) + uci.remove('network', s['.name']); + + break; + } }); uci.sections('wireless', 'wifi-iface', function(s) { @@ -1044,6 +1049,11 @@ Network = baseclass.extend(/** @lends LuCI.network.prototype */ { uci.unset('wireless', s['.name'], 'network'); }); + uci.sections('dhcp', 'dhcp', function(s) { + if (s.interface == name) + uci.remove('dhcp', s['.name']); + }); + if (firewall) return firewall.deleteNetwork(name).then(function() { return true }); diff --git a/modules/luci-base/htdocs/luci-static/resources/ui.js b/modules/luci-base/htdocs/luci-static/resources/ui.js index 0e909b6dcc..9cc62c12db 100644 --- a/modules/luci-base/htdocs/luci-static/resources/ui.js +++ b/modules/luci-base/htdocs/luci-static/resources/ui.js @@ -3021,7 +3021,7 @@ function scrubMenu(node) { for (var k in node.children) { var child = scrubMenu(node.children[k]); - if (child.title) + if (child.title && !child.firstchild_ineligible) hasSatisfiedChild = hasSatisfiedChild || child.satisfied; } } diff --git a/modules/luci-base/htdocs/luci-static/resources/validation.js b/modules/luci-base/htdocs/luci-static/resources/validation.js index 70d3a7e73a..fccce4ab0b 100644 --- a/modules/luci-base/htdocs/luci-static/resources/validation.js +++ b/modules/luci-base/htdocs/luci-static/resources/validation.js @@ -575,6 +575,18 @@ var ValidatorFactory = baseclass.extend({ string: function() { return true; + }, + + directory: function() { + return true; + }, + + file: function() { + return true; + }, + + device: function() { + return true; } } }); |