mirror of
https://github.com/gSpotx2f/luci-app-disks-info.git
synced 2025-01-07 03:07:11 +08:00
Minor improvements
This commit is contained in:
parent
098bb4ef12
commit
67b7b406ad
2
Makefile
2
Makefile
@ -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
|
||||||
|
12
README.md
12
README.md
@ -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:**
|
||||||
|
|
||||||
|
@ -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,
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
|
@ -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
|
||||||
|
BIN
packages/19.07/luci-app-disks-info_0.3-5_all.ipk
vendored
BIN
packages/19.07/luci-app-disks-info_0.3-5_all.ipk
vendored
Binary file not shown.
BIN
packages/19.07/luci-app-disks-info_0.3-6_all.ipk
vendored
Normal file
BIN
packages/19.07/luci-app-disks-info_0.3-6_all.ipk
vendored
Normal file
Binary file not shown.
BIN
packages/19.07/luci-i18n-disks-info-ru_0.3-5_all.ipk
vendored
BIN
packages/19.07/luci-i18n-disks-info-ru_0.3-5_all.ipk
vendored
Binary file not shown.
BIN
packages/19.07/luci-i18n-disks-info-ru_0.3-6_all.ipk
vendored
Normal file
BIN
packages/19.07/luci-i18n-disks-info-ru_0.3-6_all.ipk
vendored
Normal file
Binary file not shown.
@ -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 ""
|
||||||
|
|
||||||
|
@ -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 ""
|
||||||
|
|
||||||
|
@ -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 |
Loading…
Reference in New Issue
Block a user