mirror of
https://github.com/caiwx86/small-packages.git
synced 2026-10-31 22:25:13 +08:00
update 2026-09-24 10:46:53
This commit is contained in:
1 parent
907a158127
commit
b31a5c3878
4914 files changed
-1716179
No files matched your search
-470
@@ -1,470 +0,0 @@
|
||||
'use strict';
|
||||
'require baseclass';
|
||||
'require rpc';
|
||||
|
||||
document.head.append(E('style', {'type': 'text/css'},
|
||||
`
|
||||
:root {
|
||||
--app-temp-status-font-color: #2e2e2e;
|
||||
--app-temp-status-border-color: var(--border-color-medium, #d4d4d4);
|
||||
--app-temp-status-hot-color: #fff7e2;
|
||||
--app-temp-status-overheat-color: #ffe9e8;
|
||||
}
|
||||
:root[data-darkmode="true"] {
|
||||
--app-temp-status-font-color: #fff;
|
||||
--app-temp-status-border-color: var(--border-color-medium, #444);
|
||||
--app-temp-status-hot-color: #8d7000;
|
||||
--app-temp-status-overheat-color: #a93734;
|
||||
}
|
||||
.temp-status-hot {
|
||||
background-color: var(--app-temp-status-hot-color) !important;
|
||||
color: var(--app-temp-status-font-color) !important;
|
||||
}
|
||||
.temp-status-hot .td {
|
||||
color: var(--app-temp-status-font-color) !important;
|
||||
}
|
||||
.temp-status-hot td {
|
||||
color: var(--app-temp-status-font-color) !important;
|
||||
}
|
||||
.temp-status-overheat {
|
||||
background-color: var(--app-temp-status-overheat-color) !important;
|
||||
color: var(--app-temp-status-font-color) !important;
|
||||
}
|
||||
.temp-status-overheat .td {
|
||||
color: var(--app-temp-status-font-color) !important;
|
||||
}
|
||||
.temp-status-overheat td {
|
||||
color: var(--app-temp-status-font-color) !important;
|
||||
}
|
||||
|
||||
.temp-status-temp-area {
|
||||
width: 100%;
|
||||
padding: 0 0 1em 0;
|
||||
display: flex;
|
||||
-webkit-align-items: flex-start;
|
||||
align-items: flex-start;
|
||||
-webkit-justify-content: left;
|
||||
justify-content: left;
|
||||
-webkit-flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
-webkit-flex-direction: row;
|
||||
flex-direction: row;
|
||||
}
|
||||
.temp-status-list-item {
|
||||
display: inline-block;
|
||||
flex-grow: 0;
|
||||
-webkit-flex-grow 0;
|
||||
flex-shrink: 1;
|
||||
-webkit-flex-shrink 1;
|
||||
width: 29em;
|
||||
word-wrap: break-word;
|
||||
margin: 0px 4px 4px 0 !important;
|
||||
padding: 4px;
|
||||
border: 1px solid;
|
||||
border-color: transparent;
|
||||
border-color: var(--app-temp-status-border-color);
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.temp-status-temp-value {
|
||||
display: inline-block;
|
||||
margin-left: 0.5em !important;
|
||||
width: 4em;
|
||||
text-align: left;
|
||||
}
|
||||
.temp-status-sensor-name {
|
||||
display: inline-block;
|
||||
padding-left: 1.5em;
|
||||
font-size: 95%;
|
||||
}
|
||||
|
||||
#temp-status-buttons-wrapper {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
.temp-status-button {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
margin: 2px 4px 2px 0 !important;
|
||||
padding: 3px 5px;
|
||||
border: 1px solid;
|
||||
border-color: transparent;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
opacity: 0.7;
|
||||
background-color: rgba(100 100 100 / 0.2);
|
||||
}
|
||||
.temp-status-button:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
.temp-status-button:active {
|
||||
opacity: 1.0;
|
||||
}
|
||||
.temp-status-hide-item {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
margin: 0 0.5em 0 0 !important;
|
||||
padding: 1px 5px;
|
||||
border: 1px dotted;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
opacity: 0.6;
|
||||
background-color: rgba(100 100 100 / 0.2);
|
||||
font-weight: bold;
|
||||
}
|
||||
.temp-status-hide-item:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
.temp-status-hide-item:active {
|
||||
opacity: 1.0;
|
||||
}
|
||||
`));
|
||||
|
||||
return baseclass.extend({
|
||||
title : _('Temperature'),
|
||||
|
||||
viewName : 'temp-status',
|
||||
|
||||
tempHot : 95,
|
||||
|
||||
tempOverheat : 105,
|
||||
|
||||
sensorsData : null,
|
||||
|
||||
tempData : null,
|
||||
|
||||
sensorsPath : [],
|
||||
|
||||
hiddenItems : new Set(),
|
||||
|
||||
hiddenNum : E('span', {}),
|
||||
|
||||
tempTable : E('table', { 'class': 'table' }),
|
||||
|
||||
tempArea : E('div', { 'class': 'temp-status-temp-area' }),
|
||||
|
||||
tempView : E('div', {}),
|
||||
|
||||
viewType : 'table',
|
||||
|
||||
callSensors : rpc.declare({
|
||||
object: 'luci.temp-status',
|
||||
method: 'getSensors',
|
||||
expect: { '': {} },
|
||||
}),
|
||||
|
||||
callTempData: rpc.declare({
|
||||
object: 'luci.temp-status',
|
||||
method: 'getTempData',
|
||||
params: [ 'tpaths' ],
|
||||
expect: { '': {} },
|
||||
}),
|
||||
|
||||
formatTemp(mc) {
|
||||
return Number((mc / 1000).toFixed(1));
|
||||
},
|
||||
|
||||
sortFunc(a, b) {
|
||||
return (a.number > b.number) ? 1 : (a.number < b.number) ? -1 : 0;
|
||||
},
|
||||
|
||||
restoreSettingsFromLocalStorage() {
|
||||
let hiddenItems = localStorage.getItem(`luci-app-${this.viewName}-hiddenItems`);
|
||||
if(hiddenItems) {
|
||||
this.hiddenItems = new Set(hiddenItems.split(','));
|
||||
};
|
||||
let view = localStorage.getItem(`luci-app-${this.viewName}-view`);
|
||||
if(view) {
|
||||
this.viewType = view;
|
||||
};
|
||||
},
|
||||
|
||||
saveSettingsToLocalStorage() {
|
||||
localStorage.setItem(
|
||||
`luci-app-${this.viewName}-hiddenItems`, Array.from(this.hiddenItems).join(','));
|
||||
localStorage.setItem(
|
||||
`luci-app-${this.viewName}-view`, this.viewType);
|
||||
},
|
||||
|
||||
makeTempTableContent() {
|
||||
this.tempTable.innerHTML = '';
|
||||
this.tempTable.append(
|
||||
E('tr', { 'class': 'tr table-titles' }, [
|
||||
E('th', { 'class': 'th left', 'width': '33%' }, _('Sensor')),
|
||||
E('th', { 'class': 'th left' }, _('Temperature')),
|
||||
E('th', { 'class': 'th right', 'width': '1%' }, ' '),
|
||||
])
|
||||
);
|
||||
|
||||
if(this.sensorsData && this.tempData) {
|
||||
for(let [k, v] of Object.entries(this.sensorsData)) {
|
||||
v.sort(this.sortFunc);
|
||||
|
||||
for(let i of Object.values(v)) {
|
||||
let sensor = i.title || i.item;
|
||||
|
||||
if(i.sources === undefined) {
|
||||
continue;
|
||||
};
|
||||
|
||||
i.sources.sort(this.sortFunc);
|
||||
|
||||
for(let j of i.sources) {
|
||||
if(this.hiddenItems.has(j.path)) {
|
||||
continue;
|
||||
};
|
||||
|
||||
let temp = this.tempData[j.path];
|
||||
let name = (j.label !== undefined) ? sensor + " / " + j.label :
|
||||
(j.item !== undefined) ? sensor + " / " + j.item.replace(/_input$/, "") : sensor
|
||||
|
||||
if(temp !== undefined && temp !== null) {
|
||||
temp = this.formatTemp(temp);
|
||||
};
|
||||
|
||||
let tempHot = NaN;
|
||||
let tempOverheat = NaN;
|
||||
let tpoints = j.tpoints;
|
||||
let tpointsString = '';
|
||||
|
||||
if(tpoints) {
|
||||
for(let i of Object.values(tpoints)) {
|
||||
let t = this.formatTemp(i.temp);
|
||||
tpointsString += ` ${i.type}: ${t} °C`;
|
||||
|
||||
if(i.type == 'max' || i.type == 'critical' || i.type == 'emergency') {
|
||||
if(!(tempOverheat <= t)) {
|
||||
tempOverheat = t;
|
||||
};
|
||||
}
|
||||
else if(i.type == 'hot') {
|
||||
tempHot = t;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
if(isNaN(tempHot) && isNaN(tempOverheat)) {
|
||||
tempHot = this.tempHot;
|
||||
tempOverheat = this.tempOverheat;
|
||||
};
|
||||
|
||||
let rowStyle = (temp >= tempOverheat) ? ' temp-status-overheat':
|
||||
(temp >= tempHot) ? ' temp-status-hot' : '';
|
||||
|
||||
this.tempTable.append(
|
||||
E('tr', {
|
||||
'class' : 'tr' + rowStyle,
|
||||
'data-path': j.path ,
|
||||
}, [
|
||||
E('td', {
|
||||
'class' : 'td left',
|
||||
'data-title': _('Sensor')
|
||||
},
|
||||
(tpointsString.length > 0) ?
|
||||
`<span style="cursor:help; border-bottom:1px dotted" data-tooltip="${tpointsString}">${name}</span>` :
|
||||
name
|
||||
),
|
||||
E('td', {
|
||||
'class' : 'td left',
|
||||
'data-title': _('Temperature')
|
||||
},
|
||||
(temp === undefined || temp === null) ? '-' : temp + ' °C'
|
||||
),
|
||||
E('td', {
|
||||
'class' : 'td right',
|
||||
'data-title': _('Hide'),
|
||||
'title' : _('Hide'),
|
||||
},
|
||||
E('span', {
|
||||
'class': 'temp-status-hide-item',
|
||||
'title': _('Hide'),
|
||||
'click': () => this.hideItem(j.path),
|
||||
}, 'Χ'),
|
||||
),
|
||||
])
|
||||
);
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
if(this.tempTable.childNodes.length == 1) {
|
||||
this.tempTable.append(
|
||||
E('tr', { 'class': 'tr placeholder' },
|
||||
E('td', { 'class': 'td' },
|
||||
E('em', {}, _('No temperature sensors available'))
|
||||
)
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
return this.tempTable;
|
||||
},
|
||||
|
||||
makeTempAreaContent() {
|
||||
this.tempArea.innerHTML = '';
|
||||
|
||||
for(let [k, v] of Object.entries(this.sensorsData)) {
|
||||
v.sort(this.sortFunc);
|
||||
|
||||
for(let i of Object.values(v)) {
|
||||
let sensor = i.title || i.item;
|
||||
|
||||
if(i.sources === undefined) {
|
||||
continue;
|
||||
};
|
||||
|
||||
i.sources.sort(this.sortFunc);
|
||||
|
||||
for(let j of i.sources) {
|
||||
if(this.hiddenItems.has(j.path)) {
|
||||
continue;
|
||||
};
|
||||
|
||||
let temp = this.tempData[j.path];
|
||||
let name = (j.label !== undefined) ? sensor + " / " + j.label :
|
||||
(j.item !== undefined) ? sensor + " / " + j.item.replace(/_input$/, "") : sensor
|
||||
|
||||
if(temp !== undefined && temp !== null) {
|
||||
temp = this.formatTemp(temp);
|
||||
};
|
||||
|
||||
let tempHot = NaN;
|
||||
let tempOverheat = NaN;
|
||||
let tpoints = j.tpoints;
|
||||
let tpointsString = '';
|
||||
|
||||
if(tpoints) {
|
||||
for(let i of Object.values(tpoints)) {
|
||||
let t = this.formatTemp(i.temp);
|
||||
tpointsString += ` ${i.type}: ${t} °C`;
|
||||
|
||||
if(i.type == 'max' || i.type == 'critical' || i.type == 'emergency') {
|
||||
if(!(tempOverheat <= t)) {
|
||||
tempOverheat = t;
|
||||
};
|
||||
}
|
||||
else if(i.type == 'hot') {
|
||||
tempHot = t;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
if(isNaN(tempHot) && isNaN(tempOverheat)) {
|
||||
tempHot = this.tempHot;
|
||||
tempOverheat = this.tempOverheat;
|
||||
};
|
||||
|
||||
let itemStyle = (temp >= tempOverheat) ? ' temp-status-overheat':
|
||||
(temp >= tempHot) ? ' temp-status-hot' : '';
|
||||
|
||||
this.tempArea.append(
|
||||
E('div', { 'class': 'temp-status-list-item' + itemStyle }, [
|
||||
E('span', {
|
||||
'class': 'temp-status-hide-item',
|
||||
'title': _('Hide'),
|
||||
'click': () => this.hideItem(j.path),
|
||||
}, 'Χ'),
|
||||
E('span', {
|
||||
'class': 'temp-status-temp-value',
|
||||
}, (temp === undefined || temp === null) ? '-' : temp + ' °C'),
|
||||
E('span', {
|
||||
'class': 'temp-status-sensor-name'
|
||||
}, (tpointsString.length > 0) ?
|
||||
`<span style="cursor:help; border-bottom:1px dotted" data-tooltip="${tpointsString}">${name}</span>` :
|
||||
name
|
||||
),
|
||||
])
|
||||
);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
if(this.tempArea.childNodes.length == 0) {
|
||||
this.tempArea.append(
|
||||
E('em', {}, _('No temperature sensors available'))
|
||||
);
|
||||
};
|
||||
|
||||
return this.tempArea;
|
||||
},
|
||||
|
||||
makeViewContent() {
|
||||
this.tempView.innerHTML = '';
|
||||
this.tempView.append((this.viewType == 'list') ? this.makeTempAreaContent() : this.makeTempTableContent());
|
||||
this.hiddenNum.textContent = this.hiddenItems.size;
|
||||
let unhide = document.getElementById('temp-status-unhide-all');
|
||||
if(unhide) {
|
||||
unhide.style.display = (this.hiddenItems.size > 0) ? 'inline-block' : 'none';
|
||||
};
|
||||
},
|
||||
|
||||
hideItem(path) {
|
||||
this.hiddenItems.add(path);
|
||||
this.saveSettingsToLocalStorage();
|
||||
this.makeViewContent();
|
||||
},
|
||||
|
||||
unhideAllItems() {
|
||||
this.hiddenItems.clear();
|
||||
this.saveSettingsToLocalStorage();
|
||||
this.makeViewContent();
|
||||
},
|
||||
|
||||
switchView() {
|
||||
this.tempView.innerHTML = '';
|
||||
this.viewType = (this.viewType == 'list') ? 'table' : 'list'
|
||||
this.saveSettingsToLocalStorage();
|
||||
this.makeViewContent();
|
||||
},
|
||||
|
||||
load() {
|
||||
this.restoreSettingsFromLocalStorage();
|
||||
if(this.sensorsData) {
|
||||
return (this.sensorsPath.length > 0) ?
|
||||
L.resolveDefault(this.callTempData(this.sensorsPath), null) :
|
||||
Promise.resolve(null);
|
||||
} else {
|
||||
return L.resolveDefault(this.callSensors(), null);
|
||||
};
|
||||
},
|
||||
|
||||
render(data) {
|
||||
if(data) {
|
||||
if(!this.sensorsData) {
|
||||
this.sensorsData = data.sensors;
|
||||
this.sensorsPath = data.temp && new Array(...Object.keys(data.temp));
|
||||
};
|
||||
this.tempData = data.temp;
|
||||
};
|
||||
|
||||
if(!this.sensorsData || !this.tempData) {
|
||||
return;
|
||||
};
|
||||
|
||||
this.makeViewContent();
|
||||
|
||||
return E('div', { 'class': 'cbi-section' }, [
|
||||
E('div', { 'id': 'temp-status-buttons-wrapper' }, [
|
||||
E('span', {
|
||||
'class': 'temp-status-button',
|
||||
'click': () => this.switchView(),
|
||||
}, _('Switch view')),
|
||||
E('span', {
|
||||
'id' : 'temp-status-unhide-all',
|
||||
'class': 'temp-status-button',
|
||||
'style': `display:${(this.hiddenItems.size > 0) ? 'inline-block' : 'none'}`,
|
||||
'click': () => this.unhideAllItems(),
|
||||
}, [
|
||||
_('Show hidden sensors'),
|
||||
' (',
|
||||
this.hiddenNum,
|
||||
')',
|
||||
])
|
||||
]),
|
||||
this.tempView,
|
||||
]);
|
||||
},
|
||||
});
|
||||
Reference in new issue
Block a user