@growth-operations/ui-shared 1.27.0 → 1.29.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/package.json +1 -1
- package/src/home/FeatureUsage.jsx +17 -6
- package/src/lib/featureUsage.js +5 -1
package/package.json
CHANGED
|
@@ -61,16 +61,25 @@ function RecommendedTile({ notInUse, isSuperAdmin, onNavigate }) {
|
|
|
61
61
|
<Flex direction="column" gap="small">
|
|
62
62
|
<Text format={{ fontWeight: "bold" }}>Recommended to explore</Text>
|
|
63
63
|
{picks.map((f) => {
|
|
64
|
-
// Setup CTAs
|
|
65
|
-
//
|
|
66
|
-
//
|
|
67
|
-
//
|
|
64
|
+
// Setup CTAs render for EVERYONE (1.29.0, Jasper 2026-10-14: "why
|
|
65
|
+
// gate so much on super admin?"). The old blanket super-admin gate
|
|
66
|
+
// assumed the targets were admin-only surfaces — but HubSpot
|
|
67
|
+
// permissions are granular (CRM customization ≠ super admin), and
|
|
68
|
+
// hiding the CTA kept non-admins from even knowing what to ask
|
|
69
|
+
// their admin for. adminOnly items instead carry a "(Super Admin)"
|
|
70
|
+
// hint for non-admin viewers, so the permission wall is never a
|
|
71
|
+
// blind click. The adminOnly marker still distinguishes the two
|
|
72
|
+
// surface kinds; old backends emit no marker → every item gets the
|
|
73
|
+
// hint for non-admins (conservative, and matches the old gate's
|
|
74
|
+
// assumption that the targets are admin surfaces).
|
|
68
75
|
//
|
|
69
76
|
// "Learn more →" (docs_url) intentionally NOT rendered (Jasper
|
|
70
77
|
// 2026-10-14): every feature's docs_url points at the same single
|
|
71
78
|
// setup guide — noise until per-feature articles exist. docs_url
|
|
72
79
|
// stays in the wire contract; re-enabling is a one-line revert.
|
|
73
|
-
const ctas =
|
|
80
|
+
const ctas = f.ctas;
|
|
81
|
+
const hint = (c) =>
|
|
82
|
+
c.adminOnly && !isSuperAdmin ? " (Super Admin)" : "";
|
|
74
83
|
return (
|
|
75
84
|
<Flex key={f.key} direction="column" gap="extra-small">
|
|
76
85
|
<Text format={{ fontWeight: "demibold" }}>{f.name}</Text>
|
|
@@ -78,7 +87,8 @@ function RecommendedTile({ notInUse, isSuperAdmin, onNavigate }) {
|
|
|
78
87
|
{ctas.map((cta) =>
|
|
79
88
|
cta.url ? (
|
|
80
89
|
<Link key={cta.label} href={{ url: cta.url, external: true }}>
|
|
81
|
-
{cta.label}
|
|
90
|
+
{cta.label}
|
|
91
|
+
{hint(cta)} →
|
|
82
92
|
</Link>
|
|
83
93
|
) : onNavigate ? (
|
|
84
94
|
<Button
|
|
@@ -87,6 +97,7 @@ function RecommendedTile({ notInUse, isSuperAdmin, onNavigate }) {
|
|
|
87
97
|
onClick={() => onNavigate(cta.route)}
|
|
88
98
|
>
|
|
89
99
|
{cta.label}
|
|
100
|
+
{hint(cta)}
|
|
90
101
|
</Button>
|
|
91
102
|
) : null
|
|
92
103
|
)}
|
package/src/lib/featureUsage.js
CHANGED
|
@@ -18,13 +18,17 @@ const normalizeUnit = (u) =>
|
|
|
18
18
|
// One well-formed setup CTA is {label: non-empty string, url XOR route:
|
|
19
19
|
// non-empty string}. Anything else (missing label, both targets, neither
|
|
20
20
|
// target, wrong types) is dropped — a malformed item never renders.
|
|
21
|
+
// admin_only (1.28.0): an explicit false marks a per-user surface (installing
|
|
22
|
+
// the Chrome extension) that renders for EVERYONE; a missing marker means
|
|
23
|
+
// admin-only, so old backends keep the blanket super-admin gate.
|
|
21
24
|
const normalizeCta = (c) => {
|
|
22
25
|
if (!c || typeof c !== "object") return null;
|
|
23
26
|
const label = typeof c.label === "string" && c.label ? c.label : null;
|
|
24
27
|
const url = typeof c.url === "string" && c.url ? c.url : null;
|
|
25
28
|
const route = typeof c.route === "string" && c.route ? c.route : null;
|
|
26
29
|
if (!label || !(url || route) || (url && route)) return null;
|
|
27
|
-
|
|
30
|
+
const adminOnly = c.admin_only !== false;
|
|
31
|
+
return { label, ...(url ? { url } : { route }), adminOnly };
|
|
28
32
|
};
|
|
29
33
|
|
|
30
34
|
// Resolve the feature_usage block into render-ready shape:
|