Add admin presence timing settings
This commit is contained in:
@@ -1328,6 +1328,16 @@ label { display: grid; gap: 6px; color: var(--muted); font-size: 13px; }
|
||||
padding: 0;
|
||||
accent-color: var(--brand);
|
||||
}
|
||||
.seconds-field {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 7px;
|
||||
align-items: center;
|
||||
}
|
||||
.seconds-field span {
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
}
|
||||
pre {
|
||||
white-space: pre-wrap;
|
||||
overflow: auto;
|
||||
|
||||
@@ -181,6 +181,20 @@
|
||||
</section>
|
||||
<section class="settings-tab-panel" data-settings-panel="admin">
|
||||
<div class="admin-preferences">
|
||||
<fieldset class="effect-settings presence-settings">
|
||||
<legend>Signalizace navstevniku</legend>
|
||||
<p class="ai-help">Zelena znamena aktivni. Po necinosti se prepne na oranzovou a po dalsim limitu na sedou.</p>
|
||||
<div class="settings-top-row">
|
||||
<label>Zelena do
|
||||
<span class="seconds-field"><input id="presenceActiveSeconds" type="number" min="10" max="3600" step="5"><span>s</span></span>
|
||||
</label>
|
||||
<label>Seda po
|
||||
<span class="seconds-field"><input id="presenceOfflineSeconds" type="number" min="20" max="7200" step="5"><span>s</span></span>
|
||||
</label>
|
||||
</div>
|
||||
<small id="presenceStatus" class="full-row">Oranzova je cas mezi zelenou a sedou.</small>
|
||||
<button id="savePresenceSettings" class="full-row" type="button">Ulozit signalizaci</button>
|
||||
</fieldset>
|
||||
<fieldset class="effect-settings sound-settings">
|
||||
<legend>BO zvuk</legend>
|
||||
<label class="setting-switch full-row">Zvuk notifikaci <input id="adminSoundToggleSettings" type="checkbox"></label>
|
||||
|
||||
@@ -71,6 +71,9 @@ $("#logoutButton").addEventListener("click", async () => {
|
||||
|
||||
$("#settingsButton").addEventListener("click", () => $("#settingsPanel").classList.toggle("hidden"));
|
||||
$("#closeSettingsButton").addEventListener("click", () => $("#settingsPanel").classList.add("hidden"));
|
||||
$("#presenceActiveSeconds").addEventListener("input", markPresenceSettingsDirty);
|
||||
$("#presenceOfflineSeconds").addEventListener("input", markPresenceSettingsDirty);
|
||||
$("#savePresenceSettings").addEventListener("click", savePresenceSettings);
|
||||
$("#adminSoundToggle").addEventListener("click", () => {
|
||||
setAdminSoundMuted(!state.soundMuted);
|
||||
});
|
||||
@@ -522,6 +525,7 @@ function renderSite() {
|
||||
? `Klic ulozeny (${s.translations.openaiApiKeyMasked || "sk-..."})`
|
||||
: "Klic neni ulozeny. Bez nej AI preklady nepobezi.";
|
||||
renderModelOptions(s.translations?.model || "gpt-5-mini");
|
||||
renderPresenceSettings(s.adminPresence || {});
|
||||
renderTelegramSettings(s.telegram || {});
|
||||
}
|
||||
|
||||
@@ -757,6 +761,52 @@ function setOpenAiStatus(message) {
|
||||
$("#openaiApiKeyStatus").textContent = message;
|
||||
}
|
||||
|
||||
function renderPresenceSettings(settings) {
|
||||
const normalized = normalizePresenceSettings(settings);
|
||||
$("#presenceActiveSeconds").value = normalized.activeSeconds;
|
||||
$("#presenceOfflineSeconds").value = normalized.offlineSeconds;
|
||||
setPresenceStatus(`Oranzova: ${normalized.activeSeconds}-${normalized.offlineSeconds} s necinosti.`);
|
||||
}
|
||||
|
||||
function markPresenceSettingsDirty() {
|
||||
const normalized = normalizePresenceSettings({
|
||||
activeSeconds: $("#presenceActiveSeconds").value,
|
||||
offlineSeconds: $("#presenceOfflineSeconds").value
|
||||
});
|
||||
setPresenceStatus(`Neulozeno. Oranzova bude ${normalized.activeSeconds}-${normalized.offlineSeconds} s.`);
|
||||
}
|
||||
|
||||
async function savePresenceSettings() {
|
||||
if (!state.site) return;
|
||||
const normalized = normalizePresenceSettings({
|
||||
activeSeconds: $("#presenceActiveSeconds").value,
|
||||
offlineSeconds: $("#presenceOfflineSeconds").value
|
||||
});
|
||||
setPresenceStatus("Ukladam signalizaci...");
|
||||
const settings = structuredClone(state.site.settings);
|
||||
settings.adminPresence = normalized;
|
||||
await saveSite({ settings, isOnline: state.site.isOnline });
|
||||
renderPresenceSettings(state.site.settings.adminPresence || normalized);
|
||||
await Promise.all([loadConversations(), loadVisitors()]);
|
||||
setPresenceStatus(`Ulozeno. Oranzova: ${normalized.activeSeconds}-${normalized.offlineSeconds} s.`);
|
||||
}
|
||||
|
||||
function normalizePresenceSettings(value = {}) {
|
||||
const activeSeconds = clampNumber(value.activeSeconds, 10, 3600, 30);
|
||||
const offlineSeconds = Math.max(clampNumber(value.offlineSeconds, 20, 7200, 120), activeSeconds + 10);
|
||||
return { activeSeconds, offlineSeconds };
|
||||
}
|
||||
|
||||
function clampNumber(value, min, max, fallback) {
|
||||
const number = Number(value);
|
||||
if (!Number.isFinite(number)) return fallback;
|
||||
return Math.min(max, Math.max(min, Math.round(number)));
|
||||
}
|
||||
|
||||
function setPresenceStatus(message) {
|
||||
$("#presenceStatus").textContent = message;
|
||||
}
|
||||
|
||||
function renderTelegramSettings(settings) {
|
||||
$("#telegramEnabled").checked = Boolean(settings.enabled);
|
||||
$("#telegramOperatorName").value = settings.operatorName || "Alex";
|
||||
|
||||
Reference in New Issue
Block a user