@elevasis/ui 2.0.0 → 2.0.2

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.
Files changed (54) hide show
  1. package/dist/auth/index.js +1 -2
  2. package/dist/charts/index.js +7 -9
  3. package/dist/{chunk-FW4S3Z5I.js → chunk-2DSYC52I.js} +3 -3
  4. package/dist/{chunk-ZWY3A6ZU.js → chunk-CTU2JO57.js} +31 -31
  5. package/dist/{chunk-QJ2S46NI.js → chunk-DT3QYZVU.js} +2 -2
  6. package/dist/{chunk-QTD5HPKD.js → chunk-EIHG5JZN.js} +1 -1
  7. package/dist/{chunk-JHVKGZ2P.js → chunk-KFICYU6S.js} +3 -4
  8. package/dist/{chunk-R2BQITMQ.js → chunk-MELNDAZY.js} +20 -110
  9. package/dist/{chunk-RWQIFKMJ.js → chunk-MTJ43R2E.js} +10 -2
  10. package/dist/{chunk-45MS3IAW.js → chunk-MZPVNRPL.js} +136 -28
  11. package/dist/{chunk-NNKKBSJN.js → chunk-NYBEU5TE.js} +1 -1
  12. package/dist/{chunk-2IJCM3VQ.js → chunk-OCP2MBTY.js} +134 -118
  13. package/dist/{chunk-KP6LNTMH.js → chunk-OKKGD3S6.js} +3 -3
  14. package/dist/{chunk-BYZ7VTSH.js → chunk-PRLXFMNP.js} +2 -2
  15. package/dist/{chunk-T2X3WHQS.js → chunk-QRHLV74B.js} +23 -18
  16. package/dist/{chunk-5COLSYBE.js → chunk-RX4UWZZR.js} +1 -1
  17. package/dist/{chunk-C27LLJM6.js → chunk-SMJLS23U.js} +2 -2
  18. package/dist/{chunk-F2J7675J.js → chunk-TQ3HK7ZR.js} +633 -7
  19. package/dist/{chunk-EINVPEHK.js → chunk-TZOGB3X4.js} +2 -2
  20. package/dist/{chunk-TXPUIHX2.js → chunk-X7CHQ3RE.js} +1 -1
  21. package/dist/{chunk-MCA6LOGM.js → chunk-Y3D3WFJG.js} +54 -5
  22. package/dist/{chunk-YYBM5LNJ.js → chunk-YEX4MQSY.js} +1 -1
  23. package/dist/components/index.d.ts +24 -16
  24. package/dist/components/index.js +102 -271
  25. package/dist/features/auth/index.js +3 -4
  26. package/dist/features/dashboard/index.d.ts +15 -4
  27. package/dist/features/dashboard/index.js +15 -18
  28. package/dist/features/monitoring/index.css +127 -127
  29. package/dist/features/monitoring/index.d.ts +1 -0
  30. package/dist/features/monitoring/index.js +17 -19
  31. package/dist/features/operations/index.d.ts +173 -56
  32. package/dist/features/operations/index.js +19 -20
  33. package/dist/features/settings/index.d.ts +1 -0
  34. package/dist/features/settings/index.js +15 -17
  35. package/dist/hooks/index.css +127 -127
  36. package/dist/hooks/index.js +12 -9
  37. package/dist/hooks/published.css +127 -127
  38. package/dist/hooks/published.js +11 -8
  39. package/dist/index.css +118 -118
  40. package/dist/index.d.ts +14 -2
  41. package/dist/index.js +13 -12
  42. package/dist/layout/index.d.ts +20 -44
  43. package/dist/layout/index.js +6 -6
  44. package/dist/provider/index.css +127 -59
  45. package/dist/provider/index.d.ts +14 -2
  46. package/dist/provider/index.js +10 -6
  47. package/dist/provider/published.css +126 -0
  48. package/dist/provider/published.d.ts +14 -2
  49. package/dist/provider/published.js +8 -3
  50. package/dist/theme/index.js +2 -2
  51. package/package.json +3 -3
  52. package/dist/chunk-ALA56RGZ.js +0 -13
  53. package/dist/chunk-JQ4AKYUD.js +0 -635
  54. package/dist/chunk-SZHARWKU.js +0 -15
@@ -1,4 +1,5 @@
1
- import { SubshellContainer, SubshellSidebar, SubshellRightSideContainer } from './chunk-5COLSYBE.js';
1
+ import { SubshellContainer, SubshellSidebar, SubshellRightSideContainer } from './chunk-RX4UWZZR.js';
2
+ import { FeatureUnavailableState } from './chunk-Y3D3WFJG.js';
2
3
  import { ApiClientProvider, useApiClient } from './chunk-NVOCKXUQ.js';
3
4
  import { OrganizationProvider } from './chunk-W4VYXIN7.js';
4
5
  import { getErrorInfo, getErrorTitle, formatErrorMessage } from './chunk-IOKL7BKE.js';
