Skip to content

Merge to prod#394

Merged
vvlladd28 merged 7 commits into
release/4.3from
main
May 19, 2026
Merged

Merge to prod#394
vvlladd28 merged 7 commits into
release/4.3from
main

Conversation

@vvlladd28
Copy link
Copy Markdown
Member

Description

Type of change

  • New / updated documentation page (src/content/docs/**)
  • Shared include file (src/content/_includes/**)
  • Component, layout, or styling change (src/components/**, src/styles/**)
  • Landing / use-case / case-study page (src/pages/**, src/data/**)
  • Redirects (src/data/redirects.ts)
  • Version bump / release (see release skill)
  • Build, CI, scripts, or tooling
  • Other (please describe)

Affected products

Related issues

  • Closes #

Checklist

  • pnpm check passes (Astro / TypeScript)
  • pnpm lint:eslint passes
  • pnpm lint:slugcheck passes (required if pages were added/renamed/moved across languages)
  • pnpm lint:linkcheck passes locally — required to merge; run it before requesting review (use pnpm lint:linkcheck:nobuild if you already ran a build)
  • Renamed/removed pages have a redirect in src/data/redirects.ts, and pnpm generate:redirects was run
  • No hardcoded versions — values come from src/data/versions.ts
  • Screenshots attached for visual changes

stitenko and others added 7 commits May 19, 2026 12:05
* Added all High-performance SCADA fluid system widgets docs

* Added General high-performance SCADA symbols docs

* Added all General high-performance SCADA symbols docs

* Updated sidebar for SCADA widgets

* Updated sidebar for SCADA widgets - Scales

* Added High-performance SCADA oil & gas docs

* Updated Get dashboard state object option for all widgets

* Created Widgets Library navigation menu

* Added a return button to the Widgets Library

* Added Analogue gauges widgets docs

* Updated Widgets doc

* Updated links
* Updated variable

* Updated variable
* Fix author bugs surfaced by external-link audit

- trendz-analytics: wrap `<code>http://thingsboard{...}:8080</code>` in a
  JSX template literal so the remark-gfm autolinker no longer captures the
  unevaluated expression and renders an `http://thingsboard%7Bprops.product`
  anchor.
- device-library (68 files): replace `<a href="https://YOUR_TB_HOST">` and
  the markdown-form variant with an inline-code placeholder
  (`ThingsBoard account at \`YOUR_TB_HOST\``). The 2 `YOUR_TB_HOST/signup`
  links in dsgw-210 now point at the real `https://thingsboard.cloud/signup`.
- partners/distributors: pre-render all 97 cards as static HTML with real
  `<a href>` attributes so the link audit sees them, SEO indexes them, and
  no-JS users get the list. Client-side filter toggles `hidden` on cards
  instead of rebuilding the DOM. Country select is now pre-populated with
  every country so filtering by country alone works; the reset button and
  filter logic treat region/country as independent AND filters.

* Fix external 404s surfaced by link audit

- AgroSense data-converters (3 device pages, 12 URLs): the
  raw.githubusercontent.com/thingsboard/data-converters paths used
  `VENDORS/Makerfabs/...` but the public repo lays them out under
  `VENDORS/AgroSense/...` (Makerfabs is the manufacturer, AgroSense is
  the product line / folder name).
- gcp-marketplace.mdx: drop the broken
  cloud.google.com/marketplace/docs/partners/integrated-saas/pricing
  link wrapping "BYOL"; the page never existed, and the surrounding
  sentence already explains the acronym in parentheses.
- edge-vs-cloud blog post: halosmartiot.com renamed `/news/` → `/blog/`.
- mqtt-broker/mqtt-over-ws: nodejs.org dropped
  `/en/learn/getting-started/how-to-install-nodejs`; point at the
  Download page since the link sits behind "Install Node.js".
- comfort-v2 leak sensor: replace the dead
  `tektelic.com/wp-content/uploads/TEKTELIC_Comfort_Vivid_v2_UG.pdf`
  with the official user guide on `knowledgehub.tektelic.com`.
- digital-ocean install guide: DigitalOcean migrated docs to a separate
  subdomain — `www.digitalocean.com/docs/...` →
  `docs.digitalocean.com/products/droplets/how-to/connect-with-ssh/`.
- azure-marketplace.mdx: bare `azure.microsoft.com` redirects to
  `/en-us`; match the other 4 Azure references that already use the
  locale-explicit URL.

* Resolve external link redirects to canonical targets

Replaces external URLs that were reachable only via a 3xx hop with
their final canonical destination. Removes the redirect roundtrip
and keeps the URL stable against further upstream restructuring.

Host/protocol moves:
- http://wiki.seeedstudio.com/, http://www.dragino.com/ → https
- chirpstack.io → www.chirpstack.io/
- angular.io → angular.dev/
- cloudflare.com → www.cloudflare.com/
- claude.ai/download → claude.com/download
- console.anthropic.com/settings/keys → platform.claude.com/...
- console.thethingsnetwork.org/ → console.cloud.thethings.network/
- docs.anthropic.com/.../claude-code/overview → code.claude.com/docs/en/overview
- cloud.google.com/<svc>/docs/... → docs.cloud.google.com/<svc>/docs/...
  (16 specific URLs across compute, dns, k8s, memorystore, sql)
- cloud.google.com/sdk/downloads → docs.cloud.google.com/sdk/docs/install-sdk

Path renames:
- aws.amazon.com/marketplace/pp/B07V8S6JLG → /pp/prodview-wohnfuiqbf5w4
- aws.amazon.com/premiumsupport/.../route-53-create-alias-records/ → repost.aws/...
- docs.aws.amazon.com/cli/.../install-cliv2.html → getting-started-install.html
- developer.apple.com/app-store/submissions/ → /submitting/
- developer.apple.com/help/account/manage-keys/ → /help/account/keys/
- developer.apple.com/.../information_property_list/ → information-property-list/
- developer.mozilla.org/.../HTTP/Headers/ → HTTP/Reference/Headers/
- developers.cloudflare.com/fundamentals/get-started/reference/ → /reference/policies-compliances/

Trailing slash / canonical form:
- sixfab.com/alpon, /product/alpon-x4 (add /)
- lansitec.com/products/{lorawan-smart-badge-tracker,uwb-anchor} (add /)
- elastel.com/docs/ElastPro/{Getting_Started,intro} (add /)
- jetbrains.com/idea/download (add /)
- thethingsnetwork.org/docs/applications/mqtt/api (add /)
- namecheap.com KB article 9646 (add /; was the actual 4xx, the
  bare-host one is bot-detection)
- docs.mistral.ai/getting-started/quickstart/ → quickstarts (plural;
  canonical lives at /quickstarts without trailing slash)

* Address dead/problematic external domains from link audit

- Milesight (5 device pages): the manufacturer migrated from
  milesight-iot.com to milesight.com and reorganized the path
  (lorawan/<gateway|sensor>/<id> → iot/product/lorawan-<gateway|sensor>/<id>).
  Updated UG56/UG65/UG67 gateway and WS101/WS202 sensor links to the
  new canonical URLs.
- exp4j: trailing slash on objecthunter.net/exp4j → /exp4j/ to skip the
  301. The underlying domain is fine for browsers; only the audit fails
  on it because the server doesn't serve the intermediate certificate
  and curl can't fetch it via AIA the way browsers do.
- Sensolyze: their domain (sensolyze.com) now serves the cyon.ch
  "Domain nicht eingerichtet" placeholder — the hosting account is no
  longer active and the company appears gone. Drop the `link` field
  from the clients-feedback entry; FeedbackCard already renders the
  logo without an anchor when link is absent.

* Update data.it-novum vol-6 video links; drop Voxney distributor

- thingsboard-user-meetup-2025 blog post: it-novum reorganized the
  vol-6 meetup recordings under /mediathek/thingsboard/ — the old
  /video/<slug>/ URLs 301 to the new path. Update all 9 links inline
  to the canonical destination.
- Voxney PLSC, Inc. distributor: voxney.com returns a 500 from the
  audit and looks defunct; remove the entry from the distributors
  list (97 → 96 distributors).

* Fix geofencing example images on PE/PAAS and tooltip code background

- Pin Example 1 image sources to the existing -ce assets so the ImageGallery
  resolver falls back to them on PE/PAAS instead of hitting a missing CDN URL
- Override --sl-color-bg-inline-code on .thumb-tooltip so inline <code> in
  captions renders transparent against the dark tooltip background

* Address more external-link audit findings

- DockerComposeUpgradeSteps: handle deleted thingsboard-pe-docker-compose
  release branches by rendering the manifests label as plain text, and fix
  branch URL pattern (PE branches drop the trailing .0 for X.Y.0 releases).
- Update TPS company link to its new domain (tps.company → tps-factory.com).
- Replace dead TBMQ CE GitHub Discussions link with GitHub Issues.
- Drop obsolete ceGhTagOverride for Edge 4.0.1 (tag and package suffix now match).
…#391)

* Pricing calculator: fix mobile overflow, sizing, and add-on row layout

Four issues at 375-389px wide. The grid fix lives in
`CalculatorInline.astro` (inline calculators only); the remaining rules
live in `CalculatorModal.astro` and are inherited by every calculator
that uses it — both the inline pricing calculators and the modal
variants (TB and TBMQ × PAYG / Perpetual / Private Cloud).

- `.calc-inline-body` grid used bare `1fr` / `3fr` for tracks, which
  resolves to `minmax(auto, …)` and lets each track grow to fit its
  children's min-content. The fixed-width 110px number input and
  non-wrapping button text in the summary panel pushed the inputs panel
  wider than the viewport; `.calc-inline`'s `overflow: hidden` then
  clipped the Reset button and summary values. Switched to explicit
  `minmax(0, …)` and added `min-width: 0` on `.calc-panel` so the panel
  can shrink inside the grid track.

- `.calc-total-row` had no gap between the "Total" label and the amount,
  and the 26px amount + 20px label collided on a single line at 375px.
  Added `gap: $spacing-3` plus `media-down(sm)` overrides
  (label 20px → 16px, amount 26px → 18px) so the row stays one clean
  line on a phone.

- `.calc-reset-btn` used `width: 25%`, which collapses to ~70px on a
  ~280px panel — the 8px/20px padding cramps the label and the button
  looks awkward. Added `media-down(sm)` rule to switch to
  `width: auto; min-width: 100px`.

- `.calc-addon-result` used `height: 32px` (fixed) and the row default
  was 14px text on both sides. "Multi-AZ Deployment" + "Add to plan
  ($400.00)" overflowed the single-line cap and wrapped awkwardly
  mid-phrase. Switched to `min-height: 32px` so rows can grow, added
  `gap: $spacing-3` for breathing room, `white-space: nowrap` on the
  action button so "Add to plan ($X)" stays on one line, and a
  `media-down(sm)` rule that drops label + action + price to 12px so
  each add-on row stays as one horizontal pair (mirrors the desktop
  layout instead of stacking).

* Landing: center feature-card icons on mobile

The default `feature-card` variant's `.feature-card__inner` switches to
`display: block; text-align: center` at `media-down(md)`, which should
centre the inline-block `<img>` icon above the title. In practice the
icons drifted noticeably left — `<img>` baseline alignment quirks plus
the SVG's visual centroid sitting slightly off the geometric centre.

Force `display: block; margin: 0 auto $spacing-4` on
`.feature-card__icon` at the same breakpoint for guaranteed horizontal
centring. Only the default variant is affected; `tbmq-card` and `pe`
variants have their own icon rules.

* Landing: fit rule-engine hover overlay to the video rectangle

`<GifVideo>` renders `<video width="890" height="375">`. The scoped CSS
only set `width: 100%`, so the height attribute kept the element 375px
tall on narrow viewports while the video content scaled down to its
intrinsic 890:375 aspect ratio inside that taller box — letterbox bands
top and bottom. The absolutely-positioned `.overlay` (height: 100%)
matched the element, not the visible content, so the dark hover overlay
extended above and below the rule-engine diagram on mobile.

Add `height: auto` so the element honours the intrinsic aspect ratio.
The width/height HTML attributes still supply the ratio hint, so layout-
shift is unchanged.

* PE comparison table: align CE/PE columns and rework mobile layout

Multiple issues on `/products/thingsboard-pe/` at mobile widths
(≤500px) where the Features / CE / PE table layout was off:

- `.comparison-header` had no horizontal padding while `.comparison-row`
  had `padding: 12px 20px`. The header was 40px wider in its flex
  distribution area than each body row, shifting every header column's
  centre ~13-18px right of the checkmarks beneath. Added matching
  `padding: 0 1.25rem` to the header and dropped the now-redundant
  `padding-left` on the header's `.col-feature`.

- Standard IoT Protocols' label carried an unbreakable token
  `(MQTT/CoAP/HTTP/SNMP/LWM2M)`. With `overflow-wrap: normal`,
  `.col-feature`'s min-content was pinned to ~150px at 12px, blowing
  past its flex share and squeezing `.col-ce` / `.col-pe` narrower than
  the 20px icon — the icons rendered smaller and drifted right in that
  one row. Switched the slashes to commas + spaces so the label wraps
  naturally, and added `overflow-wrap: anywhere` on `.col-feature` as a
  defence against future labels with similar unbreakable tokens.

- Added `flex-shrink: 0` on the CE/PE icon images so they never shrink
  with their parent flex cell, regardless of min-content pressure
  elsewhere in the row.

- Tightened CE/PE columns at ≤500px (flex 0.4 → 0.18 in both header and
  body rows) so the icon columns sit close together near the right edge
  and the Features label gets the freed-up width. Header and body share
  the same flex, so the "CE" / "PE" letters sit directly above the
  checkmarks below.

- The Support Model row contains text cells ("Community" / "Advanced +
  SLA") that overflow a 0.18-wide cell. Added a `:has(.cell-link)`
  override that widens those cells to flex 0.45 — icon rows stay tight,
  text rows breathe.

* Pricing calculators: drop execCommand clipboard fallback

The six pricing calculators' "Copy summary" buttons tried the modern
`navigator.clipboard.writeText` first, then fell back through a hidden
`<textarea>` + `document.execCommand('copy')` if the async API rejected.
Drop the fallback:

- thingsboard.io serves over HTTPS, so the primary path always succeeds
  for production users.
- Modern Chrome/Firefox/Safari/Edge have shipped `Clipboard.writeText`
  for 5+ years (Chrome 66 Apr 2018, FF 63 Oct 2018, Safari 13.1 Mar 2020).
- The fallback only fired in `pnpm dev --host` LAN previews (non-secure
  context) and inside iframes with `clipboard-write` denied by Permissions-
  Policy — neither relevant for real thingsboard.io traffic.
- `document.execCommand` is `@deprecated` in lib.dom.d.ts, so the six
  call sites each produced a `ts(6387)` hint; dropping the block clears
  them and shaves ~17 lines per calculator (net -102).

If the primary path rejects for some unusual user, the Copy button just
won't flash "copied" — the rest of the calculator stays functional and
the user can still hit Download (separate code path) or select the
summary by hand. Affects all six calculators (TB and TBMQ × PAYG /
Perpetual / Private Cloud).

* Pricing background: hide rotated boundary cuts at wide viewports

At >= ~2000px viewports, the pricing page's animated wave background
showed faint diagonal cuts at the -28deg rotation angle — the SVG's
internal element/path boundaries leaking through against the page
background. Three sources, three fixes:

- Wave paths (4×) were filled regions bounded vertically at y=0 and
  y=1800. The `<animateTransform>` translation by one period (-900,
  -600, or -450) brought those horizontal closures into the visible
  viewBox at certain animation phases, where rotation turned them into
  diagonal hairlines. Extended each path's body by one period above
  (M-point) and one period below (last L-line) — closures now sit at
  y=-period and y=1800+period, far outside any visible viewport
  position. Loop seamlessness is preserved because translation is still
  by exactly one period.

- Radial-glow `<rect>` backdrops (2×) spanned only the original viewBox
  0..900 range. After the wave-path extension, they were the only
  layer ending at y=0 / y=900, so the boundary became visible as a
  faint opacity step (gradient-glow + waves below vs. waves alone above).
  Stretched both rects to -900..3600 to match the wave coverage, and
  flipped the two radial gradients to `gradientUnits="userSpaceOnUse"`
  with absolute centres so the glows stay anchored to their original
  positions instead of stretching downward with the larger rect.

- The SVG element's own rotated top/bottom edge (the rectangle of the
  <svg> element itself, 110% × 180% of viewport). With path + gradient
  extensions in place this is the only remaining hard edge. Added a CSS
  `mask-image: linear-gradient(...)` fade on the SVG element — applied
  in local coordinate space before transform, so the fade direction
  rotates with the SVG and tracks the boundary perfectly. Hard rectangle
  edge → smooth fade-to-transparent. Both -webkit- and unprefixed forms
  for breadth (Safari pre-15.4).

Result: no visible diagonal artifacts at any tested viewport size; the
existing `prefers-reduced-motion: reduce` rule and dark-theme tinting
are untouched.

* Pricing calculators: replace ∞ glyph with tabler:infinity icon

Slider tail tick labels rendered the infinity symbol via the unicode
`&infin;` (U+221E) glyph at 28px font-size. Cross-platform font metrics
for this character vary a lot — on Android it renders noticeably taller
than on desktop, and Chrome's mobile text autosizing can boost it
further, making the ∞ look disproportionately huge next to the
12px numeric tick labels.

Replaced the glyph with the tabler `infinity` SVG icon so the visual
size is pinned to a CSS dimension (18px) and stays consistent across
Android / iOS / desktop:

- 5 static .astro templates (TbPayg, TbPerpetual, TbmqPayg,
  TbmqPerpetual, TbmqPrivateCloud) — `<span class="…infinity">&infin;</span>`
  becomes `<span class="…infinity"><Icon name="tabler:infinity" /></span>`.
  The `Icon` component was already imported in each file.

- TbPrivateCloudCalculator builds its slider ticks in client-side JS
  (`buildTicks()` runs in the browser, can't call Astro's <Icon>) — added
  an `INFINITY_ICON` string constant that inlines the same SVG markup
  astro-icon emits (`width="1em"`, `currentColor` stroke), used when
  the tick label equals `'∞'`.

- Shared `.calc-tick-label.infinity` rule in CalculatorModal.astro went
  from `font-size: 28px; font-weight: 300; line-height: 24px` (sizing a
  text glyph) to `font-size: 18px; line-height: 1` (sizing the 1em SVG).
  `currentColor` stroke picks up the existing tick-label hover state for
  free, so no extra interaction rules were needed.

* Use-case diagrams: replace generic schema, resize to 1038px (PROD-8078)

PROD-8078 flagged that the IoT-architecture diagram on most use-case
pages was the wrong one (the LoRaWAN/Sigfox sensor-tree variant from
the old environment-monitoring layout, mistakenly mounted as the
generic `use-case.svg` for nine other pages) and that all schema
diagrams should be 1038px wide instead of 720px.

- Re-exported 14 schemas from Figma `FUX2Li59wxdYASam49kH05` via the
  REST API at scale=1.4417 → native 1038px width, then ran
  `svgo --multipass` (≈68% size reduction off the raw export). Final
  files are 220-260 KB SVG.

- `use-case.svg` + `use-case-dark.svg` now hold the simple Modbus /
  OPC-UA / BACnet / Other-Protocols → IoT Gateway → ThingsBoard →
  Alarms/Dashboards/Notifications/Data Lakes diagram (Figma frame
  `1364:13291` / `1235:28448`). The nine pages still pointing at
  `use-case.svg` — smart-office, smart-retail, smart-farming,
  site-fleet-tracking, smart-metering, air-quality-monitoring,
  smart-irrigation, waste-management, tank-level-monitoring — pick up
  the new diagram automatically with no data-file edits.

- Refreshed the other six per-page diagrams from their respective Figma
  frames at the same 1038 width: smart-energy, water-metering,
  health-care, swimming-pool, oil-and-gas, energy-management (each
  light+dark pair).

- Added two new files: `environment-monitoring.svg` +
  `environment-monitoring-dark.svg` (Figma frames `1364:13314` /
  `1364:12915`) holding the LoRaWAN/Sigfox variant — what was
  previously inside `use-case.svg`. PROD-8078 marks env-monitoring as
  "ok", so its diagram is preserved verbatim, just relocated to a
  page-specific path and brought up to 1038px.

- `src/data/use-cases/environment-monitoring.ts:56` — `schemeSrc` now
  points to the new env-monitoring-specific file.

* ImageGallery: opt out of PhotoSwipe lightbox for use-case schemas

The architecture schemas on use-case pages (rendered by
`SolutionStructure.astro`) are already full content-width — there's no
extra detail revealed by opening them in the lightbox. Click-to-zoom
also reads as more awkward than helpful: PhotoSwipe v5's
backdrop-filter blur on a mostly-white page produces a pale gray
backdrop instead of the strongly dark feel the lightbox has on docs
pages with their dark sidebars (same computed styles, different page
colors behind the blur).

- New `noLightbox?: boolean` prop on `<ImageGallery>`. When set on a
  single-image gallery (and not in `cardMode`), the figure renders the
  `<img>` (or interactive SVG) directly without the `<a
  class="gallery-thumb">` wrapper. The parent picks up an
  `image-gallery--no-lightbox` modifier class for any future styling
  hook.

- PhotoSwipe's init uses `children: '.gallery-thumb'`. With no
  `.gallery-thumb` element inside a no-lightbox gallery, the binding
  is a no-op for that gallery — no JS branch needed.

- CSS rule for `.image-gallery--no-lightbox .single-image > img` /
  `> :global(svg)` mirrors the sizing rules of `.single-thumb img` so
  the image fills the column the same way.

- Light/dark variant swap (`.light-only` / `.dark-only`) continues to
  work — those rules target the `<img>` class directly, not the
  wrapper.

- `SolutionStructure.astro` passes `noLightbox` to its single-image
  ImageGallery. Other ImageGallery usages are untouched.

* Use-case schemas: render inline theme-aware (drop noLightbox path)

Reverses commit 562c247 ("ImageGallery: opt out of PhotoSwipe lightbox
for use-case schemas") and replaces the indirection with a direct inline
render in `SolutionStructure.astro`.

Why the change of approach: the ImageGallery `noLightbox` prop was a
narrow opt-out used in exactly one place (use-case architecture
schemas), and it still left the schema rendering coupled to the
gallery's product-suffix resolution / PhotoSwipe scaffolding even
though neither was being used. Rendering the schema inline keeps
SolutionStructure self-contained and removes a special-case branch
from a component that's shared across docs.

- Revert all noLightbox additions in `ImageGallery.astro` (prop,
  Astro.props destructure, JSX branch, CSS rule, modifier class).
- `SolutionStructure.astro` now resolves the schema asset via
  `import.meta.glob('/src/assets/schemas/*.svg', { eager: true })`,
  picks up an optional `-dark.svg` sibling, and renders a
  `<figure class="uc-scheme">` with two `<img>` children using
  `.uc-scheme-img--light` / `.uc-scheme-img--dark` modifier classes.
- Theme swap is a plain `[data-theme='dark']` CSS rule pair (no JS,
  no PhotoSwipe binding); when a dark variant doesn't exist the light
  image stays visible in both themes.
- Optional `schemeCaption` renders as a `<figcaption>` (was lightbox-
  only in the ImageGallery path, so this is a small UX bonus for
  schemas that supply one).

* ImageGallery: clear inherited --color-bg on PhotoSwipe root

Starlight defines `--color-bg` globally; PhotoSwipe v5's root element
(`.pswp`) inherits it, which paints a tinted (non-transparent) layer
behind the lightbox content on non-docs pages where the page bg differs
from the Starlight default. Override with `--color-bg: transparent` so
the `.pswp__bg` backdrop-filter blur is the only thing painted behind
the image, regardless of which page hosts the gallery.

* Pricing calculators: silently swallow clipboard rejections

`navigator.clipboard.writeText(text).then(flashCopied)` without a
`.catch` lets any rejection bubble as an unhandled promise rejection.
The most common real-world trigger isn't the insecure-context case the
old execCommand fallback covered — it's Safari/Firefox throwing
`NotAllowedError: Document is not focused` when focus shifts to another
window/iframe between the click and the promise settling. That path
rejects on HTTPS too.

Add a no-op `.catch(() => {})` to all six calculators so rejections
fail silently (no `.copied` flash) without surfacing as console errors
or hitting any error tracker. The insecure-context execCommand fallback
is intentionally not restored.

Addresses PR #391 inline review comment from vvlladd28.
@vvlladd28 vvlladd28 merged commit 97a052b into release/4.3 May 19, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants