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
Adds a GET /monitors/domain/:monitorId endpoint that looks up the
registrable domain's WHOIS expiry date (walking up from subdomains),
and displays it next to the certificate expiry on the uptime details
page.
Fixes#2094
- Adjust `alignItems` to `stretch` and add `maxWidth` (260) to Gauge components in Infrastructure Details page.
- Update German translations for memory titles, temperatures, and labels in locales file.
`RadialAvgResponse` maps the response-time palette to a qualitative word:
const palette = getResponseTimeColor(avg);
const msg: Record<string, string> = {
success: "Excellent",
warning: "Average",
danger: "Poor",
};
...
{msg[palette]}
But `getResponseTimeColor` only ever returns `"success" | "warning" | "error"`
(MonitorUtils.ts) — never `"danger"`. So for the slow case `palette` is
`"error"`, `msg["error"]` is `undefined`, and no label renders. The same
component uses `theme.palette[palette].main`, which works precisely because
`palette` is the real MUI key `"error"`; every other palette helper in
MonitorUtils.ts also uses `"error"`, and `"danger"` appears nowhere else in
the client. Any monitor whose average response time is >= 300 ms shows an
empty label exactly where the "Poor" signal matters most. Use the `error`
key.
## Changes
- Add `client/src/locales/it.json` — Italian translation of all 874 UI
keys, structure mirrors `en.json` exactly. Placeholders (`{{value}}`,
etc.) and inline tag tokens (`<settingsLink>`, `<highlight>`, ...)
are preserved. Product/brand names, technical abbreviations, and
placeholder-style examples (e.g. `you@example.com`) are kept in
English. 116 leaves are intentionally kept verbatim in English
(brand names, protocol names, sample values, port numbers, regex).
- Register `it: "Italiano"` in `LanguageSelector`'s `languageNames`
map so the dropdown shows the localised name; the selector already
picks up any locale present in the i18n resources.
- Fill in the two "How do I..." sections that CONTRIBUTING.md's table
of contents already links to but did not have bodies:
- "Improve the documentation?" — short guidance on doc PRs and
keeping README translations in sync.
- "Help with translations?" — describes the current per-language
JSON workflow (source of truth: `en.json`; improve an existing
language by editing its JSON; add a new one by adding a JSON file
and registering the display name in `LanguageSelector`). Notes
that the older PoEditor sync workflow is no longer authoritative.
## Benefits
- Italian speakers can now use Checkmate in Italian.
- Contributors who follow the "Help with translations?" link from
the CONTRIBUTING TOC land on real, current guidance instead of a
broken anchor.
- Translation quality can be improved incrementally by anyone
editing `it.json` directly; no external tooling required.
The customCSS field existed on the model, types, and form schema but was
never editable, sent to the API, or rendered. Wire it end to end:
- Accept customCSS in the create/update status page body validation and
regenerate the OpenAPI spec
- Add a Custom CSS editor (multiline field) to the status page form and
include the value in the submitted form data
- Support multiline mode in the shared TextInput component
- Inject the saved CSS via a style tag when rendering the status page