@pablo2410/shared-ui 0.23.0 → 0.25.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/README.md +51 -0
- package/dist/{chunk-4QJMLQSH.js → chunk-7LI4Y6WT.js} +21 -2
- package/dist/chunk-7LI4Y6WT.js.map +1 -0
- package/dist/{chunk-4ERWOH67.js → chunk-MGTOQY6O.js} +2 -2
- package/dist/chunk-T3W42HMO.js +1145 -0
- package/dist/chunk-T3W42HMO.js.map +1 -0
- package/dist/{chunk-S4UQSTZN.js → chunk-Z4P7V5SL.js} +8 -2
- package/dist/chunk-Z4P7V5SL.js.map +1 -0
- package/dist/components/index.js +3 -3
- package/dist/hierarchy/index.js +1 -1
- package/dist/layout/index.js +4 -3
- package/dist/reporting/index.d.ts +83 -17
- package/dist/reporting/index.js +518 -10
- package/dist/reporting/index.js.map +1 -1
- package/dist/services/index.d.ts +18 -2
- package/dist/services/index.js +2 -2
- package/dist/shell/index.js +5 -4
- package/dist/shell/index.js.map +1 -1
- package/dist/shell/oplytics-shell.css +1 -1
- package/dist/tour/index.d.ts +197 -1
- package/dist/tour/index.js +55 -601
- package/dist/tour/index.js.map +1 -1
- package/package.json +10 -9
- package/dist/chunk-4QJMLQSH.js.map +0 -1
- package/dist/chunk-S4UQSTZN.js.map +0 -1
- /package/dist/{chunk-4ERWOH67.js.map → chunk-MGTOQY6O.js.map} +0 -0
package/README.md
CHANGED
|
@@ -52,6 +52,57 @@ import { OPLYTICS_COLORS, OPLYTICS_FONTS } from "@oplytics/shared-ui/theme";
|
|
|
52
52
|
import { useMobile, usePersistFn } from "@oplytics/shared-ui/hooks";
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
+
## Opi tours
|
|
56
|
+
|
|
57
|
+
Every module gets its onboarding tour the same way. A module supplies a
|
|
58
|
+
definition and marks the elements its spotlight steps point at — nothing else
|
|
59
|
+
is per-module (no storage, no trigger, no narration code):
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
import {
|
|
63
|
+
useRegisterTour,
|
|
64
|
+
type TourDefinition,
|
|
65
|
+
} from "@pablo2410/shared-ui/tour";
|
|
66
|
+
|
|
67
|
+
// Module scope (or useMemo) so the object is stable across renders.
|
|
68
|
+
const tour: TourDefinition = {
|
|
69
|
+
id: "policy-deployment", // lowercase-kebab; never rename once shipped
|
|
70
|
+
steps: [
|
|
71
|
+
{ id: "welcome", kind: "intro", label: "Welcome", fallbackText: "…" },
|
|
72
|
+
{
|
|
73
|
+
id: "plans",
|
|
74
|
+
kind: "service",
|
|
75
|
+
label: "Policy plans",
|
|
76
|
+
fallbackText: "…",
|
|
77
|
+
spotlight: { selector: "plan-card" }, // <div data-tour-target="plan-card">
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
function PolicyPage() {
|
|
83
|
+
useRegisterTour(tour);
|
|
84
|
+
// …
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
What the shared code then does:
|
|
89
|
+
|
|
90
|
+
- **Trigger** — `DashboardLayout`'s header shows "Take the tour" only while a
|
|
91
|
+
tour is registered, and replays it from step 1.
|
|
92
|
+
- **Progress** — read and written through Portal's `onboarding.userTourState`
|
|
93
|
+
/ `setUserTourState`, so it follows the user across modules. No module table.
|
|
94
|
+
- **Narration** — each step calls Portal's `ai.askOpi` with the reserved
|
|
95
|
+
`onboarding` service (Portal's onboarding persona), falling back to the
|
|
96
|
+
step's `fallbackText` if Opi is unavailable.
|
|
97
|
+
- **Auto-open** — off by default; set `autoStart: true` on the definition to
|
|
98
|
+
open for users who haven't seen the tour or left it part-way. Modules never
|
|
99
|
+
mount their own `OpiTourHost` — `DashboardLayout` mounts the one.
|
|
100
|
+
|
|
101
|
+
Per-tour storage needs Portal to accept and echo a `tourId` on those two
|
|
102
|
+
endpoints. Until it does, progress for module tours is not saved (reads fail
|
|
103
|
+
safe, nothing auto-opens, the tour and its header replay still work), and the
|
|
104
|
+
Service Hub tour's own progress is never overwritten.
|
|
105
|
+
|
|
55
106
|
## Theme CSS
|
|
56
107
|
|
|
57
108
|
Import the canonical Oplytics theme variables:
|
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
// src/services/platformDomain.ts
|
|
2
2
|
var DEFAULT_PLATFORM_DOMAIN = "oplyticsdigital.net";
|
|
3
3
|
var IPV4 = /^\d{1,3}(\.\d{1,3}){3}$/;
|
|
4
|
+
var SANDBOX_LOCALHOST_PORTS = {
|
|
5
|
+
portal: 3e3,
|
|
6
|
+
sqdcp: 3001,
|
|
7
|
+
oeemanager: 3002,
|
|
8
|
+
actionmanager: 3003,
|
|
9
|
+
businesshub: 3004,
|
|
10
|
+
connect: 3005,
|
|
11
|
+
"policy-deployment": 3006,
|
|
12
|
+
"marketing-site": 3007
|
|
13
|
+
};
|
|
4
14
|
function getPlatformDomain() {
|
|
5
15
|
if (typeof window === "undefined") return DEFAULT_PLATFORM_DOMAIN;
|
|
6
16
|
const host = window.location.hostname;
|
|
7
|
-
if (!host ||
|
|
17
|
+
if (!host || IPV4.test(host)) {
|
|
18
|
+
return DEFAULT_PLATFORM_DOMAIN;
|
|
19
|
+
}
|
|
20
|
+
if (host === "localhost") {
|
|
8
21
|
return DEFAULT_PLATFORM_DOMAIN;
|
|
9
22
|
}
|
|
10
23
|
const parts = host.split(".");
|
|
@@ -13,6 +26,12 @@ function getPlatformDomain() {
|
|
|
13
26
|
return DEFAULT_PLATFORM_DOMAIN;
|
|
14
27
|
}
|
|
15
28
|
function platformUrl(subdomainLabel, path = "") {
|
|
29
|
+
if (typeof window !== "undefined" && window.location.hostname === "localhost") {
|
|
30
|
+
const port = SANDBOX_LOCALHOST_PORTS[subdomainLabel];
|
|
31
|
+
if (port !== void 0) {
|
|
32
|
+
return `http://localhost:${port}${path}`;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
16
35
|
return `https://${subdomainLabel}.${getPlatformDomain()}${path}`;
|
|
17
36
|
}
|
|
18
37
|
function portalUrl(path = "") {
|
|
@@ -25,4 +44,4 @@ export {
|
|
|
25
44
|
platformUrl,
|
|
26
45
|
portalUrl
|
|
27
46
|
};
|
|
28
|
-
//# sourceMappingURL=chunk-
|
|
47
|
+
//# sourceMappingURL=chunk-7LI4Y6WT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/services/platformDomain.ts"],"sourcesContent":["/**\n * Platform domain resolution — single source of truth for building\n * cross-service URLs (Service Hub cards, sidebar cross-nav, footers,\n * \"Back to Portal\" links).\n *\n * Every service runs on a sibling subdomain of one parent domain\n * (portal.oplyticsdigital.net, sqdcp.oplyticsdigital.net, …), so the parent\n * domain is derived at runtime from the current hostname: strip the service\n * label, keep the rest. Links therefore stay on whichever domain the app is\n * served from — no per-app build args, and a future domain move needs no\n * code change here.\n *\n * Outside a browser (SSR, tests) or on hosts with no parent domain\n * (raw IPs) the canonical production domain is used.\n *\n * The local MacBook sandbox (docker-compose.sandbox.yml) is a special case:\n * every app is served from bare `localhost` on a fixed port per service,\n * not from sibling subdomains — so there is no domain to derive from the\n * hostname the way there is for sandbox-*.oplyticsdigital.net (the tunnel\n * variant) or real subdomains. Without this map, any cross-service link\n * built from `localhost` silently fell back to production (see incident:\n * Business Hub's sidebar link sent an authenticated sandbox user to\n * businesshub.oplyticsdigital.net instead of localhost:3004). This list\n * must be kept in sync with the port assignments in each sandbox compose\n * file — there is currently no single generated source for both.\n */\n\nexport const DEFAULT_PLATFORM_DOMAIN = \"oplyticsdigital.net\";\n\nconst IPV4 = /^\\d{1,3}(\\.\\d{1,3}){3}$/;\n\n/**\n * Fixed local-sandbox port per service subdomain label. Keys match the\n * actual subdomain label / sandbox compose service name each app uses to\n * call platformUrl(...) (e.g. \"oeemanager\", not the hyphenated\n * \"/oee-manager\" Infisical secrets folder — those two naming schemes are\n * already inconsistent elsewhere in this codebase; don't propagate that\n * inconsistency here).\n */\nexport const SANDBOX_LOCALHOST_PORTS: Record<string, number> = {\n portal: 3000,\n sqdcp: 3001,\n oeemanager: 3002,\n actionmanager: 3003,\n businesshub: 3004,\n connect: 3005,\n \"policy-deployment\": 3006,\n \"marketing-site\": 3007,\n};\n\nexport function getPlatformDomain(): string {\n if (typeof window === \"undefined\") return DEFAULT_PLATFORM_DOMAIN;\n const host = window.location.hostname;\n if (!host || IPV4.test(host)) {\n return DEFAULT_PLATFORM_DOMAIN;\n }\n if (host === \"localhost\") {\n // Handled by platformUrl's port-map branch below — a bare domain has no\n // meaning on localhost, since every sandbox service shares the same\n // host and differs only by port. Falling back to the production domain\n // here would be wrong for any localhost caller, so this path should\n // only be reached by code that doesn't also need a port (rare); return\n // the production domain as the least-surprising default for that case.\n return DEFAULT_PLATFORM_DOMAIN;\n }\n const parts = host.split(\".\");\n // sqdcp.oplyticsdigital.net → oplyticsdigital.net\n if (parts.length >= 3) return parts.slice(1).join(\".\");\n // already on the apex (oplyticsdigital.net)\n if (parts.length === 2) return host;\n return DEFAULT_PLATFORM_DOMAIN;\n}\n\n/**\n * Absolute URL for a service subdomain label on the current platform\n * domain, e.g. `platformUrl(\"sqdcp\")` → `https://sqdcp.oplyticsdigital.net`.\n *\n * On the local sandbox (hostname === \"localhost\"), resolves instead to\n * `http://localhost:<port>` using SANDBOX_LOCALHOST_PORTS, so cross-service\n * links (e.g. Portal's sidebar → Business Hub) stay local instead of\n * silently jumping to production.\n */\nexport function platformUrl(subdomainLabel: string, path = \"\"): string {\n if (\n typeof window !== \"undefined\" &&\n window.location.hostname === \"localhost\"\n ) {\n const port = SANDBOX_LOCALHOST_PORTS[subdomainLabel];\n if (port !== undefined) {\n return `http://localhost:${port}${path}`;\n }\n // Unknown label on localhost — no safe local target exists, so fall\n // through to the production URL rather than guessing a port. Better to\n // land on a working page and be visibly wrong (prod) than a broken one.\n }\n return `https://${subdomainLabel}.${getPlatformDomain()}${path}`;\n}\n\n/** Portal URL builder — the portal always lives at the `portal` label. */\nexport function portalUrl(path = \"\"): string {\n return platformUrl(\"portal\", path);\n}\n"],"mappings":";AA2BO,IAAM,0BAA0B;AAEvC,IAAM,OAAO;AAUN,IAAM,0BAAkD;AAAA,EAC7D,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,aAAa;AAAA,EACb,SAAS;AAAA,EACT,qBAAqB;AAAA,EACrB,kBAAkB;AACpB;AAEO,SAAS,oBAA4B;AAC1C,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,QAAM,OAAO,OAAO,SAAS;AAC7B,MAAI,CAAC,QAAQ,KAAK,KAAK,IAAI,GAAG;AAC5B,WAAO;AAAA,EACT;AACA,MAAI,SAAS,aAAa;AAOxB,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,KAAK,MAAM,GAAG;AAE5B,MAAI,MAAM,UAAU,EAAG,QAAO,MAAM,MAAM,CAAC,EAAE,KAAK,GAAG;AAErD,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SAAO;AACT;AAWO,SAAS,YAAY,gBAAwB,OAAO,IAAY;AACrE,MACE,OAAO,WAAW,eAClB,OAAO,SAAS,aAAa,aAC7B;AACA,UAAM,OAAO,wBAAwB,cAAc;AACnD,QAAI,SAAS,QAAW;AACtB,aAAO,oBAAoB,IAAI,GAAG,IAAI;AAAA,IACxC;AAAA,EAIF;AACA,SAAO,WAAW,cAAc,IAAI,kBAAkB,CAAC,GAAG,IAAI;AAChE;AAGO,SAAS,UAAU,OAAO,IAAY;AAC3C,SAAO,YAAY,UAAU,IAAI;AACnC;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
platformUrl
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-7LI4Y6WT.js";
|
|
4
4
|
import {
|
|
5
5
|
appendSelectionParam
|
|
6
6
|
} from "./chunk-DMUQ5WNO.js";
|
|
@@ -236,4 +236,4 @@ export {
|
|
|
236
236
|
normalizeServiceSlug,
|
|
237
237
|
buildCrossServiceLinks
|
|
238
238
|
};
|
|
239
|
-
//# sourceMappingURL=chunk-
|
|
239
|
+
//# sourceMappingURL=chunk-MGTOQY6O.js.map
|