@scalio-cloud/ui 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.11.0
4
+ - Self-hosted support (ADR 0022, T11; needs scalio-connect 0.7.0 in the backend): `supportApi` gets `status()` and
5
+ `setButtonHidden(hidden)`. The support drawer asks `status()` first; a self-hosted installation without a
6
+ connection shows no form, only a note and the button "Zum Scalio-Portal" (`<portal>/support`). The card
7
+ "Support-Verbindung" gets the switch "Support-Knopf in der Kopfzeile ausblenden". **Visible change** only where
8
+ the backend reports `link_only` or the client has `setButtonHidden`; no token changes.
9
+
3
10
  ## 0.10.0
4
11
  - `LicensePanel` takes more from an app's own `map`: a `hint` per usage bar (e.g. base + add-on seats), add-ons with
5
12
  `badges`, `detail`, `tone` (`info`/`warn`) and `removable: false`, `addonErrors` (invalid add-ons, removable),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scalio-cloud/ui",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "Scalio Control Room design tokens, Tailwind preset, self-hosted fonts, the shared app header, sign-in layout, sidebar and page blocks",
5
5
  "license": "SEE LICENSE IN README.md",
6
6
  "private": false,
package/react/labels.js CHANGED
@@ -88,6 +88,12 @@ const LABELS = {
88
88
  supportConnStatus: { unpaired: "Nicht verbunden", pending: "Wartet auf Bestätigung", active: "Verbunden", blocked: "Gesperrt" },
89
89
  supportConnHelp: "Tickets aus dieser Installation gehen an den Scalio Support. Den einmaligen Code erhalten Sie im Scalio-Portal unter Support -> Verbundene Apps.",
90
90
  supportConnHelpConnected: "Tickets aus dieser Installation gehen an den Scalio Support.",
91
+ supportLinkOnly: "Diese Installation ist nicht mit dem Scalio Support verbunden. Eröffnen Sie Ihre Anfrage bitte im Scalio-Portal.",
92
+ supportLinkOnlyAdmin: "Ein Admin kann die Verbindung unter Einstellungen -> Support-Verbindung einrichten, dann gehen Anfragen direkt aus der App.",
93
+ supportOpenPortal: "Zum Scalio-Portal",
94
+ supportButtonHidden: "Support-Knopf in der Kopfzeile ausblenden",
95
+ supportButtonHiddenNote: "Der Support-Knopf ist ausgeblendet.",
96
+ supportButtonShownNote: "Der Support-Knopf ist wieder sichtbar.",
91
97
  supportConnPending: "Ein Administrator Ihrer Organisation muss die Verbindung im Scalio-Portal bestätigen.",
92
98
  supportConnBlocked: "Diese Installation ist für den Support gesperrt. Bitte wenden Sie sich an Scalio.",
93
99
  supportConnKeyLost: "Der Schlüssel dieser Verbindung kann nicht mehr gelesen werden. Bitte verbinden Sie neu.",
@@ -277,6 +283,12 @@ const LABELS = {
277
283
  supportConnStatus: { unpaired: "Not connected", pending: "Waiting for confirmation", active: "Connected", blocked: "Blocked" },
278
284
  supportConnHelp: "Tickets from this installation go to Scalio Support. You get the one-time code in the Scalio portal under Support -> Connected apps.",
279
285
  supportConnHelpConnected: "Tickets from this installation go to Scalio Support.",
286
+ supportLinkOnly: "This installation is not connected to Scalio Support. Please open your request in the Scalio portal.",
287
+ supportLinkOnlyAdmin: "An admin can set up the connection under Settings -> Support connection; then requests go straight from the app.",
288
+ supportOpenPortal: "Open the Scalio portal",
289
+ supportButtonHidden: "Hide the support button in the header",
290
+ supportButtonHiddenNote: "The support button is hidden.",
291
+ supportButtonShownNote: "The support button is visible again.",
280
292
  supportConnPending: "An administrator of your organisation must confirm the connection in the Scalio portal.",
281
293
  supportConnBlocked: "This installation is blocked for support. Please contact Scalio.",
282
294
  supportConnKeyLost: "The key of this connection can no longer be read. Please connect again.",
package/react/support.js CHANGED
@@ -29,6 +29,8 @@ function supportApi(api) {
29
29
  connect: (portal_url, code) => data(api.post("/support/connection", { portal_url, code })),
30
30
  check: () => data(api.post("/support/connection/check")),
31
31
  disconnect: () => data(api.delete("/support/connection")),
32
+ status: () => data(api.get("/support/status")),
33
+ setButtonHidden: (hidden) => data(api.put("/support/connection/button", { hidden })),
32
34
  };
33
35
  }
34
36
 
@@ -223,8 +225,27 @@ function TicketDetail({ client, id, L, lang, onBack }) {
223
225
  );
224
226
  }
