Widgets for your website
Live examples of the same JavaScript widgets used by the anonymous portal overview. The overview cards require no iframe, account or API key. The purchase map requires a public Google Maps browser key.
Available in this source branch; unreleased. Deploy API and Web from the same release before using this on a public website.
Instructions and limitations
Copy an example into your own page. Use the API hostname for your tenant and the matching release environment. The module creates its own Shadow DOM and loads its stylesheet, so your website CSS does not change the cards. Labels, names and default colors come from that API. The host element controls available width: cards use a 300px minimum and wrap automatically. Use machineCount: 1, 2 or 3 for distinct random running machines. Use mountProgressWidgets for a specific unit, location or bank KID.
The module sends credential-free GET requests only. These public widget reads allow external origins; manager/session operations retain their exact-origin CORS restrictions. If your website uses Content Security Policy, allow the API origin in script-src, connect-src, img-src and style-src; dynamic progress also requires inline styles, the purchase chart requires data: in img-src, and WashDoc previews require blob: in img-src. Use HTTPS and a browser with ES modules, Shadow DOM, fetch and AbortSignal.timeout. Do not embed credentials. The data is live and may be unavailable; 503 means unavailable, never zero. Each card retries automatically and marks retained values as unavailable after a failed refresh. The ready promise reports initialization errors; set unavailableText for a localized initial failure message. Call destroy() when removing or replacing a widget group. Removing a host stops its polling automatically.
Running count refreshes every 15 seconds; purchases, reservations and machine pool every minute; active users every minute (the API caches their count for five minutes). Requests share one snapshot within the page. Countdown runs locally every second using server time, retains each selected machine and shows completion for 20 seconds. Pool bounds and public fields are unchanged; images are API-generated SVGs. Amounts remain separated by currency.
Paste the canonical KID from this tenant. No login is required. Location and bank include every public unit, including idle units. Use Load more for subsequent pages; loaded pages refresh every minute. Unknown timing is labelled, never replaced by a made-up countdown.
Purchase map widget
Mount the compact live purchase map directly, inside its own Shadow DOM. No iframe, portal shell, login or bearer token is required. The API site selects the tenant. Data refreshes every 10 seconds; failures back off for 30 seconds. Call destroy() when removing the widget. Supply googleMapsBrowserKey from the embedding website's public browser-key configuration; never use a server geocoding key. The option takes precedence over the nullable googleMapsBrowserKey from GetPublicWidgetPresentation (available only when the API already has GoogleMaps:ApiKey configured). The API does not need that setting when the embedding site supplies its own key. Without either source, ready rejects. Google HTTP-referrer restrictions must allow the embedding site; the widget does not change them. For sites with Content Security Policy, also follow Google Maps CSP guidance.
<div id="purchase-map" style="width:100%;height:400px"></div>
<script type="module">
import { mountPurchaseMap } from 'https://YOUR-API/docs/widgets.mjs';
const widget = mountPurchaseMap(document.querySelector('#purchase-map'), {
apiBase: 'https://YOUR-API', language: 'en-GB',
googleMapsBrowserKey: 'YOUR_PUBLIC_BROWSER_KEY'
});
await widget.ready;
// Call widget.destroy() before removing the host.
</script>Map layers: showCoins defaults to true; showHeatmap defaults to false. For a heatmap-only card, set showCoins: false, showHeatmap: true. Available in source; unreleased.
Set zoom: 7 to use a fixed zoom level after centering on the data. Values from 0 to 22 are supported. Omit zoom to fit all locations automatically. Unreleased.
Set startPosition: { latitude: 56.2, longitude: 10.5 } to choose the initial map centre. Latitude must be from -90 to 90 and longitude from -180 to 180. Combine with zoom: 6. With startPosition, automatic data fitting is skipped; live purchase following and manual navigation remain available. Omit it to keep automatic fitting. Available in source; unreleased.
After widget.ready, widget.getView() returns the current { startPosition: { latitude, longitude }, zoom }, or null when unavailable or destroyed. It reflects manual map movements. Unreleased.
Latest photos
mountRecentPhotos(host, options) displays one public thumbnail at a time, rotating every three seconds and refreshing every minute. Set apiBase to the tenant API and provide alt, loadingText, emptyText and unavailableText. It returns ready and destroy(). Only public thumbnails are loaded; original media remains protected. New export: unreleased.
const photos = mountRecentPhotos(element, { apiBase, alt: "Photo", emptyText: "No photos", unavailableText: "Unavailable" });
await photos.ready;
// On removal:
photos.destroy();