Commit Graph
2043 Commits
Author SHA1 Message Date
Alexander Holliday 4e4bc5f319 Merge pull request #3900 from bluewave-labs/fix/hover-states
fix(client): add hover states to tables, cards, stat boxes and icon buttons
2026-08-31 09:49:14 -07:00
Alex Holliday 2fec09df62 apply hover states to components directly rather than to parent 2026-08-31 09:47:20 -07:00
Alex Holliday 13e49c518d remove dead code, fix mobile regeression 2026-08-31 09:42:04 -07:00
Alexander Holliday a1f9c0304f Merge pull request #3897 from bluewave-labs/fix/network-notice-gating
fix(infrastructure): show the container-namespace notice when it applies
2026-08-31 09:36:15 -07:00
Alex Holliday d158bcdce1 pruge comment, fix busy connection regression 2026-08-31 09:34:59 -07:00
Alexander Holliday c45a21b4c8 Merge pull request #3896 from bluewave-labs/fix/gauge-arc-clamp-and-key
fix(infrastructure): clamp gauge arc and fix disk key fallback
2026-08-31 09:30:45 -07:00
Alex Holliday a0738dff63 purge narrative comment 2026-08-31 09:29:17 -07:00
Alex Holliday 94ecbfe365 add missing props 2026-08-31 09:24:56 -07:00
Alex Holliday 5343241036 add a flex basis prop instead of one-off fix 2026-08-31 09:21:35 -07:00
gorkem-bwl 3e56dc63a9 fix(client): correct StatBox hover and separate nested-control hover
Addresses review findings on the hover-states change.

StatBox's hover was a no-op. `GradientBox` always paints an opaque
`linear-gradient` via the `background` shorthand, which populates
background-image and covers any `backgroundColor` beneath it, so the new hover
was invisible — a regression from the `opacity: 0.95` it replaced. The overlay
now layers onto the same gradient, and moves into `GradientBox` where `bg` is
in scope, behind an `interactive` prop.

The mobile card branch gated its cursor and hover on `onRowClick` alone, so
expandable-row tables below the md breakpoint rendered cards that expand on
click but showed no pointer and no hover — the exact inconsistency this change
set out to fix, reintroduced on mobile. Both branches now share one
`isInteractive` flag.

The row action gear used the same overlay as the row beneath it. Alpha
overlays compose, so it was not invisible as reported, but the resulting delta
was 6 levels — too faint for a nested control. Adds `HOVER.CONTROL` (0.05) and
an `action.controlHover` token for controls nested inside a hoverable row: the
gear and the pagination arrows.

Claude-Session: https://claude.ai/code/session_01AbYLvwpEaZFXktHVcqrFRd
2026-08-28 19:53:39 -04:00
gorkem-bwl 9a6602b9e1 fix(client): add hover states to tables, cards, stat boxes and icon buttons
Clickable surfaces across the app set `cursor: pointer` but gave no visual
response on hover, so rows and cards read as static text.

Two separate causes:

- `DataTable` never passed MUI's opt-in `hover` prop on `TableRow`, which is
  `false` by default, so no table in the app shaded on hover. One change here
  covers all 16 page tables (Uptime, Incidents, Tags, Team, Notifications,
  Maintenance, Proxies, Status pages, Checks, Geo checks, Infrastructure,
  PageSpeed and the three Logs tables).
- `IconButton` gates its hover style behind `props => !props.disableRipple`,
  and the theme sets `disableRipple: true` globally, so the row action gear
  and the pagination arrows lost their background. `MenuItem` is unaffected —
  its hover sits on the base style — so action menu items already worked and
  are left alone.

Adds a `HOVER.ROW` (0.025) constant and an `action.rowHover` palette token,
defined in both light and dark palettes so the overlay direction is correct on
each surface. Kept separate from MUI's shared `action.hover` so menu items,
which read that token, are not restyled as a side effect.

Also fixes `cursor` on expandable rows, which showed `default` despite being
clickable to expand.

Claude-Session: https://claude.ai/code/session_01AbYLvwpEaZFXktHVcqrFRd
2026-08-28 19:13:33 -04:00
gorkem-bwl 9ffcbd1242 fix(infrastructure): show the container-namespace notice when it applies
The network tab warns when Capture can only see a container's own
network namespace, but the condition required EVERY reported interface
to be named lo, lo0 or docker0. A containerised Capture usually also
reports the container's veth under a host-looking name (eth0, ens3,
...), so the common case failed that test and the notice never
appeared - leaving those users with plausible-but-meaningless traffic
and nothing explaining why.

Widening it to "any container-only name present" would have been wrong
in the other direction: a host-level Capture on a machine running
Docker legitimately reports docker0 alongside its real NIC, and would
then have been warned incorrectly.

Interface names alone cannot separate the two cases. What does is that
in the container case nothing carries real traffic, while a genuine
host has a busy NIC. The notice now fires when a container-only
interface is present AND every interface is idle, using a 1 KB/s
threshold - real NICs sit orders of magnitude above it, a container's
veth sits at or near zero.

