From e423a6667a174b02f858b5e762efd6ffa3d82885 Mon Sep 17 00:00:00 2001 From: Hugh Kaznowski Date: Sat, 5 Sep 2026 19:29:01 +0100 Subject: [PATCH] Tickets added --- tickets/017-regex-cheat-sheet-icon.md | 11 +++++++++++ tickets/018-boolean-param-kind.md | 12 ++++++++++++ tickets/019-docs-isError-use-case.md | 12 ++++++++++++ tickets/020-css-themes-full-replacement.md | 13 +++++++++++++ tickets/021-remove-alert-delivery-hint-text.md | 7 +++++++ tickets/022-edit-existing-metric-declarations.md | 12 ++++++++++++ tickets/023-dashboards-refresh-with-ui.md | 11 +++++++++++ ...ut-tab-independent-rolling-range-and-controls.md | 12 ++++++++++++ tickets/025-popout-tabs-dont-apply-theme.md | 11 +++++++++++ 9 files changed, 101 insertions(+) create mode 100644 tickets/017-regex-cheat-sheet-icon.md create mode 100644 tickets/018-boolean-param-kind.md create mode 100644 tickets/019-docs-isError-use-case.md create mode 100644 tickets/020-css-themes-full-replacement.md create mode 100644 tickets/021-remove-alert-delivery-hint-text.md create mode 100644 tickets/022-edit-existing-metric-declarations.md create mode 100644 tickets/023-dashboards-refresh-with-ui.md create mode 100644 tickets/024-popout-tab-independent-rolling-range-and-controls.md create mode 100644 tickets/025-popout-tabs-dont-apply-theme.md diff --git a/tickets/017-regex-cheat-sheet-icon.md b/tickets/017-regex-cheat-sheet-icon.md new file mode 100644 index 0000000..a251089 --- /dev/null +++ b/tickets/017-regex-cheat-sheet-icon.md @@ -0,0 +1,11 @@ +# Add a regex cheat-sheet icon next to regex input fields + +From WISHLIST.md: regex fields should have an "@" icon that, on hover or click, shows a cheat sheet of regex syntax. + +Add a small icon (similar in spirit to the existing `HelpIcon` component) next to every user-facing regex input, that reveals a compact regex-syntax cheat sheet (common tokens like `\d`, `\w`, `(?P...)`, `*`, `+`, `?`, `|`, anchors, etc.) on hover or click. + +## Acceptance criteria +- A new reusable icon/popover component (e.g. `RegexHelpIcon.tsx`, modeled on `HelpIcon.tsx`) renders an "@" icon and shows a regex syntax cheat sheet on hover or click. +- The icon is placed next to every regex input field: `Params.tsx` (message match regex), `Metrics.tsx` (message match regex), `Alerts.tsx` (field regex), and the filter bar's `regex(...)` syntax (`FilterBar.tsx`, e.g. via its existing help affordance). +- Cheat sheet content covers the regex flavor actually used by the engine (Rust `regex` crate), not e.g. PCRE-only syntax that wouldn't work here. +- Icon/popover follows existing styling conventions (matches `HelpIcon.tsx` look and interaction pattern) and works in both light/dark themes. diff --git a/tickets/018-boolean-param-kind.md b/tickets/018-boolean-param-kind.md new file mode 100644 index 0000000..808c455 --- /dev/null +++ b/tickets/018-boolean-param-kind.md @@ -0,0 +1,12 @@ +# Support a boolean param kind that's always present (true/false, not omitted) + +Discovered while scoping the "IsError" docs use case (see ticket 019): declaring a param today always requires a capture group, and a param is *omitted* from a line's fields (not `false`/empty) whenever its regex doesn't match (`src/engine.rs`, `LogEntryDto::params` build path — "A param is omitted (not included as null/empty) when its regex/capture group doesn't match"). There's also no boolean kind — `MetricPrimitiveKind` (`src/data_value.rs`) only has `String`, `Number`, `Timestamp`, `Duration`. + +This blocks a use case like declaring a param `IsError` that's `true` for any message matching `error` (case-insensitively) and `false` for every other message — today a non-matching line just doesn't get the param at all, and there's no boolean type to hold the result even if it did. + +## Acceptance criteria +- `MetricPrimitiveKind` gains a `Boolean` variant (`src/data_value.rs`), serialized as `"boolean"` consistent with the other lowercase kinds. +- A param declared with kind `Boolean` doesn't require (or use) a capture group for its value — its value is whether `message_match_regex` matches the line, case-insensitively or per the regex's own flags. +- A `Boolean`-kind param is present on every line as `true` or `false` (never omitted), unlike capture-based params. +- Params UI (`Params.tsx`) offers `boolean` as a kind option and hides/disables the capture-group input when it's selected (or clarifies it's unused). +- Existing string/number/timestamp/duration param behavior (including the "omitted when unmatched" semantics for those) is unchanged. diff --git a/tickets/019-docs-isError-use-case.md b/tickets/019-docs-isError-use-case.md new file mode 100644 index 0000000..bd2bef6 --- /dev/null +++ b/tickets/019-docs-isError-use-case.md @@ -0,0 +1,12 @@ +# Add an "IsError" worked example to the Parameters docs + +From WISHLIST.md: add a use case to the docs showing how to create a parameter `IsError` that's `true` for any message containing "error" (case-insensitive) and `false` otherwise. + +Add a worked example to the "Parameters" section in `webapp/src/components/Docs.tsx` (alongside the existing `duration` worked example) showing how to declare a boolean `IsError` param: regex `(?i)error`, kind `boolean`, no capture group needed, true/false on every line. + +This use case surfaces missing functionality — today params always need a capture group and are *omitted* (not `false`) on non-matching lines, and there's no boolean kind. Ticket 018 (boolean param kind) was created to cover that missing functionality; this docs ticket depends on it landing first (so the worked example describes real, working behavior) — indicate in the doc's example that it relies on the boolean param kind. + +## Acceptance criteria +- Depends on ticket 018 (boolean param kind) — implement/land that first. +- "Parameters" section in `Docs.tsx` gets a new worked example: declaring `IsError` with regex `(?i)error`, kind `boolean`, showing it as `true`/`false` on every log line. +- The existing `duration` worked example and surrounding prose are otherwise unchanged. diff --git a/tickets/020-css-themes-full-replacement.md b/tickets/020-css-themes-full-replacement.md new file mode 100644 index 0000000..3c8b01d --- /dev/null +++ b/tickets/020-css-themes-full-replacement.md @@ -0,0 +1,13 @@ +# Make imported/linked CSS always a full theme replacement + +From WISHLIST.md: colour schemes should be full CSS replacements — there should be no "use as theme" tickbox distinguishing a selectable alternative theme from an always-on overlay. Every imported/linked stylesheet should just work the same way as the built-in colour schemes: a selectable, full replacement. + +Currently `NavMenu.tsx`'s CSS section has an `is_theme`/"Use as theme" checkbox (`cssIsTheme`/`cssLinkIsTheme` state, `panel.importCssEntry(filename, content, isTheme)` / `panel.linkCssEntry(url, isTheme)`) that decides whether an entry becomes a selectable theme (validated against the canonical `--c-*` variable set, toggled via `panel.setCustomTheme`) or an always-on CSS overlay applied on top of the active colour scheme. This ticket removes that distinction: every imported/linked stylesheet is validated as a theme and becomes a selectable alternative to the built-in colour schemes, same as today's `is_theme: true` path. + +## Acceptance criteria +- The "Use as theme" checkboxes are removed from both the CSS import form and the CSS link form in `NavMenu.tsx`. +- Imported/linked CSS is always validated against the canonical `--c-*` theme variable set (`parseThemeCss`) and always becomes a selectable theme entry (today's `is_theme: true` behavior) — the "always-on overlay" mode is removed. +- The explanatory text "imported/linked stylesheets — check 'Use as theme' to make one a selectable alternative to the built-in colour schemes above instead of an always-on overlay" is deleted/rewritten to reflect the simpler model (every entry is a selectable theme). +- The CSS filename input's placeholder changes from `"name.css"` to `"enter name"`. +- Backend/`CssEntry`/`is_theme` plumbing (`src/settings.rs`, `src/api.rs`, `src/dto.rs`, `webapp/src/lib/api.ts`) is simplified accordingly if `is_theme` becomes always-true and dead as a variable — remove it if no longer meaningful, or confirm it's still needed for backward compatibility with existing saved entries. +- Existing saved CSS entries (including any persisted with `is_theme: false`) keep working — decide and document how they're treated (e.g. migrated to always selectable) rather than silently breaking. diff --git a/tickets/021-remove-alert-delivery-hint-text.md b/tickets/021-remove-alert-delivery-hint-text.md new file mode 100644 index 0000000..07b733a --- /dev/null +++ b/tickets/021-remove-alert-delivery-hint-text.md @@ -0,0 +1,7 @@ +# Remove the "Every alert rule delivers here" hint text + +From WISHLIST.md: delete the line "Every alert rule delivers here — see the Alerts panel to define rules." from the Ntfy sink settings section. + +## Acceptance criteria +- The `

