Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified public/img/admin/app-edit-badge-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/img/admin/app-edit-badge.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/img/admin/app-edit-labels-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/img/admin/app-edit-labels.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/img/dashboard/badge-labels.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/img/dashboard/badge-list.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
399 changes: 274 additions & 125 deletions public/js/admin-app-form.js

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion public/js/admin-color-control.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { html, raw, setHtml } from '/js/html.js?v=c71f8903';
import { qa, q } from '/js/utils.js?v=b18c93ed';

const CC_SWATCHES = ['#1c1c1e', '#8e8e93', '#f2f2f7', '#ff393c', '#ffcd00', '#35c759', '#0289ff', '#cb30df'];
export const BADGE_DEFAULT = '#1e6ef4';
export const BADGE_SWATCHES = ['#1c1c1e', '#8e8e93', '#f2f2f7', '#ff393c', '#ffcd00', '#35c759', '#1e6ef4', '#cb30df'];
const _ccIco = {
hueLo:
Expand Down Expand Up @@ -158,6 +159,10 @@ export function renderColorControl(
container.appendChild(hidden);
let mode = isSem(value) ? value : 'color';
let showTune = false;
/* The value as it was stored. The sliders are integers, so reading a colour
back out of them shifts it, and an untouched control would save a colour
nobody picked. Cleared the moment the user changes anything. */
let pristine = mode === 'color' ? value : null;
const curHex = () => _hsvToHex(+hEl.value, +sEl.value, +vEl.value);
const _rgb = h => {
const x = _cssToHex(h);
Expand Down Expand Up @@ -195,9 +200,10 @@ export function renderColorControl(
codeRv.textContent = mode === 'color' ? hex : mode === 'dark' ? 'Dark' : 'Light';
codeRv.classList.remove('is-ph');
}
hidden.value = mode === 'color' ? hex : mode;
hidden.value = mode === 'color' ? (pristine ?? hex) : mode;
}
const commit = () => {
pristine = null;
paint();
onChange?.(hidden.value);
};
Expand Down
33 changes: 32 additions & 1 deletion public/js/admin-save-logic.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
// @ts-check
/* Keep this module free of the DOM. The DOM reads stay in doSave. */

const BADGE_DEFAULT = '#1e6ef4';

/* Keep in step with MAX_LABELS in badge-logic.js. */
const MAX_LABELS = 5;

export function cleanId(label, fallback = 'item') {
return (
String(label || '')
Expand Down Expand Up @@ -91,6 +96,21 @@ export function claimFolderChildren(items, folderId, childIds) {
return list;
}

/** One stored Live Activity label. Array order is priority order.

@param {string} path @param {any} [style]
@returns {{ path: string, name?: string, unit?: string, color?: string, min?: number }} */
export function buildActivityLabel(path, style) {
const min = Math.floor(Number(style?.min));
return {
path,
name: style?.name?.trim() || undefined,
unit: style?.unit?.trim() || undefined,
color: style?.color && style.color !== BADGE_DEFAULT ? style.color : undefined,
min: Number.isFinite(min) && min > 1 ? min : undefined,
};
}

/** @param {any} v @param {any} [orig] @param {Iterable<string>} [takenIds] */
export function buildAppItem(v, orig, takenIds = []) {
if (!v.label) return { error: 'Name required' };
Expand All @@ -111,6 +131,15 @@ export function buildAppItem(v, orig, takenIds = []) {
? { enabled: true, label: v.staticLabel.slice(0, 10), color: v.staticColor || 'blue' }
: undefined;
const spaths = v.spaths || [];
const combine = spaths.length >= 2 && !!v.actCombine;
const labels = spaths.length
? spaths.slice(0, MAX_LABELS).map(p => buildActivityLabel(p, v.slabels?.[p]))
: undefined;
const first = combine ? buildActivityLabel('', v.slabels?.[spaths[0]]) : null;
const combinedCustom =
first && (first.color || first.unit || first.min)
? { color: first.color, unit: first.unit, min: first.min }
: undefined;
return {
item: {
id: orig?.id || newItemId(v.label, 'app', takenIds),
Expand All @@ -129,8 +158,10 @@ export function buildAppItem(v, orig, takenIds = []) {
params: v.actParams?.length ? v.actParams : undefined,
headers: v.actHeaders?.length ? v.actHeaders : undefined,
extract: spaths.length === 1 ? spaths[0] : spaths.length > 1 ? spaths.map(p => ({ path: p })) : undefined,
labels: combine ? undefined : labels,
combine: combine || undefined,
interval: Math.max(10, v.actInt),
custom: customObj,
custom: combinedCustom || customObj,
},
staticBadge: staticBadgeObj,
},
Expand Down
3 changes: 3 additions & 0 deletions public/js/admin-state.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ export const state = {
siurl: '',
scol: 'dark',
spaths: [],
/* Live Activity label styling, keyed by value path. */
slabels: Object.create(null),
slegacySum: false,
fnums: [],

_evItem: null,
Expand Down
4 changes: 2 additions & 2 deletions public/js/admin-widget-form.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { state } from '/js/admin-state.js?v=b7731aa4';
import { state } from '/js/admin-state.js?v=c23e6346';
import { PE_SVG, CHEV_SVG, initInlineEdit } from '/js/admin-shared.js?v=8f69dad6';
import { renderWidgetConfigForm } from '/js/widget-config-form.js?v=45bbb2b7';
import { renderWidgetConfigForm } from '/js/widget-config-form.js?v=63dccc19';
import { html, raw, setHtml } from '/js/html.js?v=c71f8903';
import {
sizesForView,
Expand Down
34 changes: 27 additions & 7 deletions public/js/admin.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { buildAppForm, buildFolderForm, serializeKvRows } from '/js/admin-app-form.js?v=f236bd68';
import { buildAppForm, buildFolderForm, captureActLabels, serializeKvRows } from '/js/admin-app-form.js?v=d54926e8';
import { checkAuth, requireLogin, wirePasswordStrength } from '/js/admin-auth.js?v=5e6450f0';
import { applyDrop, canJoinFolder, folderRowZone } from '/js/admin-drag-logic.js?v=ebe3e806';
import { reorderItems, resolveAdminSection } from '/js/admin-logic.js?v=ddfc6f80';
Expand All @@ -9,11 +9,11 @@ import {
saveWithRevert,
snapshotItems,
upsertItem,
} from '/js/admin-save-logic.js?v=52a970d3';
} from '/js/admin-save-logic.js?v=48a9e055';
import { loadSettings, showBgFields, showBgFit, showWallpaperFile } from '/js/admin-settings.js?v=f7078bc0';
import { ag, ap, initInlineEdit, setReauthHandler, toast } from '/js/admin-shared.js?v=8f69dad6';
import { state } from '/js/admin-state.js?v=b7731aa4';
import { buildWidgetForm } from '/js/admin-widget-form.js?v=15aad905';
import { state } from '/js/admin-state.js?v=c23e6346';
import { buildWidgetForm } from '/js/admin-widget-form.js?v=c4b1a7b4';
import { html, raw, setHtml } from '/js/html.js?v=c71f8903';
import { initI18n, LANGUAGES, t } from '/js/i18n.js?v=d056c9c5';
import { iconChain, loadLocalIcons, resolveIcon } from '/js/icons.js?v=69c2b9bd';
Expand All @@ -25,12 +25,12 @@ import {
NOTE,
parseErrorsAsSkipped,
SKIP,
} from '/js/import-foreign.js?v=4161a917';
} from '/js/import-foreign.js?v=ef4f3d44';
import { isMobileLayout, onLayoutChange } from '/js/layout.js?v=28416a75';
import { confirmModal, openModal as openDialog, promptModal } from '/js/modal.js?v=ff76dc56';
import { readMode, watchSystemTheme, writeMode } from '/js/theme.js?v=fbd2d2ef';
import { el, inp, q, qa, clr as rc, sanitizeCssUrl, setUserText, tgt } from '/js/utils.js?v=b18c93ed';
import { normalizeColorInput } from '/js/admin-color-control.js?v=984a0b69';
import { normalizeColorInput } from '/js/admin-color-control.js?v=9fded679';
import { parseYamlTolerant, YamlLiteError } from '/js/yaml-lite.js?v=cceca788';

/* A class rather than a bare media query. Some phones report a wider CSS
Expand Down Expand Up @@ -680,14 +680,31 @@ function openModal(idx) {
state._iframeOpts = item?.iframe ? { ...item.iframe } : {};
state.fnums = [];
state.spaths = [];
if (item?.monitoring?.activity?.extract) {
state.slabels = Object.create(null);
const actLabels = item?.monitoring?.activity?.labels;
/* An older config summed its values. Saving must not turn that into a list. */
state.slegacySum = false;
if (Array.isArray(actLabels) && actLabels.length) {
for (const l of actLabels) {
if (!l || typeof l.path !== 'string' || !l.path) continue;
state.spaths.push(l.path);
state.slabels[l.path] = {
name: l.name || '',
unit: l.unit || '',
color: l.color || '#1e6ef4',
min: l.min == null ? '' : String(l.min),
};
}
} else if (item?.monitoring?.activity?.extract) {
const ex = Array.isArray(item.monitoring.activity.extract)
? item.monitoring.activity.extract
: [item.monitoring.activity.extract];
state.spaths = ex.map(e => (typeof e === 'string' ? e : e.path)).filter(Boolean);
state.slegacySum = state.spaths.length >= 2;
} else if (item?.badge?.extract) {
const ex = Array.isArray(item.badge.extract) ? item.badge.extract : [item.badge.extract];
state.spaths = ex.map(e => (typeof e === 'string' ? e : e.path)).filter(Boolean);
state.slegacySum = state.spaths.length >= 2;
}

const isEdit = idx != null;
Expand Down Expand Up @@ -960,6 +977,7 @@ async function doSave(orig) {
};
} else {
const isPing = inp('hc-type-ping')?.checked;
captureActLabels();
const v = {
label: inp('f-lbl')?.value?.trim(),
href: inp('f-href')?.value?.trim(),
Expand All @@ -982,6 +1000,8 @@ async function doSave(orig) {
iconUrl: state.siurl,
scol: state.scol,
spaths: state.spaths,
actCombine: inp('act-combine')?.checked || false,
slabels: state.slabels,
};
const res = buildAppItem(
v,
Expand Down
Loading