Checked against six scenarios: the reported case (lo + ens3 + docker0,
all near zero) now warns; a host with a busy NIC plus an idle docker0
does not; a fully namespaced container still warns as before; and a
quiet host with no container-only names stays silent.

The notice text is updated to match, since it previously described
only the all-container-names case and did not explain that a
host-looking interface can be the container's own.

Claude-Session: https://claude.ai/code/session_01AbYLvwpEaZFXktHVcqrFRd
2026-08-28 12:44:14 -04:00
gorkem-bwl 840e12eb9a fix(infrastructure): clamp gauge arc and fix disk key fallback
Two small pre-existing bugs in the infrastructure gauges.

Arc overdraw. Gauge computed strokeLength from the raw `progress` prop
while the label and the fill colour both used `progressWithinRange`,
the value clamped to 0-100. A reading above 100% therefore swept the
arc past a full circle - the offset (circumference - strokeLength)
went negative - while the label still read "100.0%". A negative
reading drew the arc backwards for the same reason. strokeLength now
uses the clamped value, so out-of-range input stops at exactly one
turn and matches what the label and colour already showed. Values in
range are unaffected.

The effect that animates the arc also listed `progress` in its
dependency array while only reading `strokeLength`, so it re-ran the
100ms animation on changes that could not alter the arc (105% to 110%,
say). Now that strokeLength is derived from the clamped value, the
stale dependency is dropped.

Disk key fallback. `disk?.device || 0 + idx` parses as
`disk?.device || (0 + idx)` because + binds tighter than ||, so the
fallback was just `idx` and the leading 0 did nothing. It happened to
produce unique keys, but by accident rather than intent, and a disk
whose device is the empty string collided with index 0. Replaced with
a `disk-${idx}` template so the intent is explicit.

Claude-Session: https://claude.ai/code/session_01AbYLvwpEaZFXktHVcqrFRd
2026-08-28 11:22:29 -04:00
gorkem-bwl 96b2266a9d fix(infrastructure): wrap gauge row so every disk stays reachable
The gauge row on the infrastructure details page laid out memory, CPU
and one gauge per disk in a single flex row with no wrapping and no
overflow handling. Each gauge is capped at 260px, so on a host with
enough disks the row ran past the content column.

RootLayout sets overflow: "hidden" on that column, so the excess was
clipped outright rather than becoming scrollable - the later disks
rendered but could not be reached by any means.

Three changes, all scoped to this row:

flexWrap moves the overflow onto additional rows.

useFlexGap is required alongside it. MUI's Stack implements `spacing`
as `& > :not(style) ~ :not(style) { marginLeft }`, and that selector is
DOM-order based rather than line-aware, so the first card of each
wrapped row would carry a spurious 16px left margin and misalign
against the row above. useFlexGap switches to a real flex gap.

flexBasis on the children is what actually makes the line break.
BaseChart sets `flex: 1`, which expands to `flex: 1 1 0%`; wrapping is
decided by the sum of items' hypothetical main sizes, so with a zero
basis that sum is 0 and the row never overflows. The cards would
instead shrink to min-content (roughly the 70px gauge plus the widest
label) and stay on one cramped line. Giving each child a 260px basis
makes the row wrap at the intended card width.

The basis is applied through the row's own `& > *` selector rather than
by changing BaseChart, which has eight other consumers that default to
maxWidth: "100%" and would have had their layout altered.

The repeated 260 literals are now a named constant.

Only affects viewports at or above the md breakpoint; below it the
stack is already a column, where flexWrap is inert.

Claude-Session: https://claude.ai/code/session_01AbYLvwpEaZFXktHVcqrFRd
2026-08-28 10:36:50 -04:00
Alex Holliday 0c9334071f refactor monitor pages 2026-08-27 14:28:29 -07:00
Alex Holliday e444d5fbe6 decycle imports 2026-08-27 13:54:40 -07:00
Alex Holliday e9dca23664 add base monitor list page 2026-08-27 13:53:28 -07:00
Alex Holliday 7fb0e9dc70 new monitor list controller hook 2026-08-27 13:18:02 -07:00
Alex Holliday de148f9773 add pagespeed table to redux state 2026-08-27 12:32:10 -07:00
Alex Holliday 4bc71a3d18 interpoalte colors for severity of downtime 2026-08-26 11:48:33 -07:00
Alex Holliday f30085bae3 deal with empty strings for proxyId 2026-08-26 11:19:08 -07:00
Alex Holliday d8ce2dfdc8 set keep previous data 2026-08-26 10:40:02 -07:00
Alex Holliday 68679bc0bf lockfile script 2026-08-25 15:16:12 -07:00
Alex Holliday 0b54b5c6cd minor version bump 2026-08-25 14:49:52 -07:00
Alex Holliday 9839d48ca0 add img-src blob: to CSP, stop refetching blob 2026-08-25 14:44:01 -07:00
Alexander Holliday 83c2df4390 Merge pull request #3863 from eralpozcan/feat/status-page-monitor-tags
feat(status-page): show monitor tags in status page selector
2026-08-25 14:16:33 -07:00
Alex Holliday 3f62c8ec6a resolve scoping issue by fetching proxy summary 2026-08-25 11:13:12 -07:00
Alex Holliday ea8ad88ae9 add global proxy setting config and translation keys 2026-08-25 10:29:19 -07:00
Alex Holliday 6e271f834c select -> radio, update descriptions 2026-08-25 09:55:34 -07:00
Alex Holliday 0c21dcdd2a add settings response type, destructure 2026-08-25 09:39:56 -07:00
eralpozcan 9bb95e1f0c feat: show monitor tags in status page selector 2026-08-22 14:05:44 +03:00
Alex Holliday ccfda938d5 Add proxies to create/edit monitors page 2026-08-21 15:13:34 -07:00
Alex Holliday cc137e1d06 add proxies CRUD pages 2026-08-21 15:13:17 -07:00
gorkem-bwl 68c1f2e281 feat(client): show uptime percentages with two decimals
Requested by a user who found xx.xx% more trustworthy than xx.x% on their
status page. The presentational argument holds, but the stronger reason is
that one decimal was actively misleading.

