Minor improvements

This commit is contained in:
gSpot 2021-10-06 23:57:36 +03:00
parent 098bb4ef12
commit 67b7b406ad
12 changed files with 151 additions and 112 deletions

View File

@ -7,7 +7,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_VERSION:=0.3 PKG_VERSION:=0.3
PKG_RELEASE:=5 PKG_RELEASE:=6
LUCI_TITLE:=Information about connected disk devices (partitions, filesystems, SMART). LUCI_TITLE:=Information about connected disk devices (partitions, filesystems, SMART).
LUCI_DEPENDS:=+fdisk +smartmontools +smartmontools-drivedb LUCI_DEPENDS:=+fdisk +smartmontools +smartmontools-drivedb
LUCI_PKGARCH:=all LUCI_PKGARCH:=all

View File

@ -5,16 +5,16 @@ OpenWrt >= 19.07.
**Installation notes:** **Installation notes:**
wget --no-check-certificate -O /tmp/luci-app-disks-info_0.3-5_all.ipk https://github.com/gSpotx2f/luci-app-disks-info/raw/master/packages/19.07/luci-app-disks-info_0.3-5_all.ipk wget --no-check-certificate -O /tmp/luci-app-disks-info_0.3-6_all.ipk https://github.com/gSpotx2f/luci-app-disks-info/raw/master/packages/19.07/luci-app-disks-info_0.3-6_all.ipk
opkg install /tmp/luci-app-disks-info_0.3-5_all.ipk opkg install /tmp/luci-app-disks-info_0.3-6_all.ipk
rm /tmp/luci-app-disks-info_0.3-5_all.ipk rm /tmp/luci-app-disks-info_0.3-6_all.ipk
/etc/init.d/rpcd restart /etc/init.d/rpcd restart
**i18n-ru:** **i18n-ru:**
wget --no-check-certificate -O /tmp/luci-i18n-disks-info-ru_0.3-5_all.ipk https://github.com/gSpotx2f/luci-app-disks-info/raw/master/packages/19.07/luci-i18n-disks-info-ru_0.3-5_all.ipk wget --no-check-certificate -O /tmp/luci-i18n-disks-info-ru_0.3-6_all.ipk https://github.com/gSpotx2f/luci-app-disks-info/raw/master/packages/19.07/luci-i18n-disks-info-ru_0.3-6_all.ipk
opkg install /tmp/luci-i18n-disks-info-ru_0.3-5_all.ipk opkg install /tmp/luci-i18n-disks-info-ru_0.3-6_all.ipk
rm /tmp/luci-i18n-disks-info-ru_0.3-5_all.ipk rm /tmp/luci-i18n-disks-info-ru_0.3-6_all.ipk
**Screenshots:** **Screenshots:**

View File