` containing "Every alert rule delivers here — see the Alerts panel to define rules." is removed from the Ntfy sink section in `NavMenu.tsx` (around line 387). +- No other content in that section changes. diff --git a/tickets/022-edit-existing-metric-declarations.md b/tickets/022-edit-existing-metric-declarations.md new file mode 100644 index 0000000..95a975d --- /dev/null +++ b/tickets/022-edit-existing-metric-declarations.md @@ -0,0 +1,12 @@ +# Allow editing a declared metric's properties + +From WISHLIST.md: in the Metrics section, it's not clear what the properties are for existing metrics, and it should be possible to edit them when clicked. + +Today, clicking a declared metric badge in `Metrics.tsx` only selects it to show its bucket values/trend table (`setSelected(m.name)`); its regex and param matchers are only visible as a `title` tooltip on hover (`title={m.message_match_regex}`), and there's no way to change a metric's regex/params after declaring it — the declaration form (`declareMetric`) only creates new metrics, and there's no update endpoint (`src/api.rs` only has `GET`/`POST /api/metrics`, no `PUT /api/metrics/{name}`). + +## Acceptance criteria +- Clicking a declared metric populates the declaration form (name, message match regex, param matchers with param_name/capture_group/kind/role) with that metric's current values, in addition to (or instead of) selecting it for the bucket-values view — make both available without one hiding the other. +- Backend gains a way to update an existing metric declaration in place (e.g. `PUT /api/metrics/{name}`), reusing the existing validation from `declare_metric` (`src/api.rs`, `src/engine.rs`). +- Submitting the form while editing an existing metric updates it rather than failing on a duplicate-name conflict or silently creating a second declaration. +- The properties (regex, params, kinds, roles) are visible in the UI without relying solely on a hover tooltip — e.g. shown inline once a metric is selected/being edited. +- Declaring a brand-new metric (the existing flow) is unaffected. diff --git a/tickets/023-dashboards-refresh-with-ui.md b/tickets/023-dashboards-refresh-with-ui.md new file mode 100644 index 0000000..5c286cd --- /dev/null +++ b/tickets/023-dashboards-refresh-with-ui.md @@ -0,0 +1,11 @@ +# Dashboards should refresh when the rest of the UI refreshes + +`App.tsx` polls logs/timeline every `POLL_MS` (2000ms — `src/App.tsx`) and, for rolling range presets, recomputes `range.startMs`/`range.endMs` on each tick. Dashboard panels (`PanelPreview` in `Dashboards.tsx`) only refetch their PromQL series when `panel.promql`, `panel.chart_type`, `range.startMs`, or `range.endMs` change (`useEffect` dependency array, `Dashboards.tsx` ~line 78). So a dashboard panel only refreshes if the rolling range's bounds actually move; with a fixed/absolute range selected, or between rolling-preset ticks where the resolved bounds happen not to change, panels go stale even though the rest of the UI (log table, timeline) is actively re-polling. + +Dashboards should refresh on the same cadence as the rest of the app, not only when their `range` prop happens to change value. + +## Acceptance criteria +- Dashboard panels (`PanelPreview`, and by extension `AllDashboardsView`) refetch their PromQL series on the same polling cadence as `App.tsx`'s log/timeline polling, independent of whether `range.startMs`/`range.endMs` literally changed. +- This applies both to the normal `Dashboards` section and the popped-out dashboard view, if it polls independently. +- No duplicate/overlapping fetches are introduced (e.g. a range change and the periodic tick firing at the same time shouldn't double-fetch). +- Existing refetch-on-range/query/chart-type-change behavior is preserved. diff --git a/tickets/024-popout-tab-independent-rolling-range-and-controls.md b/tickets/024-popout-tab-independent-rolling-range-and-controls.md new file mode 100644 index 0000000..223af9b --- /dev/null +++ b/tickets/024-popout-tab-independent-rolling-range-and-controls.md @@ -0,0 +1,12 @@ +# Popped-out tabs should carry over the preset kind (not a frozen range) and have their own time-range controls + +Opening a section in a new tab (`PopOutButton` in `CollapsibleSection.tsx`) does not currently carry over the active colour scheme/theme — see ticket 025 for that bug and its fix; this ticket is scoped to time-range handling only. + +The time range handling is wrong for rolling presets. `popOutUrl` resolves the *current* `range` to absolute `startMs`/`endMs` query params at click time (`CollapsibleSection.tsx` ~line 101), and `StandaloneRanged` (`App.tsx` ~line 148) passes that frozen `{startMs, endMs}` straight into `Metrics`/`Dashboards` with no further updates. So opening a tab while "Last 5m" is active doesn't open a new tab that's *also* sliding its own independent 5-minute window — it opens a tab pinned forever to whatever absolute window happened to be resolved at that instant, and it has no time-range picker at all to change that afterward. + +## Acceptance criteria +- Opening a new tab carries over which preset was active (e.g. `5m`), not just its resolved absolute bounds — pass the preset id (`TimeRangePresetId`, `LogTimeline.tsx`) via query params instead of (or alongside) `startMs`/`endMs`. +- If the source section was on a rolling preset (anything but a manually dragged/fixed range), the new tab starts its own independently-sliding window of the same size (e.g. its own "last 5m"), recomputed on its own polling cadence — it must NOT track or freeze to the source tab's window, and changes in the source tab's range after the popout was opened have no effect on it. +- If the source section had a fixed/dragged range (not a preset), that fixed range is still carried over as absolute bounds, same as today. +- The popped-out standalone page (`StandaloneRanged` in `App.tsx`, covering `metrics` and `dashboards` sections) gets its own time-range controls (the same preset buttons / drag-to-select UI `LogTimeline.tsx` already provides elsewhere), rather than only ever displaying whatever range was passed in the URL with no way to change it afterward. +- The `log` and `params` standalone pages (which already have or don't need their own range picker) are unaffected. diff --git a/tickets/025-popout-tabs-dont-apply-theme.md b/tickets/025-popout-tabs-dont-apply-theme.md new file mode 100644 index 0000000..3c00715 --- /dev/null +++ b/tickets/025-popout-tabs-dont-apply-theme.md @@ -0,0 +1,11 @@ +# Popped-out tabs don't apply the active colour scheme/theme at all + +Reported: clicking "Open in new tab" (`PopOutButton`) opens a tab that doesn't match the current colour scheme/theme at all. + +Root cause: applying the colour scheme (`applyColorScheme`, `document.documentElement` class) and injecting any active custom theme's CSS is done entirely inside `useSettingsPanel()` (`webapp/src/lib/useSettingsPanel.ts`), and that hook is only ever called from `NavMenu.tsx:34`. Every popped-out standalone route (`StandalonePage` in `App.tsx`, used by `StandaloneLog`, `StandaloneParams`, `StandaloneRanged` for metrics/dashboards) wraps its children in `DocsNavProvider` only — it never renders `NavMenu` and never calls `useSettingsPanel()`. So a popped-out tab never sets the colour-scheme class or injects the custom theme `