mirror of
https://github.com/Laxilef/OTGateway.git
synced 2025-12-11 02:34:29 +05:00
feat: added multilanguage for portal
This commit is contained in:
425
src_data/pages/dashboard.html
Normal file
425
src_data/pages/dashboard.html
Normal file
@@ -0,0 +1,425 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title data-i18n>dashboard.title</title>
|
||||
<link rel="stylesheet" href="/static/app.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header class="container">
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="/">
|
||||
<div class="logo" data-i18n>logo</div>
|
||||
</a></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<!--<li><a href="https://github.com/Laxilef/OTGateway/wiki" role="button" class="secondary" target="_blank">Help</a></li>-->
|
||||
<li>
|
||||
<select id="lang" aria-label="Lang">
|
||||
<option value="en" selected>EN</option>
|
||||
<option value="ru">RU</option>
|
||||
</select>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main class="container">
|
||||
<article>
|
||||
<hgroup>
|
||||
<h2 data-i18n>dashboard.name</h2>
|
||||
<p></p>
|
||||
</hgroup>
|
||||
|
||||
<div id="dashboard-busy" aria-busy="true"></div>
|
||||
<div id="dashboard-container" class="hidden">
|
||||
<details open>
|
||||
<summary><b data-i18n>dashboard.section.control</b></summary>
|
||||
<div class="grid">
|
||||
<div class="thermostat" id="thermostat-heating">
|
||||
<div class="thermostat-header" data-i18n>dashboard.thermostat.heating</div>
|
||||
<div class="thermostat-temp">
|
||||
<div class="thermostat-temp-target"><span id="thermostat-heating-target"></span> <span class="temp-unit"></span></div>
|
||||
<div class="thermostat-temp-current"><span data-i18n>dashboard.thermostat.temp.current</span>: <span id="thermostat-heating-current"></span> <span class="temp-unit"></span></div>
|
||||
</div>
|
||||
<div class="thermostat-minus"><button id="thermostat-heating-minus" class="outline"><i class="icons-down"></i></button></div>
|
||||
<div class="thermostat-plus"><button id="thermostat-heating-plus" class="outline"><i class="icons-up"></i></button></div>
|
||||
<div class="thermostat-control">
|
||||
<input type="checkbox" role="switch" id="thermostat-heating-enabled" value="true">
|
||||
<label htmlFor="thermostat-heating-enabled" data-i18n>dashboard.thermostat.enable</label>
|
||||
|
||||
<input type="checkbox" role="switch" id="thermostat-heating-turbo" value="true">
|
||||
<label htmlFor="thermostat-heating-turbo" data-i18n>dashboard.thermostat.turbo</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="thermostat" id="thermostat-dhw">
|
||||
<div class="thermostat-header" data-i18n>dashboard.thermostat.dhw</div>
|
||||
<div class="thermostat-temp">
|
||||
<div class="thermostat-temp-target"><span id="thermostat-dhw-target"></span> <span class="temp-unit"></span></div>
|
||||
<div class="thermostat-temp-current"><span data-i18n>dashboard.thermostat.temp.current</span>: <span id="thermostat-dhw-current"></span> <span class="temp-unit"></span></div>
|
||||
</div>
|
||||
<div class="thermostat-minus"><button class="outline" id="thermostat-dhw-minus"><i class="icons-down"></i></button></div>
|
||||
<div class="thermostat-plus"><button class="outline" id="thermostat-dhw-plus"><i class="icons-up"></i></button></div>
|
||||
<div class="thermostat-control">
|
||||
<input type="checkbox" role="switch" id="thermostat-dhw-enabled" value="true">
|
||||
<label htmlFor="thermostat-dhw-enabled" data-i18n>dashboard.thermostat.enable</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<hr />
|
||||
|
||||
<details>
|
||||
<summary><b data-i18n>dashboard.section.states</b></summary>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row" data-i18n>dashboard.state.ot</th>
|
||||
<td><input type="radio" id="ot-connected" aria-invalid="false" checked disabled /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" data-i18n>dashboard.state.mqtt</th>
|
||||
<td><input type="radio" id="mqtt-connected" aria-invalid="false" checked disabled /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" data-i18n>dashboard.state.emergency</th>
|
||||
<td><input type="radio" id="ot-emergency" aria-invalid="false" checked disabled /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" data-i18n>dashboard.state.heating</th>
|
||||
<td><input type="radio" id="ot-heating" aria-invalid="false" checked disabled /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" data-i18n>dashboard.state.dhw</th>
|
||||
<td><input type="radio" id="ot-dhw" aria-invalid="false" checked disabled /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" data-i18n>dashboard.state.flame</th>
|
||||
<td><input type="radio" id="ot-flame" aria-invalid="false" checked disabled /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" data-i18n>dashboard.state.fault</th>
|
||||
<td><input type="radio" id="ot-fault" aria-invalid="false" checked disabled /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" data-i18n>dashboard.state.diag</th>
|
||||
<td><input type="radio" id="ot-diagnostic" aria-invalid="false" checked disabled /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" data-i18n>dashboard.state.extpump</th>
|
||||
<td><input type="radio" id="ot-external-pump" aria-invalid="false" checked disabled /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" data-i18n>dashboard.state.modulation</th>
|
||||
<td><b id="ot-modulation"></b> %</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" data-i18n>dashboard.state.pressure</th>
|
||||
<td><b id="ot-pressure"></b> <span class="pressure-unit"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" data-i18n>dashboard.state.dhwFlowRate</th>
|
||||
<td><b id="ot-dhw-flow-rate"></b> <span class="volume-unit"></span>/min</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" data-i18n>dashboard.state.faultCode</th>
|
||||
<td><b id="ot-fault-code"></b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" data-i18n>dashboard.state.indoorTemp</th>
|
||||
<td><b id="indoor-temp"></b> <span class="temp-unit"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" data-i18n>dashboard.state.outdoorTemp</th>
|
||||
<td><b id="outdoor-temp"></b> <span class="temp-unit"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" data-i18n>dashboard.state.heatingTemp</th>
|
||||
<td><b id="heating-temp"></b> <span class="temp-unit"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" data-i18n>dashboard.state.heatingSetpointTemp</th>
|
||||
<td><b id="heating-setpoint-temp"></b> <span class="temp-unit"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" data-i18n>dashboard.state.heatingReturnTemp</th>
|
||||
<td><b id="heating-return-temp"></b> <span class="temp-unit"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" data-i18n>dashboard.state.dhwTemp</th>
|
||||
<td><b id="dhw-temp"></b> <span class="temp-unit"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" data-i18n>dashboard.state.exhaustTemp</th>
|
||||
<td><b id="exhaust-temp"></b> <span class="temp-unit"></span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</details>
|
||||
|
||||
<hr />
|
||||
|
||||
<details>
|
||||
<summary><b data-i18n>dashboard.section.otDiag</b></summary>
|
||||
<pre><b>Vendor:</b> <span id="slave-vendor"></span>
|
||||
<b>Member ID:</b> <span id="slave-member-id"></span>
|
||||
<b>Flags:</b> <span id="slave-flags"></span>
|
||||
<b>Type:</b> <span id="slave-type"></span>
|
||||
<b>Version:</b> <span id="slave-version"></span>
|
||||
<b>OT version:</b> <span id="slave-ot-version"></span>
|
||||
<b>Heating limits:</b> <span id="heating-min-temp"></span>...<span id="heating-max-temp"></span> <span class="temp-unit"></span>
|
||||
<b>DHW limits:</b> <span id="dhw-min-temp"></span>...<span id="dhw-max-temp"></span> <span class="temp-unit"></span></pre>
|
||||
</details>
|
||||
</div>
|
||||
</article>
|
||||
</main>
|
||||
|
||||
<footer class="container">
|
||||
<small>
|
||||
<b>Made by Laxilef</b>
|
||||
• <a href="https://github.com/Laxilef/OTGateway/blob/master/LICENSE" target="_blank" class="secondary" data-i18n>nav.license</a>
|
||||
• <a href="https://github.com/Laxilef/OTGateway/blob/master/" target="_blank" class="secondary" data-i18n>nav.source</a>
|
||||
• <a href="https://github.com/Laxilef/OTGateway/wiki" target="_blank" class="secondary" data-i18n>nav.help</a>
|
||||
• <a href="https://github.com/Laxilef/OTGateway/issues" target="_blank" class="secondary" data-i18n>nav.issues</a>
|
||||
• <a href="https://github.com/Laxilef/OTGateway/releases" target="_blank" class="secondary" data-i18n>nav.releases</a>
|
||||
</small>
|
||||
</footer>
|
||||
|
||||
<script src="/static/app.js"></script>
|
||||
<script>
|
||||
let modifiedTime = null;
|
||||
let noRegulators;
|
||||
let prevSettings;
|
||||
let newSettings = {
|
||||
heating: {
|
||||
enable: false,
|
||||
turbo: false,
|
||||
target: 0
|
||||
},
|
||||
dhw: {
|
||||
enable: false,
|
||||
target: 0
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
const lang = new Lang(document.getElementById('lang'));
|
||||
lang.build();
|
||||
|
||||
document.querySelector('#thermostat-heating-minus').addEventListener('click', (event) => {
|
||||
if (!prevSettings) {
|
||||
return;
|
||||
}
|
||||
|
||||
newSettings.heating.target -= 0.5;
|
||||
modifiedTime = Date.now();
|
||||
|
||||
let minTemp;
|
||||
if (noRegulators) {
|
||||
minTemp = prevSettings.heating.minTemp;
|
||||
} else {
|
||||
minTemp = prevSettings.system.unitSystem == 0 ? 5 : 41;
|
||||
}
|
||||
|
||||
if (prevSettings && newSettings.heating.target < minTemp) {
|
||||
newSettings.heating.target = minTemp;
|
||||
}
|
||||
|
||||
setValue('#thermostat-heating-target', newSettings.heating.target);
|
||||
});
|
||||
|
||||
document.querySelector('#thermostat-heating-plus').addEventListener('click', (event) => {
|
||||
if (!prevSettings) {
|
||||
return;
|
||||
}
|
||||
|
||||
newSettings.heating.target += 0.5;
|
||||
modifiedTime = Date.now();
|
||||
|
||||
let maxTemp;
|
||||
if (noRegulators) {
|
||||
maxTemp = prevSettings.heating.maxTemp;
|
||||
} else {
|
||||
maxTemp = prevSettings.system.unitSystem == 0 ? 30 : 86;
|
||||
}
|
||||
|
||||
if (prevSettings && newSettings.heating.target > maxTemp) {
|
||||
newSettings.heating.target = maxTemp;
|
||||
}
|
||||
|
||||
setValue('#thermostat-heating-target', newSettings.heating.target);
|
||||
});
|
||||
|
||||
document.querySelector('#thermostat-dhw-minus').addEventListener('click', (event) => {
|
||||
if (!prevSettings) {
|
||||
return;
|
||||
}
|
||||
|
||||
newSettings.dhw.target -= 1.0;
|
||||
modifiedTime = Date.now();
|
||||
|
||||
if (newSettings.dhw.target < prevSettings.dhw.minTemp) {
|
||||
newSettings.dhw.target = prevSettings.dhw.minTemp;
|
||||
}
|
||||
|
||||
setValue('#thermostat-dhw-target', newSettings.dhw.target);
|
||||
});
|
||||
|
||||
document.querySelector('#thermostat-dhw-plus').addEventListener('click', (event) => {
|
||||
if (!prevSettings) {
|
||||
return;
|
||||
}
|
||||
|
||||
newSettings.dhw.target += 1.0;
|
||||
modifiedTime = Date.now();
|
||||
|
||||
if (newSettings.dhw.target > prevSettings.dhw.maxTemp) {
|
||||
newSettings.dhw.target = prevSettings.dhw.maxTemp;
|
||||
}
|
||||
|
||||
setValue('#thermostat-dhw-target', newSettings.dhw.target);
|
||||
});
|
||||
|
||||
document.querySelector('#thermostat-heating-enabled').addEventListener('change', (event) => {
|
||||
modifiedTime = Date.now();
|
||||
newSettings.heating.enable = event.currentTarget.checked;
|
||||
});
|
||||
|
||||
document.querySelector('#thermostat-heating-turbo').addEventListener('change', (event) => {
|
||||
modifiedTime = Date.now();
|
||||
newSettings.heating.turbo = event.currentTarget.checked;
|
||||
});
|
||||
|
||||
document.querySelector('#thermostat-dhw-enabled').addEventListener('change', (event) => {
|
||||
modifiedTime = Date.now();
|
||||
newSettings.dhw.enable = event.currentTarget.checked;
|
||||
});
|
||||
|
||||
setTimeout(async function onLoadPage() {
|
||||
if (modifiedTime) {
|
||||
if ((Date.now() - modifiedTime) < 5000) {
|
||||
setTimeout(onLoadPage, 1000);
|
||||
return;
|
||||
}
|
||||
|
||||
modifiedTime = null;
|
||||
}
|
||||
|
||||
// settings
|
||||
try {
|
||||
let modified = prevSettings && (
|
||||
(prevSettings.heating.enable != newSettings.heating.enable)
|
||||
|| (prevSettings.heating.turbo != newSettings.heating.turbo)
|
||||
|| (prevSettings.heating.target != newSettings.heating.target)
|
||||
|| (prevSettings.opentherm.dhwPresent && prevSettings.dhw.enable != newSettings.dhw.enable)
|
||||
|| (prevSettings.opentherm.dhwPresent && prevSettings.dhw.target != newSettings.dhw.target)
|
||||
);
|
||||
|
||||
if (modified) {
|
||||
console.log(newSettings);
|
||||
}
|
||||
|
||||
let parameters = { cache: 'no-cache' };
|
||||
if (modified) {
|
||||
parameters.method = "POST";
|
||||
parameters.body = JSON.stringify(newSettings);
|
||||
}
|
||||
|
||||
const response = await fetch('/api/settings', parameters);
|
||||
if (!response.ok) {
|
||||
throw new Error('Response not valid');
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
noRegulators = !result.opentherm.nativeHeatingControl && !result.equitherm.enable && !result.pid.enable;
|
||||
prevSettings = result;
|
||||
newSettings.heating.enable = result.heating.enable;
|
||||
newSettings.heating.turbo = result.heating.turbo;
|
||||
newSettings.heating.target = result.heating.target;
|
||||
newSettings.dhw.enable = result.dhw.enable;
|
||||
newSettings.dhw.target = result.dhw.target;
|
||||
|
||||
if (result.opentherm.dhwPresent) {
|
||||
show('#thermostat-dhw');
|
||||
} else {
|
||||
hide('#thermostat-dhw');
|
||||
}
|
||||
|
||||
setCheckboxValue('#thermostat-heating-enabled', result.heating.enable);
|
||||
setCheckboxValue('#thermostat-heating-turbo', result.heating.turbo);
|
||||
setValue('#thermostat-heating-target', result.heating.target);
|
||||
|
||||
setCheckboxValue('#thermostat-dhw-enabled', result.dhw.enable);
|
||||
setValue('#thermostat-dhw-target', result.dhw.target);
|
||||
|
||||
setValue('.temp-unit', temperatureUnit(result.system.unitSystem));
|
||||
setValue('.pressure-unit', pressureUnit(result.system.unitSystem));
|
||||
setValue('.volume-unit', volumeUnit(result.system.unitSystem));
|
||||
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
// vars
|
||||
try {
|
||||
const response = await fetch('/api/vars', { cache: 'no-cache' });
|
||||
if (!response.ok) {
|
||||
throw new Error('Response not valid');
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
setValue('#thermostat-heating-current', noRegulators ? result.temperatures.heating : result.temperatures.indoor);
|
||||
setValue('#thermostat-dhw-current', result.temperatures.dhw);
|
||||
|
||||
setState('#ot-connected', result.states.otStatus);
|
||||
setState('#ot-emergency', result.states.emergency);
|
||||
setState('#ot-heating', result.states.heating);
|
||||
setState('#ot-dhw', result.states.dhw);
|
||||
setState('#ot-flame', result.states.flame);
|
||||
setState('#ot-fault', result.states.fault);
|
||||
setState('#ot-diagnostic', result.states.diagnostic);
|
||||
setState('#ot-external-pump', result.states.externalPump);
|
||||
setState('#mqtt-connected', result.states.mqtt);
|
||||
|
||||
setValue('#ot-modulation', result.sensors.modulation);
|
||||
setValue('#ot-pressure', result.sensors.pressure);
|
||||
setValue('#ot-dhw-flow-rate', result.sensors.dhwFlowRate);
|
||||
setValue('#ot-fault-code', result.sensors.faultCode ? ("E" + result.sensors.faultCode) : "-");
|
||||
|
||||
setValue('#indoor-temp', result.temperatures.indoor);
|
||||
setValue('#outdoor-temp', result.temperatures.outdoor);
|
||||
setValue('#heating-temp', result.temperatures.heating);
|
||||
setValue('#heating-return-temp', result.temperatures.heatingReturn);
|
||||
setValue('#dhw-temp', result.temperatures.dhw);
|
||||
setValue('#exhaust-temp', result.temperatures.exhaust);
|
||||
|
||||
setValue('#heating-min-temp', result.parameters.heatingMinTemp);
|
||||
setValue('#heating-max-temp', result.parameters.heatingMaxTemp);
|
||||
setValue('#heating-setpoint-temp', result.parameters.heatingSetpoint);
|
||||
setValue('#dhw-min-temp', result.parameters.dhwMinTemp);
|
||||
setValue('#dhw-max-temp', result.parameters.dhwMaxTemp);
|
||||
|
||||
setValue('#slave-member-id', result.parameters.slaveMemberId);
|
||||
setValue('#slave-vendor', memberIdToVendor(result.parameters.slaveMemberId));
|
||||
|
||||
setValue('#slave-flags', result.parameters.slaveFlags);
|
||||
setValue('#slave-type', result.parameters.slaveType);
|
||||
setValue('#slave-version', result.parameters.slaveVersion);
|
||||
setValue('#slave-ot-version', result.parameters.slaveOtVersion);
|
||||
setBusy('#dashboard-busy', '#dashboard-container', false);
|
||||
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
setTimeout(onLoadPage, 10000);
|
||||
}, 1000);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user