@ -4,7 +4,11 @@
document.head.append(E('style', {'type': 'text/css'}, document.head.append(E('style', {'type': 'text/css'},
` `
.label-status { :root {
--app-disks-info-dark-font-color: #2e2e2e;
--app-disks-info-light-font-color: #fff;
}
.disks-info-label-status {
display: inline; display: inline;
margin: 0 4px !important; margin: 0 4px !important;
padding: 1px 4px; padding: 1px 4px;
@ -14,23 +18,30 @@ document.head.append(E('style', {'type': 'text/css'},
text-transform: uppercase; text-transform: uppercase;
font-weight: bold; font-weight: bold;
line-height: 1.6em; line-height: 1.6em;
color: #fff !important;
} }
.ok { .disks-info-ok {
background-color: #2ea256 !important; background-color: #2ea256 !important;
color: var(--app-disks-info-light-font-color) !important;
} }
.warn { .disks-info-warn {
background-color: #fff7e2 !important; background-color: #fff7e2 !important;
color: var(--app-disks-info-dark-font-color) !important;
} }
.err { .disks-info-warn .td {
color: var(--app-disks-info-dark-font-color) !important;
}
.disks-info-warn td {
color: var(--app-disks-info-dark-font-color) !important;
}
.disks-info-err {
background-color: #ff4e54 !important; background-color: #ff4e54 !important;
color: #fff !important; color: var(--app-disks-info-light-font-color) !important;
} }
.err .td { .disks-info-err .td {
color: #fff !important; color: var(--app-disks-info-light-font-color) !important;
} }
.err td { .disks-info-err td {
color: #fff !important; color: var(--app-disks-info-light-font-color) !important;
} }
`)); `));
@ -61,9 +72,15 @@ return L.view.extend({
let num = document.getElementById('logging_interval_value' + deviceNormalized).value; let num = document.getElementById('logging_interval_value' + deviceNormalized).value;
let pSave = document.getElementById('logging_interval_type' + deviceNormalized).checked; let pSave = document.getElementById('logging_interval_type' + deviceNormalized).checked;
if(/^[0-9]{1,2}$/.test(num) && Number(num) > 0) {
num = String(Number(num));
} else {
return;
};
return fs.exec('/usr/sbin/smartctl', return fs.exec('/usr/sbin/smartctl',
[ '-l', 'scttempint,' + (pSave ? num + ',p' : num), device ] [ '-l', 'scttempint,' + (pSave ? num + ',p' : num), device ]
).then((res) => { ).then(res => {
window.location.reload(); window.location.reload();
}).catch(e => ui.addNotification(null, E('p', {}, e.message))); }).catch(e => ui.addNotification(null, E('p', {}, e.message)));
}, },
@ -175,7 +192,7 @@ return L.view.extend({
tr.append( tr.append(
E('div', { E('div', {
'class': (i === 5 && parseInt(fields[i]) >= this.fsSpaceWarning) ? 'class': (i === 5 && parseInt(fields[i]) >= this.fsSpaceWarning) ?
'td left warn' : 'td left', 'td left disks-info-warn' : 'td left',
'data-title': dfTableTitles[i], 'data-title': dfTableTitles[i],
}, },
(i === 5) ? E('div', { (i === 5) ? E('div', {
@ -218,8 +235,8 @@ return L.view.extend({
createSmartTable: function(smartObject) { createSmartTable: function(smartObject) {
let smartStatusLabel = (smartObject.smart_status.passed) ? let smartStatusLabel = (smartObject.smart_status.passed) ?
E('span', { 'class': 'label-status ok' }, _('passed')) : E('span', { 'class': 'disks-info-label-status disks-info-ok' }, _('passed')) :
E('span', { 'class': 'label-status err' }, _('failed')); E('span', { 'class': 'disks-info-label-status disks-info-err' }, _('failed'));
let smartStatus = E('h5', { 'style': 'width:100% !important; text-align:center !important' }, [ let smartStatus = E('h5', { 'style': 'width:100% !important; text-align:center !important' }, [
_('SMART overall-health self-assessment test result:'), _('SMART overall-health self-assessment test result:'),
@ -240,10 +257,10 @@ return L.view.extend({
for(let attr of smartObject.ata_smart_attributes.table) { for(let attr of smartObject.ata_smart_attributes.table) {
let tempValue; let tempValue;
let lineStyle = (attr.value <= attr.thresh) ? 'tr err' : let lineStyle = (attr.value <= attr.thresh) ? 'tr disks-info-err' :
(this.smartCriticalAttrs.includes(attr.id) && attr.raw.value > 0) ? 'tr warn' : (this.smartCriticalAttrs.includes(attr.id) && attr.raw.value > 0) ? 'tr disks-info-warn' :
(this.smartTempAttrs.includes(attr.id) && +(attr.raw.string.split(' ')[0]) >= this.diskTempWarning) ? (this.smartTempAttrs.includes(attr.id) && +(attr.raw.string.split(' ')[0]) >= this.diskTempWarning) ?
'tr warn' : 'tr'; 'tr disks-info-warn' : 'tr';
smartAttrsTable.append( smartAttrsTable.append(
E('div', { E('div', {
@ -285,13 +302,15 @@ return L.view.extend({
createErrorLog: function(table) { createErrorLog: function(table) {
let errorLogTable = E('div', { 'class': 'table' }, let errorLogTable = E('div', { 'class': 'table' },
E('div', { 'class': 'tr table-titles' }, [ E('div', { 'class': 'tr table-titles' }, [
E('div', { 'class': 'th left', 'style':'min-width:33%' }, _('Lifetime hours')), E('div', { 'class': 'th left', 'style':'min-width:16%' }, _('Error number')),
E('div', { 'class': 'th left', 'style':'min-width:17%' }, _('Lifetime hours')),
E('div', { 'class': 'th left' }, _('Description')), E('div', { 'class': 'th left' }, _('Description')),
]) ])
); );
for(let errObj of table) { for(let errObj of table) {
errorLogTable.append( errorLogTable.append(
E('div', { 'class': 'tr' }, [ E('div', { 'class': 'tr' }, [
E('div', { 'class': 'td left' }, errObj.error_number),
E('div', { 'class': 'td left' }, errObj.lifetime_hours), E('div', { 'class': 'td left' }, errObj.lifetime_hours),
E('div', { 'class': 'td left' }, errObj.error_description), E('div', { 'class': 'td left' }, errObj.error_description),
]) ])
@ -311,8 +330,8 @@ return L.view.extend({
E('div', { 'class': 'table' }, [ E('div', { 'class': 'table' }, [
E('div', { E('div', {
'class': (smartObject.temperature.current >= smartObject.temperature.op_limit_max) ? 'class': (smartObject.temperature.current >= smartObject.temperature.op_limit_max) ?
'tr err' : (smartObject.temperature.current >= this.diskTempWarning) ? 'tr disks-info-err' : (smartObject.temperature.current >= this.diskTempWarning) ?
'tr warn' : 'tr', 'tr disks-info-warn' : 'tr',
}, [ }, [
E('div', { 'class': 'td left', 'style':'min-width:33%' }, _('Current') + ':'), E('div', { 'class': 'td left', 'style':'min-width:33%' }, _('Current') + ':'),
E('div', { 'class': 'td left' }, ('current' in smartObject.temperature) ? E('div', { 'class': 'td left' }, ('current' in smartObject.temperature) ?
@ -360,6 +379,13 @@ return L.view.extend({
let dataSize = smartObject.ata_sct_temperature_history.size; let dataSize = smartObject.ata_sct_temperature_history.size;
let tempData = smartObject.ata_sct_temperature_history.table; let tempData = smartObject.ata_sct_temperature_history.table;
let dataUnits = []; let dataUnits = [];
let tempMin = tempData.reduce(
(min, current) => (current < min && current !== null) ? current : min,
Infinity);
let tempMax = tempData.reduce(
(max, current) => (current > max && current !== null) ? current : max,
-Infinity);
let tempDiff = tempMax - tempMin;
let i = dataSize - 1; let i = dataSize - 1;
while(i >= 0) { while(i >= 0) {
@ -375,12 +401,11 @@ return L.view.extend({
let svgWidth = 900; let svgWidth = 900;
let svgHeight = 300; let svgHeight = 300;
let tempValueMul = 3; // 1C == 3px let tempValueMul = (tempDiff >= 60) ? 3 : Math.round(svgHeight / (tempDiff + 20)); // 1°C = "tempValueMul"px
let tempOffset = 0; // lowest temp value: 0C let tempMinimalValue = (tempMin > 10) ? tempMin - 10 : 0;
let tempStep = 5; // 5C step let tempAxisStep = (tempDiff >= 60) ? 6 : (tempDiff >= 30) ? 4 : 2;
let timeStep = svgWidth / dataSize; let timeAxisStep = svgWidth / dataSize;
let timeLineInterval = Math.ceil(dataSize / 32); // 4 intervals (5 x 4 = 20 min) let timeAxisInterval = Math.ceil(dataSize / 32);
let svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); let svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('width', '100%'); svg.setAttribute('width', '100%');
svg.setAttribute('height', '100%'); svg.setAttribute('height', '100%');
@ -394,9 +419,9 @@ return L.view.extend({
for(let i = 0; i < dataSize; i++) { for(let i = 0; i < dataSize; i++) {
tempPoints.push([ tempPoints.push([
i * timeStep, i * timeAxisStep,
(dataUnits[i][1] != null) ? (dataUnits[i][1] != null) ?
(svgHeight - (dataUnits[i][1] - tempOffset) * tempValueMul) : (svgHeight - (dataUnits[i][1] - tempMinimalValue) * tempValueMul) :
svgHeight * 2 svgHeight * 2
]); ]);
}; };
@ -407,36 +432,36 @@ return L.view.extend({
// temperature warning // temperature warning
let lineW = document.createElementNS('http://www.w3.org/2000/svg', 'line'); let lineW = document.createElementNS('http://www.w3.org/2000/svg', 'line');
lineW.setAttribute('x1', 0); lineW.setAttribute('x1', 0);
lineW.setAttribute('y1', svgHeight - (this.diskTempWarning - tempOffset) * tempValueMul); lineW.setAttribute('y1', svgHeight - (this.diskTempWarning - tempMinimalValue) * tempValueMul);
lineW.setAttribute('x2', '100%'); lineW.setAttribute('x2', '100%');
lineW.setAttribute('y2', svgHeight - (this.diskTempWarning - tempOffset) * tempValueMul); lineW.setAttribute('y2', svgHeight - (this.diskTempWarning - tempMinimalValue) * tempValueMul);
lineW.setAttribute('style', 'stroke:orange; stroke-width:0.8'); lineW.setAttribute('style', 'stroke:orange; stroke-width:0.8');
svg.appendChild(lineW); svg.appendChild(lineW);
// temperature critical // temperature critical
let lineC = document.createElementNS('http://www.w3.org/2000/svg', 'line'); let lineC = document.createElementNS('http://www.w3.org/2000/svg', 'line');
lineC.setAttribute('x1', 0); lineC.setAttribute('x1', 0);
lineC.setAttribute('y1', svgHeight - (this.diskTempCritical - tempOffset) * tempValueMul); lineC.setAttribute('y1', svgHeight - (this.diskTempCritical - tempMinimalValue) * tempValueMul);
lineC.setAttribute('x2', '100%'); lineC.setAttribute('x2', '100%');
lineC.setAttribute('y2', svgHeight - (this.diskTempCritical - tempOffset) * tempValueMul); lineC.setAttribute('y2', svgHeight - (this.diskTempCritical - tempMinimalValue) * tempValueMul);
lineC.setAttribute('style', 'stroke:red; stroke-width:0.7'); lineC.setAttribute('style', 'stroke:red; stroke-width:0.7');
svg.appendChild(lineC); svg.appendChild(lineC);
// time labels // time labels
let j = 0; let j = 0;
for(let i = 0; i < svgWidth; i += timeStep * timeLineInterval) { for(let i = 0; i < svgWidth; i += timeAxisStep * timeAxisInterval) {
let line = document.createElementNS('http://www.w3.org/2000/svg', 'line'); let line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
line.setAttribute('x1', i); line.setAttribute('x1', i);
line.setAttribute('y1', 0); line.setAttribute('y1', 0);
line.setAttribute('x2', i); line.setAttribute('x2', i);
line.setAttribute('y2', '100%'); line.setAttribute('y2', '100%');
line.setAttribute('style', 'stroke:black; stroke-width:1; opacity:0.1'); line.setAttribute('style', 'stroke:rgba(122,122,122,0.2); stroke-width:1');
svg.appendChild(line); svg.appendChild(line);
let text = document.createElementNS('http://www.w3.org/2000/svg', 'text'); let text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
text.setAttribute('x', i + 6); text.setAttribute('x', i + 6);
text.setAttribute('y', 0); text.setAttribute('y', 0);
text.setAttribute('style', 'fill:rgba(122,122,122,0.5); font-family:monospace; font-size:12px; font-weight:bold; writing-mode:vertical-rl'); text.setAttribute('style', 'fill:rgba(122,122,122,0.5); font-family:monospace; font-size:12px; font-weight:bold; writing-mode:vertical-rl');
if(i >= 2 * timeStep * timeLineInterval) { if(i >= 2 * timeAxisStep * timeAxisInterval) {
text.appendChild(document.createTextNode('%02d.%02d %02d:%02d'.format( text.appendChild(document.createTextNode('%02d.%02d %02d:%02d'.format(
dataUnits[j][2].getDate(), dataUnits[j][2].getDate(),
dataUnits[j][2].getMonth() + 1, dataUnits[j][2].getMonth() + 1,
@ -444,7 +469,7 @@ return L.view.extend({
dataUnits[j][2].getMinutes() dataUnits[j][2].getMinutes()
))); )));
}; };
j += timeLineInterval; j += timeAxisInterval;
svg.appendChild(text); svg.appendChild(text);
if(j >= dataSize) { if(j >= dataSize) {
break; break;
@ -453,25 +478,33 @@ return L.view.extend({
// temperature labels // temperature labels
let c = 0; let c = 0;
for(let i = svgHeight; i > 0; i -= tempValueMul * tempStep) { for(let i = svgHeight; i > 0; i -= tempValueMul * tempAxisStep) {
let line = document.createElementNS('http://www.w3.org/2000/svg', 'line'); let line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
line.setAttribute('x1', 0); line.setAttribute('x1', 0);
line.setAttribute('y1', i); line.setAttribute('y1', i);
line.setAttribute('x2', '100%'); line.setAttribute('x2', '100%');
line.setAttribute('y2', i); line.setAttribute('y2', i);
line.setAttribute('style', 'stroke:black; stroke-width:1; opacity:0.1'); line.setAttribute('style', 'stroke:rgba(122,122,122,0.2); stroke-width:1');
svg.appendChild(line); svg.appendChild(line);
let text = document.createElementNS('http://www.w3.org/2000/svg', 'text'); let text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
text.setAttribute('x', 0); text.setAttribute('x', 0);
text.setAttribute('y', i - 3); text.setAttribute('y', i - 3);
text.setAttribute('style', 'fill:#eee; font-family:monospace; font-size:14px; text-shadow:1px 1px 1px #000'); text.setAttribute('style', 'fill:#eee; font-family:monospace; font-size:14px; text-shadow:1px 1px 1px #000');
if(c % 2 === 0) { if(c % 2 === 0) {
text.appendChild(document.createTextNode(((svgHeight - i) / tempValueMul) + tempOffset + ' °C')); text.appendChild(document.createTextNode(((svgHeight - i) / tempValueMul) + tempMinimalValue + ' °C'));
}; };
svg.appendChild(text); svg.appendChild(text);
c++; c++;
}; };
// temperature min/max, log interval
let text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
text.setAttribute('x', svgWidth / 3);
text.setAttribute('y', svgHeight - 10);
text.setAttribute('style', 'fill:#eee; font-family:monospace; font-size:12px; text-shadow:1px 1px 1px #000');
text.appendChild(document.createTextNode(`Interval:${intervalMin}m Tmin:${tempMin}°C Tmax:${tempMax}°C`));
svg.appendChild(text);
// TABLE // TABLE
dataUnits = dataUnits.filter((e, i, a) => { dataUnits = dataUnits.filter((e, i, a) => {
@ -487,13 +520,11 @@ return L.view.extend({
); );
for(let [num, temp, date] of dataUnits) { for(let [num, temp, date] of dataUnits) {
if(temp === null) { if(temp === null) continue;
continue;
};
sctTempTable.append( sctTempTable.append(
E('div', { E('div', {
'class': (temp >= this.diskTempCritical) ? 'tr err' : 'class': (temp >= this.diskTempCritical) ? 'tr disks-info-err' :
(temp >= this.diskTempWarning) ? 'tr warn' : 'tr', (temp >= this.diskTempWarning) ? 'tr disks-info-warn' : 'tr',
}, [ }, [
E('div', { 'class': 'td left', 'data-title': _('Index') }, E('div', { 'class': 'td left', 'data-title': _('Index') },
num), num),
@ -512,13 +543,15 @@ return L.view.extend({
}; };
let deviceNormalized = device.replace(/\//g, '-'); let deviceNormalized = device.replace(/\//g, '-');
let loggingIntervalValue = E('select', { let loggingIntervalValue = E('input', {
'id': 'logging_interval_value' + deviceNormalized, 'id': 'logging_interval_value' + deviceNormalized,
'type': 'text',
'class': 'cbi-input-text',
'style': 'width:4em !important; min-width:4em !important', 'style': 'width:4em !important; min-width:4em !important',
'maxlength': 2,
'value': 1,
}, E('option', { 'value': '1' }, 1)); }, E('option', { 'value': '1' }, 1));
for(let i = 5; i <= 60 ; i += 5) { ui.addValidator(loggingIntervalValue, 'range(1,99)', false)
loggingIntervalValue.append(E('option', { 'value': String(i) }, i));
};
return E([ return E([
E('div', { 'class': 'cbi-value' }, [ E('div', { 'class': 'cbi-value' }, [
@ -533,6 +566,7 @@ return L.view.extend({
sctTempTable sctTempTable
), ),
]), ]),
E('div', { 'class': 'cbi-value' }, [ E('div', { 'class': 'cbi-value' }, [
E('label', { 'class': 'cbi-value-title', 'for': 'logging_interval_value' + deviceNormalized }, E('label', { 'class': 'cbi-value-title', 'for': 'logging_interval_value' + deviceNormalized },
_('Set logging interval') + ' (' + _('min') + ')'), _('Set logging interval') + ' (' + _('min') + ')'),
@ -552,42 +586,16 @@ return L.view.extend({
E('label', { 'class': 'cbi-value-title' }, E('label', { 'class': 'cbi-value-title' },
_('Write to device memory') _('Write to device memory')
), ),
E('div', { 'class': 'cbi-value-field' }, E('div', { 'class': 'cbi-value-field' }, [
E('button', { E('button', {
'class': 'btn cbi-button-apply important', 'class': 'btn cbi-button-apply important',
'click': ui.createHandlerFn(this, this.setSctTempLogInterval, device), 'click': ui.createHandlerFn(this, this.setSctTempLogInterval, device),
}, _('Apply')) }, _('Apply')),
), ]),
E('hr'), E('hr'),
]), ]),
]);
},
createSsdArea: function(ssdStatObject) { ]);
let ssdPercEndurObj = ssdStatObject.table.find(e => e.offset == 8);
if(ssdPercEndurObj) {
return E('div', { 'class': 'cbi-value' }, [
E('h3', {}, _('SSD') + ':'),
E('div', { 'class': 'table' }, [
E('div', { 'class': 'tr' }, [
E('div', { 'class': 'td left', 'style':'min-width:33%' },
_('Percentage used endurance indicator') + ':'),
E('div', {
'class': (ssdPercEndurObj.value >= this.ssdEnduranceWarning) ?
'td left warn' : 'td left',
},
E('div', {
'class': 'cbi-progressbar',
'title': ssdPercEndurObj.value + '%',
'data-tooltip': _('May not be supported by some devices...'),
},
E('div', { 'style': 'width:' + ssdPercEndurObj.value + '%' })
)
),
]),
]),
]);
};
}, },
createDeviceStatistics: function(statObject) { createDeviceStatistics: function(statObject) {
@ -595,14 +603,28 @@ return L.view.extend({
E('h3', {}, _('Device statistics') + ':') E('h3', {}, _('Device statistics') + ':')
); );
for(let page of statObject.pages) { for(let page of statObject.pages) {
if(page.number == 5 || page.number == 7) continue; if(!Array.isArray(page.table) || page.table.length === 0) continue;
let pageTableTitle = E('h5', { 'style': 'width:100% !important; text-align:left !important' }, _(page.name)); let pageTableTitle = E('h5', { 'style': 'width:100% !important; text-align:left !important' }, _(page.name));
let pageTable = E('div', { 'class': 'table' }); let pageTable = E('div', { 'class': 'table' });
for(let entry of page.table) { for(let entry of page.table) {
pageTable.append( pageTable.append(
E('div', { 'class': 'tr' }, [ E('div', { 'class': 'tr' }, [
E('div', { 'class': 'td left', 'style':'min-width:33%' }, _(entry.name) + ':'), E('div', { 'class': 'td left', 'style':'min-width:33%' }, _(entry.name) + ':'),
E('div', { 'class': 'td left' }, entry.value), (page.number === 7 && entry.offset === 8) ?
E('div', {
'class': (entry.value >= this.ssdEnduranceWarning) ?
'td left disks-info-warn' : 'td left',
},
E('div', {
'class': 'cbi-progressbar',
'title': entry.value + '%',
'data-tooltip': _('May not be supported by some devices...'),
},
E('div', { 'style': 'width:' + entry.value + '%' })
)
)
:
E('div', { 'class': 'td left' }, entry.value),
]) ])
); );
}; };
@ -760,7 +782,9 @@ return L.view.extend({
this.diskTempWarning = smartObject.temperature && smartObject.temperature.op_limit_max || 60; this.diskTempWarning = smartObject.temperature && smartObject.temperature.op_limit_max || 60;
this.diskTempCritical = smartObject.temperature && smartObject.temperature.limit_max || 80; this.diskTempCritical = smartObject.temperature && smartObject.temperature.limit_max || 80;
if('smart_status' in smartObject && 'ata_smart_attributes' in smartObject) { if('smart_status' in smartObject && 'ata_smart_attributes' in smartObject &&
Array.isArray(smartObject.ata_smart_attributes.table) &&
smartObject.ata_smart_attributes.table.length > 0) {
deviceTab.append(this.createSmartTable(smartObject)); deviceTab.append(this.createSmartTable(smartObject));
}; };
if('ata_smart_error_log' in smartObject) { if('ata_smart_error_log' in smartObject) {
@ -771,18 +795,14 @@ return L.view.extend({
if('temperature' in smartObject) { if('temperature' in smartObject) {
deviceTab.append(this.createTempTable(smartObject)); deviceTab.append(this.createTempTable(smartObject));
}; };
if('ata_sct_temperature_history' in smartObject) { if('ata_sct_temperature_history' in smartObject &&
Array.isArray(smartObject.ata_sct_temperature_history.table) &&
smartObject.ata_sct_temperature_history.table.length > 0) {
deviceTab.append(this.createSctTempArea(smartObject)); deviceTab.append(this.createSctTempArea(smartObject));
}; };
if('ata_device_statistics' in smartObject) { if('ata_device_statistics' in smartObject &&
let ssdStatObject = smartObject.ata_device_statistics.pages.find(e => e.number == 7); Array.isArray(smartObject.ata_device_statistics.pages) &&
smartObject.ata_device_statistics.pages.length > 0) {
if(ssdStatObject) {
let ssdArea = this.createSsdArea(ssdStatObject);
if(ssdArea) {
deviceTab.append(ssdArea);
};
};
deviceTab.append(this.createDeviceStatistics(smartObject.ata_device_statistics)); deviceTab.append(this.createDeviceStatistics(smartObject.ata_device_statistics));
}; };
if('device' in smartObject) { if('device' in smartObject) {
@ -797,8 +817,9 @@ return L.view.extend({
}; };
return E([ return E([
E('h2', { 'class': 'fade-in' }, _('Disks info')), E('h2', { 'class': 'fade-in' }, _('Disk devices')),
E('div', { 'class': 'cbi-section-descr fade-in' }), E('div', { 'class': 'cbi-section-descr fade-in' },
_("Information about the connected disk devices.")),
devicesNode, devicesNode,
]); ]);
}, },

View File

@ -3,6 +3,6 @@ module('luci.controller.disks-info', package.seeall)
function index() function index()
if nixio.fs.access('/bin/df') and nixio.fs.access('/usr/sbin/fdisk') and nixio.fs.access('/usr/sbin/smartctl') then if nixio.fs.access('/bin/df') and nixio.fs.access('/usr/sbin/fdisk') and nixio.fs.access('/usr/sbin/smartctl') then
entry({'admin', 'services', 'disks-info'}, view('disks-info'), _('Disks info'), 10).acl_depends = { 'luci-app-disks-info' } entry({'admin', 'services', 'disks-info'}, view('disks-info'), _('Disk devices'), 10).acl_depends = { 'luci-app-disks-info' }
end end
end end

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -56,12 +56,15 @@ msgstr "Идентификатор диска"
msgid "Disklabel type" msgid "Disklabel type"
msgstr "Тип разметки диска" msgstr "Тип разметки диска"
msgid "Disks info" msgid "Disk devices"
msgstr "Информация о дисках" msgstr "Дисковые устройства"
msgid "End" msgid "End"
msgstr "Конец" msgstr "Конец"
msgid "Error number"
msgstr "Номер ошибки"
msgid "Estimated time" msgid "Estimated time"
msgstr "Расчётное время" msgstr "Расчётное время"
@ -95,6 +98,9 @@ msgstr "Находится в базе smartctl [подробно: -P show]"
msgid "Index" msgid "Index"
msgstr "Индекс" msgstr "Индекс"
msgid "Information about the connected disk devices."
msgstr "Информация о подключенных дисковых устройствах."
msgid "LU WWN Device Id" msgid "LU WWN Device Id"
msgstr "" msgstr ""
@ -140,8 +146,8 @@ msgstr "Отсутствует в базе smartctl [подробно: -P showal
msgid "Partitions" msgid "Partitions"
msgstr "Разделы" msgstr "Разделы"
msgid "Percentage used endurance indicator" msgid "Percentage Used Endurance Indicator"
msgstr "Процентный индикатор износа" msgstr "Процентный Индикатор Износа"
msgid "Preserve across power cycles" msgid "Preserve across power cycles"
msgstr "Сохранить при выключении питания" msgstr "Сохранить при выключении питания"
@ -159,7 +165,7 @@ msgid "Refresh devices"
msgstr "Обновить устройства" msgstr "Обновить устройства"
msgid "Rotating Media Statistics" msgid "Rotating Media Statistics"
msgstr "Статистика механической части" msgstr "Статистика Механической Части"
msgid "Rotation Rate" msgid "Rotation Rate"
msgstr "Скорость вращения" msgstr "Скорость вращения"
@ -197,8 +203,8 @@ msgstr "Серийный номер"
msgid "Size" msgid "Size"
msgstr "Размер" msgstr "Размер"
msgid "SSD" msgid "Solid State Device Statistics"
msgstr "" msgstr "Статистика SSD"
msgid "Start" msgid "Start"
msgstr "Начало" msgstr "Начало"
@ -206,6 +212,9 @@ msgstr "Начало"
msgid "Temperature" msgid "Temperature"
msgstr "Температура" msgstr "Температура"
msgid "Temperature Statistics"
msgstr "Статистика Температуры"
msgid "THRESH" msgid "THRESH"
msgstr "" msgstr ""

View File

@ -46,12 +46,15 @@ msgstr ""
msgid "Disklabel type" msgid "Disklabel type"
msgstr "" msgstr ""
msgid "Disks info" msgid "Disk devices"
msgstr "" msgstr ""
msgid "End" msgid "End"
msgstr "" msgstr ""
msgid "Error number"
msgstr ""
msgid "Estimated time" msgid "Estimated time"
msgstr "" msgstr ""
@ -85,6 +88,9 @@ msgstr ""
msgid "Index" msgid "Index"
msgstr "" msgstr ""
msgid "Information about the connected disk devices."
msgstr ""
msgid "LU WWN Device Id" msgid "LU WWN Device Id"
msgstr "" msgstr ""
@ -130,7 +136,7 @@ msgstr ""
msgid "Partitions" msgid "Partitions"
msgstr "" msgstr ""
msgid "Percentage used endurance indicator" msgid "Percentage Used Endurance Indicator"
msgstr "" msgstr ""
msgid "Preserve across power cycles" msgid "Preserve across power cycles"
@ -187,7 +193,7 @@ msgstr ""
msgid "Size" msgid "Size"
msgstr "" msgstr ""
msgid "SSD" msgid "Solid State Device Statistics"
msgstr "" msgstr ""
msgid "Start" msgid "Start"
@ -196,6 +202,9 @@ msgstr ""
msgid "Temperature" msgid "Temperature"
msgstr "" msgstr ""
msgid "Temperature Statistics"
msgstr ""
msgid "THRESH" msgid "THRESH"
msgstr "" msgstr ""

View File

@ -1,6 +1,6 @@
{ {
"admin/services/disks-info": { "admin/services/disks-info": {
"title": "Disks info", "title": "Disk devices",
"order": 10, "order": 10,
"action": { "action": {
"type": "view", "type": "view",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 567 KiB

After

Width:  |  Height:  |  Size: 572 KiB