@@ -124,6 +125,10 @@ function OrgServiceBridge({
124
125
  const isReady = !!currentWorkOSOrganizationId && !isInitializing && !isOrgRefreshing;
125
126
  return /* @__PURE__ */ jsx(ElevasisServiceProvider, { apiRequest, organizationId: currentWorkOSOrganizationId, isReady, children: /* @__PURE__ */ jsx(NotificationProvider, { adapter: notifications, children: /* @__PURE__ */ jsx(InitializationProvider, { children }) }) });
126
127
  }
128
+ var FEATURE_KEY_ALIASES = {
129
+ crm: "acquisition",
130
+ "lead-gen": "acquisition"
131
+ };
127
132
  function createUseFeatureAccess({
128
133
  useInitialization: useInitialization2,
129
134
  useOrganization: useOrganization2
@@ -139,7 +144,8 @@ function createUseFeatureAccess({
139
144
  const userConfig = profile?.config;
140
145
  const checkFeature = useCallback(
141
146
  (featureKey) => {
142
- const key = featureKey;
147
+ const normalizedFeatureKey = FEATURE_KEY_ALIASES[featureKey] ?? featureKey;
148
+ const key = normalizedFeatureKey;
143
149
  if (profile?.is_platform_admin) {
144
150
  return { allowed: true, restrictedBy: null };
145
151
  }
@@ -180,19 +186,118 @@ function useOptionalElevasisFeatures() {
180
186
  function getEnabledFeatures(features, hasFeature) {
181
187
  return features.filter((feature) => hasFeature(feature.key));
182
188
  }
183
- function getNavItems(features) {
184
- return features.flatMap((feature) => feature.navEntry ? [feature.navEntry] : []);
189
+ function normalizeRoutePath(path) {
190
+ const trimmedPath = path.trim();
191
+ if (!trimmedPath || trimmedPath === "/") {
192
+ return "/";
193
+ }
194
+ return trimmedPath.replace(/\/+$/, "") || "/";
195
+ }
196
+ function isRouteMatch(currentPath, route) {
197
+ const normalizedCurrentPath = normalizeRoutePath(currentPath);
198
+ const normalizedRoute = normalizeRoutePath(route);
199
+ return normalizedCurrentPath === normalizedRoute || normalizedCurrentPath.startsWith(`${normalizedRoute}/`);
200
+ }
201
+ function filterNavLinks(links, disabledSubsectionPaths, isFeatureEnabled) {
202
+ return links.flatMap((link) => {
203
+ if (link.featureKey && !isFeatureEnabled(link.featureKey)) {
204
+ return [];
205
+ }
206
+ if (disabledSubsectionPaths.some((disabledPath) => isRouteMatch(link.link, disabledPath))) {
207
+ return [];
208
+ }
209
+ const nestedLinks = link.links?.length ? filterNavLinks(link.links, disabledSubsectionPaths, isFeatureEnabled) : void 0;
210
+ return [
211
+ {
212
+ ...link,
213
+ links: nestedLinks
214
+ }
215
+ ];
216
+ });
217
+ }
218
+ function getNavItems(features, disabledSubsectionPaths, isFeatureEnabled) {
219
+ return features.flatMap((feature) => {
220
+ if (!feature.navEntry) {
221
+ return [];
222
+ }
223
+ const links = feature.navEntry.links?.length ? filterNavLinks(feature.navEntry.links, disabledSubsectionPaths, isFeatureEnabled) : void 0;
224
+ return [
225
+ {
226
+ ...feature.navEntry,
227
+ links
228
+ }
229
+ ];
230
+ });
231
+ }
232
+ function findMatchingNavLink(links, currentPath) {
233
+ for (const link of links) {
234
+ if (link.links?.length) {
235
+ const nestedLink = findMatchingNavLink(link.links, currentPath);
236
+ if (nestedLink) {
237
+ return nestedLink;
238
+ }
239
+ }
240
+ if (isRouteMatch(currentPath, link.link)) {
241
+ return link;
242
+ }
243
+ }
244
+ return null;
245
+ }
246
+ function isHiddenNavLink(link, disabledSubsectionPaths, isFeatureEnabled) {
247
+ if (link.featureKey && !isFeatureEnabled(link.featureKey)) {
248
+ return true;
249
+ }
250
+ return disabledSubsectionPaths.some((disabledPath) => isRouteMatch(link.link, disabledPath));
251
+ }
252
+ function resolveNavRoute(features, currentPath, disabledSubsectionPaths, isFeatureEnabled) {
253
+ for (const feature of features) {
254
+ const navEntry = feature.navEntry;
255
+ const matchesSubshell = feature.subshellRoutes?.some((route) => isRouteMatch(currentPath, route)) ?? false;
256
+ const matchesEntryLink = navEntry?.link ? isRouteMatch(currentPath, navEntry.link) : false;
257
+ const matchedLink = navEntry?.links?.length ? findMatchingNavLink(navEntry.links, currentPath) : null;
258
+ if (!matchesSubshell && !matchesEntryLink && !matchedLink) {
259
+ continue;
260
+ }
261
+ if (matchedLink && isHiddenNavLink(matchedLink, disabledSubsectionPaths, isFeatureEnabled)) {
262
+ return {
263
+ state: "disabled",
264
+ path: currentPath,
265
+ feature,
266
+ navEntry,
267
+ navLink: matchedLink
268
+ };
269
+ }
270
+ return {
271
+ state: "enabled",
272
+ path: currentPath,
273
+ feature,
274
+ navEntry,
275
+ navLink: matchedLink ?? void 0
276
+ };
277
+ }
278
+ return {
279
+ state: "missing",
280
+ path: currentPath
281
+ };
185
282
  }
186
283
  function ElevasisFeaturesProvider({
187
284
  features,
188
285
  timeRange,
189
286
  operationsApiUrl,
190
287
  operationsSSEManager,
288
+ disabledSubsectionPaths = [],
191
289
  children
192
290
  }) {
193
291
  const { hasFeature } = useFeatureAccess();
292
+ const normalizedDisabledSubsectionPaths = useMemo(
293
+ () => disabledSubsectionPaths.map((path) => normalizeRoutePath(path)),
294
+ [disabledSubsectionPaths]
295
+ );
194
296
  const enabledFeatures = useMemo(() => getEnabledFeatures(features, hasFeature), [features, hasFeature]);
195
- const navItems = useMemo(() => getNavItems(enabledFeatures), [enabledFeatures]);
297
+ const navItems = useMemo(
298
+ () => getNavItems(enabledFeatures, normalizedDisabledSubsectionPaths, hasFeature),
299
+ [enabledFeatures, normalizedDisabledSubsectionPaths, hasFeature]
300
+ );
196
301
  const getFeature = useCallback(
197
302
  (key) => features.find((feature) => feature.key === key),
198
303
  [features]
@@ -201,6 +306,10 @@ function ElevasisFeaturesProvider({
201
306
  (key) => enabledFeatures.some((feature) => feature.key === key),
202
307
  [enabledFeatures]
203
308
  );
309
+ const resolveNavRouteByPath = useCallback(
310
+ (path) => resolveNavRoute(enabledFeatures, path, normalizedDisabledSubsectionPaths, isFeatureEnabled),
311
+ [enabledFeatures, normalizedDisabledSubsectionPaths, isFeatureEnabled]
312
+ );
204
313
  const value = useMemo(
205
314
  () => ({
206
315
  navItems,
@@ -209,38 +318,37 @@ function ElevasisFeaturesProvider({
209
318
  timeRange,
210
319
  operationsApiUrl,
211
320
  operationsSSEManager,
321
+ disabledSubsectionPaths: normalizedDisabledSubsectionPaths,
212
322
  isFeatureEnabled,
213
- getFeature
323
+ getFeature,
324
+ resolveNavRoute: resolveNavRouteByPath
214
325
  }),
215
- [navItems, enabledFeatures, features, timeRange, operationsApiUrl, operationsSSEManager, isFeatureEnabled, getFeature]
326
+ [
327
+ navItems,
328
+ enabledFeatures,
329
+ features,
330
+ timeRange,
331
+ operationsApiUrl,
332
+ operationsSSEManager,
333
+ normalizedDisabledSubsectionPaths,
334
+ isFeatureEnabled,
335
+ getFeature,
336
+ resolveNavRouteByPath
337
+ ]
216
338
  );
217
339
  return /* @__PURE__ */ jsx(ElevasisFeaturesContext.Provider, { value, children });
218
340
  }
219
- function isRouteMatch(currentPath, route) {
220
- return currentPath.startsWith(route);
221
- }
222
- function resolveFeatureShellFeature(features, currentPath) {
223
- for (const feature of features) {
224
- if (!feature.sidebar || !feature.subshellRoutes?.length) {
225
- continue;
226
- }
227
- if (feature.subshellRoutes.some((route) => isRouteMatch(currentPath, route))) {
228
- return feature;
229
- }
230
- }
231
- return null;
232
- }
233
341
  function FeatureShell({ children }) {
234
- const { enabledFeatures } = useElevasisFeatures();
342
+ const { resolveNavRoute: resolveNavRoute2 } = useElevasisFeatures();
235
343
  const { currentPath } = useRouterContext();
236
- const matchedFeature = useMemo(
237
- () => resolveFeatureShellFeature(enabledFeatures, currentPath),
238
- [enabledFeatures, currentPath]
239
- );
240
- if (!matchedFeature?.sidebar) {
344
+ const routeResolution = resolveNavRoute2(currentPath);
345
+ if (routeResolution.state === "disabled") {
346
+ return /* @__PURE__ */ jsx(FeatureUnavailableState, { path: currentPath });
347
+ }
348
+ if (routeResolution.state !== "enabled" || !routeResolution.feature?.sidebar) {
241
349
  return /* @__PURE__ */ jsx(Fragment, { children });
242
350
  }
243
- const SidebarComponent = matchedFeature.sidebar;
351
+ const SidebarComponent = routeResolution.feature.sidebar;
244
352
  return /* @__PURE__ */ jsxs(SubshellContainer, { children: [
245
353
  /* @__PURE__ */ jsx(SubshellSidebar, { width: 250, children: /* @__PURE__ */ jsx(SidebarComponent, {}) }),
246
354
  /* @__PURE__ */ jsx(SubshellRightSideContainer, { children })
@@ -1,4 +1,4 @@
1
- import { sidebarItemPadding, sidebarItemHeight, sidebarIconSize, sidebarIconStroke, sidebarIconInnerSize } from './chunk-QJ2S46NI.js';
1
+ import { sidebarItemPadding, sidebarItemHeight, sidebarIconSize, sidebarIconStroke, sidebarIconInnerSize } from './chunk-DT3QYZVU.js';
2
2
  import { UnstyledButton, Group, Box, ThemeIcon } from '@mantine/core';
3
3
  import { IconChevronRight } from '@tabler/icons-react';
4
4
  import { jsx, jsxs } from 'react/jsx-runtime';
@@ -1,9 +1,112 @@
1
1
  import { useAppearance } from './chunk-QJ2KCHKX.js';
2
- import { sidebarGroupChevronSize, sidebarIconInnerSize, sidebarListItemIconSize } from './chunk-QJ2S46NI.js';
3
- import { Box, Group, Text, Center, Container, Stack, UnstyledButton, Collapse } from '@mantine/core';
2
+ import { subshellNavItemIconSize, sidebarIconSize, sidebarIconStroke, sidebarIconInnerSize, sidebarGroupChevronSize } from './chunk-DT3QYZVU.js';
3
+ import { UnstyledButton, Stack, Group, Text, Box, ThemeIcon, Center, Container, Collapse } from '@mantine/core';
4
4
  import { jsx, jsxs } from 'react/jsx-runtime';
5
5
  import { IconChevronDown, IconChevronRight } from '@tabler/icons-react';
6
6
 
7
+ var activeColor = "var(--color-primary)";
8
+ var defaultColor = "var(--color-text-subtle)";
9
+ var hoverColor = "var(--color-text)";
10
+ var activeBg = `color-mix(in srgb, ${activeColor} 10%, transparent)`;
11
+ var SubshellNavItem = ({
12
+ icon: Icon,
13
+ label,
14
+ isActive = false,
15
+ onClick,
16
+ description,
17
+ badge,
18
+ disabled = false
19
+ }) => {
20
+ return /* @__PURE__ */ jsx(
21
+ UnstyledButton,
22
+ {
23
+ onClick: disabled ? void 0 : onClick,
24
+ disabled,
25
+ style: {
26
+ width: "100%",
27
+ padding: "var(--mantine-spacing-xs)",
28
+ backgroundColor: isActive ? activeBg : "transparent",
29
+ borderRadius: "var(--mantine-radius-default)",
30
+ transition: `all var(--duration-fast) var(--easing)`,
31
+ cursor: disabled ? "not-allowed" : "pointer",
32
+ opacity: disabled ? 0.5 : 1
33
+ },
34
+ onMouseEnter: (e) => {
35
+ if (!isActive && !disabled) {
36
+ e.currentTarget.style.backgroundColor = "var(--color-surface-hover)";
37
+ const textElements = e.currentTarget.querySelectorAll("[data-text-element]");
38
+ textElements.forEach((el) => {
39
+ el.style.color = hoverColor;
40
+ });
41
+ }
42
+ },
43
+ onMouseLeave: (e) => {
44
+ if (!isActive && !disabled) {
45
+ e.currentTarget.style.backgroundColor = "transparent";
46
+ const textElements = e.currentTarget.querySelectorAll("[data-text-element]");
47
+ textElements.forEach((el) => {
48
+ el.style.color = defaultColor;
49
+ });
50
+ }
51
+ },
52
+ children: /* @__PURE__ */ jsxs(Stack, { gap: 2, children: [
53
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "nowrap", children: [
54
+ /* @__PURE__ */ jsx(
55
+ Icon,
56
+ {
57
+ size: subshellNavItemIconSize,
58
+ style: {
59
+ flexShrink: 0,
60
+ opacity: isActive ? 1 : 0.6,
61
+ color: isActive ? activeColor : defaultColor
62
+ }
63
+ }
64
+ ),
65
+ /* @__PURE__ */ jsx(
66
+ Text,
67
+ {
68
+ size: "sm",
69
+ fw: isActive ? 600 : 400,
70
+ style: {
71
+ overflow: "hidden",
72
+ textOverflow: "ellipsis",
73
+ whiteSpace: "nowrap",
74
+ flex: 1,
75
+ fontFamily: "var(--elevasis-font-family-subtitle)",
76
+ color: isActive ? activeColor : defaultColor,
77
+ transition: `color var(--duration-fast) var(--easing)`
78
+ },
79
+ "data-text-element": true,
80
+ children: label
81
+ }
82
+ ),
83
+ badge && /* @__PURE__ */ jsx("div", { style: { flexShrink: 0 }, children: badge })
84
+ ] }),
85
+ description && /* @__PURE__ */ jsx(
86
+ Text,
87
+ {
88
+ size: "xs",
89
+ c: "dimmed",
90
+ style: {
91
+ paddingLeft: "22px",
92
+ lineHeight: 1.2,
93
+ color: isActive ? activeColor : defaultColor,
94
+ opacity: isActive ? 0.8 : 0.6,
95
+ transition: `all var(--duration-fast) var(--easing)`,
96
+ display: "-webkit-box",
97
+ WebkitLineClamp: 2,
98
+ WebkitBoxOrient: "vertical",
99
+ overflow: "hidden",
100
+ textOverflow: "ellipsis"
101
+ },
102
+ "data-text-element": true,
103
+ children: description
104
+ }
105
+ )
106
+ ] })
107
+ }
108
+ );
109
+ };
7
110
  var SubshellSidebarSection = ({
8
111
  icon: Icon,
9
112
  label,
@@ -19,14 +122,30 @@ var SubshellSidebarSection = ({
19
122
  borderBottom: "1px solid var(--color-border)"
20
123
  },
21
124
  children: /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
22
- /* @__PURE__ */ jsx(Icon, { size: 16, color: "var(--color-text-subtle)" }),
23
125
  /* @__PURE__ */ jsx(
24
- Text,
126
+ ThemeIcon,
127
+ {
128
+ variant: "light",
129
+ size: sidebarIconSize,
130
+ style: {
131
+ backgroundColor: "var(--color-surface)",
132
+ color: "var(--color-primary)",
133
+ flexShrink: 0
134
+ },
135
+ children: /* @__PURE__ */ jsx(Icon, { size: sidebarIconInnerSize, stroke: sidebarIconStroke })
136
+ }
137
+ ),
138
+ /* @__PURE__ */ jsx(
139
+ Box,
25
140
  {
26
- size: "sm",
27
- fw: 600,
28
- c: "var(--color-text-subtle)",
29
- style: { fontFamily: "var(--mantine-font-family-headings)", flex: 1 },
141
+ c: "var(--color-text)",
142
+ style: {
143
+ fontFamily: "var(--elevasis-font-family-subtitle)",
144
+ flex: 1,
145
+ fontSize: "var(--mantine-font-size-md)",
146
+ fontWeight: 500,
147
+ lineHeight: 1.2
148
+ },
30
149
  children: label
31
150
  }
32
151
  ),
@@ -45,10 +164,10 @@ var PageContainer = ({ children }) => {
45
164
  /* @__PURE__ */ jsx(Container, { size: "xl", p: 0, w: "100%", children: /* @__PURE__ */ jsx(Stack, { gap: "lg", children }) })
46
165
  );
47
166
  };
48
- var activeColor = "var(--color-primary)";
167
+ var activeColor2 = "var(--color-primary)";
49
168
  var defaultTextColor = "var(--color-text)";
50
169
  var subtleColor = "var(--color-text-subtle)";
51
- var activeBg = `color-mix(in srgb, ${activeColor} 10%, transparent)`;
170
+ var activeBg2 = `color-mix(in srgb, ${activeColor2} 10%, transparent)`;
52
171
  var CollapsibleSidebarGroup = ({
53
172
  icon: Icon,
54
173
  label,
@@ -64,8 +183,8 @@ var CollapsibleSidebarGroup = ({
64
183
  loadingComponent
65
184
  }) => {
66
185
  const showActiveStyle = !isExpanded && isActive;
67
- const iconColor = showActiveStyle ? activeColor : subtleColor;
68
- const textColor = showActiveStyle ? activeColor : defaultTextColor;
186
+ const iconColor = showActiveStyle ? activeColor2 : subtleColor;
187
+ const textColor = showActiveStyle ? activeColor2 : defaultTextColor;
69
188
  const fontWeight = showActiveStyle ? 600 : 500;
70
189
  const handleLabelClick = (e) => {
71
190
  if (onLabelClick) {
@@ -84,7 +203,7 @@ var CollapsibleSidebarGroup = ({
84
203
  width: "100%",
85
204
  padding: "var(--mantine-spacing-xs)",
86
205
  color: textColor,
87
- backgroundColor: showActiveStyle ? activeBg : "transparent",
206
+ backgroundColor: showActiveStyle ? activeBg2 : "transparent",
88
207
  transition: `all var(--duration-fast) var(--easing)`,
89
208
  cursor: "pointer",
90
209
  overflow: "hidden"
@@ -106,7 +225,7 @@ var CollapsibleSidebarGroup = ({
106
225
  {
107
226
  style: { flexShrink: 0, color: iconColor, cursor: onLabelClick ? "pointer" : "inherit" },
108
227
  onClick: onLabelClick ? handleLabelClick : void 0,
109
- children: /* @__PURE__ */ jsx(Icon, { size: sidebarIconInnerSize, color: activeColor })
228
+ children: /* @__PURE__ */ jsx(Icon, { size: sidebarIconInnerSize, color: activeColor2 })
110
229
  }
111
230
  ),
112
231
  /* @__PURE__ */ jsx(
@@ -148,108 +267,5 @@ var CollapsibleSidebarGroup = ({
148
267
  ) })
149
268
  ] });
150
269
  };
151
- var activeColor2 = "var(--color-primary)";
152
- var defaultColor = "var(--color-text-subtle)";
153
- var hoverColor = "var(--color-text)";
154
- var activeBg2 = `color-mix(in srgb, ${activeColor2} 10%, transparent)`;
155
- var SidebarListItem = ({
156
- icon: Icon,
157
- label,
158
- isActive = false,
159
- onClick,
160
- description,
161
- badge,
162
- disabled = false
163
- }) => {
164
- return /* @__PURE__ */ jsx(
165
- UnstyledButton,
166
- {
167
- onClick: disabled ? void 0 : onClick,
168
- disabled,
169
- style: {
170
- width: "100%",
171
- padding: "var(--mantine-spacing-xs)",
172
- backgroundColor: isActive ? activeBg2 : "transparent",
173
- borderRadius: "var(--mantine-radius-default)",
174
- transition: `all var(--duration-fast) var(--easing)`,
175
- cursor: disabled ? "not-allowed" : "pointer",
176
- opacity: disabled ? 0.5 : 1
177
- },
178
- onMouseEnter: (e) => {
179
- if (!isActive && !disabled) {
180
- e.currentTarget.style.backgroundColor = "var(--color-surface-hover)";
181
- const textElements = e.currentTarget.querySelectorAll("[data-text-element]");
182
- textElements.forEach((el) => {
183
- el.style.color = hoverColor;
184
- });
185
- }
186
- },
187
- onMouseLeave: (e) => {
188
- if (!isActive && !disabled) {
189
- e.currentTarget.style.backgroundColor = "transparent";
190
- const textElements = e.currentTarget.querySelectorAll("[data-text-element]");
191
- textElements.forEach((el) => {
192
- el.style.color = defaultColor;
193
- });
194
- }
195
- },
196
- children: /* @__PURE__ */ jsxs(Stack, { gap: 2, children: [
197
- /* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "nowrap", children: [
198
- /* @__PURE__ */ jsx(
199
- Icon,
200
- {
201
- size: sidebarListItemIconSize,
202
- style: {
203
- flexShrink: 0,
204
- opacity: isActive ? 1 : 0.6,
205
- color: isActive ? activeColor2 : defaultColor
206
- }
207
- }
208
- ),
209
- /* @__PURE__ */ jsx(
210
- Text,
211
- {
212
- size: "sm",
213
- fw: isActive ? 600 : 400,
214
- style: {
215
- overflow: "hidden",
216
- textOverflow: "ellipsis",
217
- whiteSpace: "nowrap",
218
- flex: 1,
219
- fontFamily: "var(--elevasis-font-family-subtitle)",
220
- color: isActive ? activeColor2 : defaultColor,
221
- transition: `color var(--duration-fast) var(--easing)`
222
- },
223
- "data-text-element": true,
224
- children: label
225
- }
226
- ),
227
- badge && /* @__PURE__ */ jsx("div", { style: { flexShrink: 0 }, children: badge })
228
- ] }),
229
- description && /* @__PURE__ */ jsx(
230
- Text,
231
- {
232
- size: "xs",
233
- c: "dimmed",
234
- style: {
235
- paddingLeft: "22px",
236
- lineHeight: 1.2,
237
- color: isActive ? activeColor2 : defaultColor,
238
- opacity: isActive ? 0.8 : 0.6,
239
- transition: `all var(--duration-fast) var(--easing)`,
240
- display: "-webkit-box",
241
- WebkitLineClamp: 2,
242
- WebkitBoxOrient: "vertical",
243
- overflow: "hidden",
244
- textOverflow: "ellipsis"
245
- },
246
- "data-text-element": true,
247
- children: description
248
- }
249
- )
250
- ] })
251
- }
252
- );
253
- };
254
270
 
255
- export { CollapsibleSidebarGroup, PageContainer, SidebarListItem, SubshellLoader, SubshellSidebarSection };
271
+ export { CollapsibleSidebarGroup, PageContainer, SubshellLoader, SubshellNavItem, SubshellSidebarSection };
@@ -1,7 +1,7 @@
1
- import { useCyberColors, CyberLegendItem, CyberAreaChart } from './chunk-JHVKGZ2P.js';
2
- import { CardHeader, EmptyState } from './chunk-MCA6LOGM.js';
3
- import { useResourcesHealth } from './chunk-EINVPEHK.js';
1
+ import { useCyberColors, CyberLegendItem, CyberAreaChart } from './chunk-KFICYU6S.js';
2
+ import { useResourcesHealth } from './chunk-TZOGB3X4.js';
4
3
  import { getTimeRangeDates, formatBucketTime } from './chunk-LXHZYSMQ.js';
4
+ import { CardHeader, EmptyState } from './chunk-Y3D3WFJG.js';
5
5
  import { Paper, Center, Loader, Group } from '@mantine/core';
6
6
  import { IconActivity, IconChartBar } from '@tabler/icons-react';
7
7
  import { useMemo } from 'react';
@@ -1,6 +1,6 @@
1
- import { CredentialNameSchema, UuidSchema, useErrorNotification, showApiErrorNotification } from './chunk-EINVPEHK.js';
1
+ import { CredentialNameSchema, UuidSchema, useErrorNotification, showApiErrorNotification } from './chunk-TZOGB3X4.js';
2
2
  import { getTimeRangeDates } from './chunk-LXHZYSMQ.js';
3
- import { useNotificationAdapter } from './chunk-45MS3IAW.js';
3
+ import { useNotificationAdapter } from './chunk-MZPVNRPL.js';
4
4
  import { GC_TIME_SHORT, STALE_TIME_MONITORING, GC_TIME_MEDIUM, STALE_TIME_DEFAULT } from './chunk-IOKL7BKE.js';
5
5
  import { useElevasisServices } from './chunk-QEPXAWE2.js';
6
6
  import { z } from 'zod';
@@ -1,12 +1,12 @@
1
1
  import { FilterBar } from './chunk-PDHTXPSF.js';
2
2
  import { CustomModal } from './chunk-GBMNCNHX.js';
3
- import { CyberAreaChart, CostTrendChart, ActivityTrendChart } from './chunk-JHVKGZ2P.js';
4
- import { CenteredErrorState, CardHeader, StatsCardSkeleton, TrendIndicator, DetailCardSkeleton, EmptyState, PageTitleCaption, JsonViewer } from './chunk-MCA6LOGM.js';
5
- import { AppShellLoader } from './chunk-YYBM5LNJ.js';
6
- import { useExecutionLogsFilters, useTimeRangeDates, useActivityFilters } from './chunk-BYZ7VTSH.js';
7
- import { useResolveError, useResolveAllErrors, usePaginationState, useErrorDetails, useMarkAsRead, useExecutionLogs, useExecutionHealth, useErrorAnalysis, useErrorDetail, useResolveErrorsByExecution, useResources, useCostTrends, useCostSummary, useCostByModel, useCostBreakdown, useActivityTrend, useActivities, useNotifications, useMarkAllAsRead, useTestNotification } from './chunk-EINVPEHK.js';
3
+ import { CyberAreaChart, CostTrendChart, ActivityTrendChart } from './chunk-KFICYU6S.js';
4
+ import { AppShellLoader } from './chunk-YEX4MQSY.js';
5
+ import { useExecutionLogsFilters, useTimeRangeDates, useActivityFilters } from './chunk-PRLXFMNP.js';
6
+ import { useResolveError, useResolveAllErrors, usePaginationState, useErrorDetails, useMarkAsRead, useExecutionLogs, useExecutionHealth, useErrorAnalysis, useErrorDetail, useResolveErrorsByExecution, useResources, useCostTrends, useCostSummary, useCostByModel, useCostBreakdown, useActivityTrend, useActivities, useNotifications, useMarkAllAsRead, useTestNotification } from './chunk-TZOGB3X4.js';
8
7
  import { formatBucketTime, getTimeRangeDates } from './chunk-LXHZYSMQ.js';
9
8
  import { formatDuration } from './chunk-XA34RETF.js';
9
+ import { CenteredErrorState, CardHeader, StatsCardSkeleton, TrendIndicator, DetailCardSkeleton, EmptyState, PageTitleCaption, JsonViewer } from './chunk-Y3D3WFJG.js';
10
10
  import { PAGE_SIZE_DEFAULT } from './chunk-IOKL7BKE.js';
11
11
  import { useRouterContext } from './chunk-Q7DJKLEN.js';
12
12
  import { useState, useMemo, useCallback } from 'react';
@@ -1360,8 +1360,22 @@ function ErrorDetailsModal({ executionId, opened, onClose, organizationName }) {
1360
1360
  }
1361
1361
  return map;
1362
1362
  }, [resources]);
1363
+ const resourceTypeMap = useMemo(() => {
1364
+ const map = /* @__PURE__ */ new Map();
1365
+ if (resources) {
1366
+ for (const r of resources.workflows) {
1367
+ map.set(r.resourceId, "workflow");
1368
+ }
1369
+ for (const r of resources.agents) {
1370
+ map.set(r.resourceId, "agent");
1371
+ }
1372
+ }
1373
+ return map;
1374
+ }, [resources]);
1363
1375
  const primaryError = errors?.[0];
1364
1376
  const resolvedResourceName = primaryError ? resourceNameMap.get(primaryError.resourceId) ?? primaryError.resourceId : void 0;
1377
+ const resolvedResourceType = primaryError ? resourceTypeMap.get(primaryError.resourceId) : void 0;
1378
+ const resourceDetailHref = primaryError && resolvedResourceType ? `/operations/resources/${resolvedResourceType}/${primaryError.resourceId}` : null;
1365
1379
  const allResolved = errors?.every((e) => e.resolved) ?? false;
1366
1380
  const hasRetries = errors && errors.length > 1;
1367
1381
  const handleCopyDetails = () => {
@@ -1432,13 +1446,13 @@ ${primaryError.errorContext ? JSON.stringify(primaryError.errorContext, null, 2)
1432
1446
  /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
1433
1447
  /* @__PURE__ */ jsx(Code, { children: primaryError.executionId }),
1434
1448
  /* @__PURE__ */ jsx(CopyButton, { value: `"${organizationName}/${primaryError.resourceId}" ${primaryError.executionId}`, children: ({ copied, copy }) => /* @__PURE__ */ jsx(Tooltip, { label: copied ? "Copied" : "Copy Execution Ref", children: /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", color: copied ? "teal" : "gray", onClick: copy, children: copied ? /* @__PURE__ */ jsx(IconCheck, { size: 14 }) : /* @__PURE__ */ jsx(IconCopy, { size: 14 }) }) }) }),
1435
- /* @__PURE__ */ jsx(
1449
+ resourceDetailHref && /* @__PURE__ */ jsx(
1436
1450
  ActionIcon,
1437
1451
  {
1438
1452
  variant: "subtle",
1439
1453
  size: "sm",
1440
1454
  component: "a",
1441
- href: `/operations/resources/workflow/${primaryError.resourceId}`,
1455
+ href: resourceDetailHref,
1442
1456
  target: "_blank",
1443
1457
  title: "View Execution Log",
1444
1458
  children: /* @__PURE__ */ jsx(IconExternalLink, { size: 14 })
@@ -1545,16 +1559,7 @@ ${primaryError.errorContext ? JSON.stringify(primaryError.errorContext, null, 2)
1545
1559
  ] }),
1546
1560
  /* @__PURE__ */ jsxs(Group, { children: [
1547
1561
  /* @__PURE__ */ jsx(Button, { variant: "default", onClick: onClose, children: "Close" }),
1548
- /* @__PURE__ */ jsx(
1549
- Button,
1550
- {
1551
- component: "a",
1552
- href: `/operations/resources/workflow/${primaryError.resourceId}`,
1553
- target: "_blank",
1554
- leftSection: /* @__PURE__ */ jsx(IconExternalLink, { size: 16 }),
1555
- children: "View Execution Log"
1556
- }
1557
- )
1562
+ resourceDetailHref && /* @__PURE__ */ jsx(Button, { component: "a", href: resourceDetailHref, target: "_blank", leftSection: /* @__PURE__ */ jsx(IconExternalLink, { size: 16 }), children: "View Execution Log" })
1558
1563
  ] })
1559
1564
  ] })
1560
1565
  ] })
@@ -1594,7 +1599,7 @@ function getNavigationPath2(activity) {
1594
1599
  case "agent_run":
1595
1600
  return `/operations/resources/agent/${activity.entityId}`;
1596
1601
  case "hitl_action":
1597
- return "/command-queue";
1602
+ return "/operations/command-queue";
1598
1603
  case "credential_change":
1599
1604
  return "/settings/credentials";
1600
1605
  case "api_key_change":
@@ -1,4 +1,4 @@
1
- import { topbarHeight, sidebarTransitionDuration, sidebarBottomSectionHeight } from './chunk-QJ2S46NI.js';
1
+ import { topbarHeight, sidebarTransitionDuration, sidebarBottomSectionHeight } from './chunk-DT3QYZVU.js';
2
2
  import { jsx, jsxs } from 'react/jsx-runtime';
3
3
  import { useState } from 'react';
4
4
 
@@ -1,6 +1,6 @@
1
- import { NavigationButton } from './chunk-NNKKBSJN.js';
1
+ import { NavigationButton } from './chunk-NYBEU5TE.js';
2
2
  import { useAppearance } from './chunk-QJ2KCHKX.js';
3
- import { sidebarItemGap, sidebarSubLinkPaddingY, sidebarSubLinkPaddingX, sidebarSubLinkIndent, sidebarHoverDelay, sidebarTransitionDuration, sidebarCollapsedWidth, sidebarWidth, topbarHeight, sidebarToggleIconSize, sidebarSectionPadding } from './chunk-QJ2S46NI.js';
3
+ import { sidebarItemGap, sidebarSubLinkPaddingY, sidebarSubLinkPaddingX, sidebarSubLinkIndent, sidebarHoverDelay, sidebarTransitionDuration, sidebarCollapsedWidth, sidebarWidth, topbarHeight, sidebarToggleIconSize, sidebarSectionPadding } from './chunk-DT3QYZVU.js';
4
4
  import { useRouterContext } from './chunk-Q7DJKLEN.js';
5
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
6
  import { createContext, memo, useEffect, createElement, useContext, useRef, useLayoutEffect, useState } from 'react';