225
227
 
228
+ // Self-hosted without a connection (ADR 0022, T11): no form, only the way to the portal's support page.
229
+ function PortalLink({ status, L }) {
230
+ return h(
231
+ "div",
232
+ { className: "scalio-support-form", "data-testid": "support-link-only" },
233
+ h("p", { className: "scalio-support-meta" }, L.supportLinkOnly),
234
+ h("a", { className: "scalio-btn-primary", href: status.portal_page, target: "_blank", rel: "noopener noreferrer",
235
+ "data-testid": "support-portal-link" }, L.supportOpenPortal),
236
+ h("p", { className: "scalio-support-meta" }, L.supportLinkOnlyAdmin)
237
+ );
238
+ }
239
+
226
240
  function SupportDesk({ client, page, lang, labels }) {
227
241
  const L = labelsFor(lang, labels);
242
+ const [status, setStatus] = React.useState(client.status ? null : {});
243
+ React.useEffect(() => {
244
+ if (!client.status) return undefined;
245
+ let alive = true;
246
+ client.status().then((d) => alive && setStatus(d || {})).catch(() => alive && setStatus({}));
247
+ return () => { alive = false; };
248
+ }, [client]);
228
249
  const [tab, setTab] = React.useState("new");
229
250
  const [ticket, setTicket] = React.useState(null);
230
251
  const [note, setNote] = React.useState("");
@@ -233,6 +254,8 @@ function SupportDesk({ client, page, lang, labels }) {
233
254
  type: "button", role: "tab", "aria-selected": tab === key, className: cx("scalio-support-tab", tab === key && "is-active"),
234
255
  onClick: () => { setTab(key); setTicket(null); setNote(""); }, "data-testid": `support-tab-${key}`,
235
256
  }, label);
257
+ if (status === null) return h("div", { className: "scalio-support-meta" }, L.loading);
258
+ if (status.link_only && status.portal_page) return h(PortalLink, { status, L });
236
259
  return h(
237
260
  React.Fragment,
238
261
  null,
@@ -313,6 +336,15 @@ function SupportConnection({ client, lang, labels, onChange }) {
313
336
  : null,
314
337
  note ? h("div", { className: "scalio-notice is-ok", "data-testid": "support-note" }, note) : null,
315
338
  error ? h("div", { className: "scalio-notice is-error", role: "alert", "data-testid": "support-error" }, error) : null,
339
+ client.setButtonHidden
340
+ ? h(
341
+ "label",
342
+ { className: "scalio-support-check", "data-testid": "support-button-hidden" },
343
+ h("input", { type: "checkbox", checked: !!st.button_hidden, disabled: busy,
344
+ onChange: (e) => { const hide = e.target.checked; run(() => client.setButtonHidden(hide), hide ? L.supportButtonHiddenNote : L.supportButtonShownNote); } }),
345
+ h("span", null, L.supportButtonHidden)
346
+ )
347
+ : null,
316
348
  connected
317
349
  ? h(
318
350
  "div",