Intl rounds to the displayed precision, so every value above 99.95% rendered
as "100.0%" — a claim of zero downtime for a period that contained real
outages. On a public status page that is the opposite of reassuring: the
number reads as flawless during a month with a visible incident.

One decimal also collapsed the range operators care about most. 99.9%,
99.95% and 99.99% are three very different commitments (8.7 hours, 4.4 hours
and 52 minutes of annual downtime) and the first rendered as 99.9% while the
other two were indistinguishable at 100.0%.

Everything flows through the shared formatter in FormatUtils, so this covers
both surfaces at once: the monitor list and diagnostics gauges in the web
app, and the uptime figure, chart cells and hover tooltip on status pages.
Infrastructure gauges are untouched — they format separately at zero
decimals, where CPU at "43.00%" would only add noise.

Server-side precision was already sufficient; the aggregation divides
without rounding, so no API change is needed.

Adds tests pinning the regression: 7 of the 10 fail against the previous
one-decimal formatter.

Note: this restores the client Vitest setup. PR #3844 introduced it, but the
config, scripts and logger tests were dropped when that branch merged into
develop, leaving the client with no test runner again.
2026-08-20 09:38:07 -07:00
Alexander Holliday a719edb0fc Merge pull request #3856 from bluewave-labs/feat/theme-button
feat: add theme mode to auth footer menu
2026-08-19 12:05:25 -07:00
Alex Holliday 84a73d9616 add theme mode to auth footer menu 2026-08-19 12:02:45 -07:00
Alex Holliday 7b2358bd48 improve keyboard navigation on create monitor page 2026-08-19 11:28:46 -07:00
Alexander Holliday bc25c15c34 Merge pull request #3844 from bluewave-labs/fix/redact-sensitive-fields-client-logs
fix(security): redact sensitive fields from client-side logs
2026-08-18 10:49:47 -07:00
Alex Holliday 1b6218ea56 remove tests and harness 2026-08-18 10:46:57 -07:00
Alexander Holliday 617ac3a9bb Merge pull request #3847 from bluewave-labs/fix/dns-monitors-status-page-picker
fix(status-page): allow DNS monitors to be added to status pages
2026-08-18 10:21:17 -07:00
Alex Holliday 248dad01d4 add retention hint 2026-08-18 10:01:05 -07:00
Alex Holliday 840c936501 remove unused vars 2026-08-18 09:38:34 -07:00
gorkem-bwl 7096afcdf2 fix(status-page): allow DNS monitors to be added to status pages
The monitor picker on the status page create/configure form fetched
candidates using a hardcoded list of monitor types that omitted "dns", so
DNS monitors were filtered out server-side and never appeared in the
dialog. Everything else was already in place: the DNS provider stores
checks like any other monitor type, and the status page renders them once
attached.

Rather than appending "dns" to the hardcoded list, derive the query from
the existing SelectableMonitorTypes tuple in @/Types/Monitor. The two lists
had silently drifted apart, and deriving prevents the next new monitor type
from hitting the same bug. "hardware" is appended explicitly because
infrastructure monitors are created on their own page and so are absent
from the selectable set.

Net effect on the requested types: gains "dns", loses none.

Fixes #3721
2026-08-18 02:37:54 -04:00
Alex Holliday c15d6e0851 wire client 2026-08-17 14:56:53 -07:00
Alex Holliday 506133af29 add daily tooltip 2026-08-17 13:55:01 -07:00
Alex Holliday 03f168fa84 add daily bucket type 2026-08-17 13:54:38 -07:00
Alex Holliday 4b02bbec37 add helper methods 2026-08-17 13:54:14 -07:00
Alex Holliday 42aae20fa3 add param to URL 2026-08-17 13:30:03 -07:00
Alex Holliday c71c833b77 add range to query 2026-08-17 13:20:36 -07:00
Alex Holliday cee7db64ee add range types 2026-08-17 13:16:55 -07:00