datastake-daf 0.6.757 → 0.6.759

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 (43) hide show
  1. package/dist/components/index.js +3299 -2881
  2. package/dist/layouts/index.js +476 -452
  3. package/dist/pages/index.js +836 -662
  4. package/dist/style/datastake/mapbox-gl.css +330 -0
  5. package/dist/utils/index.js +481 -802
  6. package/package.json +1 -1
  7. package/rollup.config.js +0 -20
  8. package/src/@daf/core/components/Dashboard/Map/Map.stories.js +8 -0
  9. package/src/@daf/core/components/Dashboard/Map/helper.js +134 -3
  10. package/src/@daf/core/components/Dashboard/Map/hook.js +4 -0
  11. package/src/@daf/core/components/Dashboard/Map/index.jsx +19 -0
  12. package/src/@daf/core/components/Dashboard/Map/storyConfig.js +2 -1
  13. package/src/@daf/core/components/Dashboard/Map/storyConfig6.js +69 -0
  14. package/src/@daf/core/components/Dashboard/Widget/ActivityIndicators/config.js +2 -5
  15. package/src/@daf/core/components/Dashboard/Widget/KeyIndicators/index.jsx +1 -1
  16. package/src/@daf/core/components/EditForm/form.jsx +1 -1
  17. package/src/@daf/core/components/EditForm/storyConfig2.js +25028 -865
  18. package/src/@daf/core/components/Graphs/components/BaseGraph.jsx +1 -1
  19. package/src/@daf/core/components/Icon/configs/SpacingHeight.js +8 -0
  20. package/src/@daf/core/components/Icon/configs/SpacingWidth.js +8 -0
  21. package/src/@daf/core/components/Icon/configs/index.js +5 -1
  22. package/src/@daf/hooks/useMapHelper.js +15 -1
  23. package/src/@daf/pages/Dashboards/SupplyChain/index.jsx +2 -2
  24. package/src/@daf/pages/Documents/index.jsx +3 -2
  25. package/src/@daf/pages/Events/Activities/index.jsx +3 -2
  26. package/src/@daf/pages/Events/Incidents/index.jsx +3 -2
  27. package/src/@daf/pages/Events/index.jsx +3 -2
  28. package/src/@daf/pages/Locations/MineSite/columns.js +5 -7
  29. package/src/@daf/pages/Locations/MineSite/index.jsx +4 -5
  30. package/src/@daf/pages/Locations/index.jsx +3 -2
  31. package/src/@daf/pages/Stakeholders/Operators/index.jsx +2 -2
  32. package/src/@daf/pages/Stakeholders/Workers/index.jsx +3 -2
  33. package/src/@daf/pages/Stakeholders/index.jsx +3 -2
  34. package/src/@daf/pages/Summary/Activities/Restoration/helper.js +133 -79
  35. package/src/@daf/pages/Summary/Activities/Restoration/index.jsx +57 -60
  36. package/src/@daf/pages/Summary/Minesite/index.jsx +0 -2
  37. package/src/@daf/pages/Summary/Operator/index.jsx +1 -3
  38. package/src/@daf/utils/tooltip.js +5 -2
  39. package/src/utils.js +1 -3
  40. package/dist/constants/index.js +0 -26
  41. package/src/constants/breadCrumbs.js +0 -20
  42. package/src/constants.js +0 -1
  43. package/src/helpers/breadCrumbs.js +0 -347
@@ -1,9 +1,11 @@
1
1
  import { useMemo, useCallback } from 'react';
2
2
  import { DashboardLayout, Header, ImageCarousel, KeyIndicators, MineSiteMap, Widget, PieChart, ActivityIndicators } from '../../../../../../src/index.js'
3
3
  import { getKeyIndicatorsRowConfig } from './config';
4
- import { getActivityImages, getGenderDistributionData, isGenderDistributionEmpty, calculateGenderPieData, getGenderTooltipChildren, getActivityIndicatorsConfig } from './helper';
4
+ import { getActivityImages, getGenderDistributionData, isGenderDistributionEmpty, calculateGenderPieData, getGenderTooltipChildren, getActivityIndicatorsConfig, getMapDataFromActivity } from './helper';
5
5
  import { renderTooltipJsx } from '../../../../../../src/utils';
6
+ import { convertDMS } from '../../../../../../src/helpers/Map';
6
7
  import { useResizeContext } from '../../../../../../src/context';
8
+ import CustomIcon from '../../../../../../src/@daf/core/components/Icon/CustomIcon.jsx';
7
9
 
8
10
  const RestorationActivitySummary = ({ activityData, supportText, onDownload, downloadDisabled, actionButtons, breadcrumbs, goBackTo, loading, t = () => { } }) => {
9
11
  const { isCollapsed, isNestedSidebarCollapsed } = useResizeContext();
@@ -24,6 +26,9 @@ const RestorationActivitySummary = ({ activityData, supportText, onDownload, dow
24
26
  [activityData, t]
25
27
  );
26
28
 
29
+ // Map Data - transformed from activityData
30
+ const mapData = useMemo(() => getMapDataFromActivity(activityData, t), [activityData, t]);
31
+
27
32
  return (
28
33
  <DashboardLayout
29
34
  header={
@@ -46,7 +51,7 @@ const RestorationActivitySummary = ({ activityData, supportText, onDownload, dow
46
51
  <section>
47
52
  <Widget
48
53
  title={t("Activity Location")}
49
- className="no-px no-pt-body no-p-body no-pb-body"
54
+ className="no-px h-w-btn-header no-pt-body no-p-body no-pb-body"
50
55
  style={{ height: '100%', display: 'flex', flexDirection: 'column' }}
51
56
  >
52
57
  <div style={{ flex: 1, minHeight: 0 }}>
@@ -55,73 +60,65 @@ const RestorationActivitySummary = ({ activityData, supportText, onDownload, dow
55
60
  t={t}
56
61
  isSatellite={true}
57
62
  app={"straatos"}
63
+ type={'location-territory'}
58
64
  showSider={false}
59
65
  user={null}
60
- data={[
61
- {
62
- _id: {},
63
- id: "7f2aaed4-4b2e-406c-8e0a-6659c5c8367b",
64
- color: "#6698E4",
65
- parent: {
66
- _id: {},
67
- createdAt: "2024-06-13T14:51:55.296Z",
68
- updatedAt: "2024-06-13T14:51:55.296Z",
69
- id: "a5340bf1-2c7d-413f-a2a5-ccd7dc8f7a7c",
70
- name: "New Mine",
71
- authorId: "4e6066e9-00d8-423a-94ec-c7c9d3432fec",
72
- collectId: "f8a2b6a9cc935ef3e5844427f49aade34e152eca",
73
- country: "AL",
74
- category: "mineSite",
75
- datastakeId: "LOC-00000000141",
76
- __v: 0,
77
- },
78
- administrativeLevel1: "6839cb26-5af4-44a3-b136-a0f0a0bcecc6",
79
- administrativeLevel2: "f849835d-5640-4bee-ae98-9f1c810c1abe",
80
- // "name": "New Mine",
81
- country: "AL",
82
- category: "mineSite",
83
- authorId: "4e6066e9-00d8-423a-94ec-c7c9d3432fec",
84
- gps: {
85
- latitude: 7,
86
- longitude: 1,
87
- },
88
- area: [
89
- [6, 5],
90
- [7, 1],
91
- [9, 2],
92
- ],
93
- associatedSubjects: [
94
- {
95
- entity: "Event",
96
- _id: {},
97
- nature: "",
98
- },
99
- ],
100
- published: false,
101
- version: 1,
102
- createdAt: "2024-06-13T14:51:55.296Z",
103
- updatedAt: "2024-06-13T14:51:55.296Z",
104
- name: "Name",
105
- type: "Loc Type",
106
- __v: 0,
107
- datastakeId: "LOC-00000000141",
108
- },
109
- ]}
110
- // tooltipAsText: true,
66
+ data={mapData}
67
+ maxZoom={18}
111
68
  primaryLink={true}
112
- renderTooltip={() => {
69
+ style={{ height: '100%', width: '100%' }}
70
+ renderTooltipForLocation={(data) => {
71
+ const coordinates = data.gps?.latitude && data.gps?.longitude
72
+ ? convertDMS(data.gps.latitude, data.gps.longitude)
73
+ : null;
74
+
75
+ if (!coordinates) {
76
+ return [];
77
+ }
78
+
79
+ const isActivityEnd = data.name === t("Activity End") || data.id?.includes('-departure');
80
+ const iconColor = isActivityEnd ? "#FF7A45" : "#016C6E";
81
+
82
+ return [
83
+ {
84
+ label: t("Coordinates"),
85
+
86
+ value: (
87
+ <div style={{ display: 'flex', alignItems: 'center', gap: '6px', flexWrap: 'nowrap' }}>
88
+ {/* Latitude icon (vertical) */}
89
+ <div style={{ display: 'flex', alignItems: 'center' }}>
90
+ <CustomIcon
91
+ name="SpacingHeight"
92
+ width={14}
93
+ height={14}
94
+ color={iconColor}
95
+ />
96
+ <span style={{ fontWeight: 600, marginLeft: '4px' }}>{coordinates[0]}</span>
97
+ </div>
98
+ {/* Longitude icon (horizontal) */}
99
+ <div style={{ display: 'flex', alignItems: 'center' }}>
100
+ <CustomIcon
101
+ name="SpacingWidth"
102
+ width={14}
103
+ height={14}
104
+ color={iconColor}
105
+ />
106
+ <span style={{ fontWeight: 600, marginLeft: '4px' }}>{coordinates[1]}</span>
107
+ </div>
108
+ </div>
109
+ ),
110
+ },
111
+ ];
112
+ }}
113
+ renderTooltipForTerritory={(data) => {
113
114
  return [
114
115
  {
115
- label: "Name",
116
- value: "Name",
116
+ label: t("Plot Name"),
117
+ value: data.plotName || data.name || "--",
117
118
  },
118
119
  ];
119
120
  }}
120
- center={[13, -15]}
121
- mapConfig={{ maxZoom: 18 }}
122
- type={'territory'}
123
121
  link={true}
124
- onClickLink={() => { }}
125
122
  />
126
123
  </div>
127
124
  </Widget>
@@ -29,7 +29,6 @@ const MineSummary = ({
29
29
  getRedirectLink = () => {},
30
30
  goBack = () => {},
31
31
  onIdChange = () => {},
32
- breadcrumbs = [],
33
32
  }) => {
34
33
  const {
35
34
  selectedItem,
@@ -71,7 +70,6 @@ const MineSummary = ({
71
70
  className="with-border-header h-w-btn-header no-px-body"
72
71
  goBackTo={!hasSelect && goBack}
73
72
  loading={loading}
74
- breadcrumbs={breadcrumbs}
75
73
  addedHeaderFirst
76
74
  actionButtons={[
77
75
  {
@@ -29,8 +29,7 @@ const OperatorSummary = ({
29
29
  goTo = () => {},
30
30
  getRedirectLink = () => {},
31
31
  goBack = () => {},
32
- onIdChange = () => {},
33
- breadcrumbs = [],
32
+ onIdChange = () => {}
34
33
  }) => {
35
34
  const {
36
35
  selectedItem,
@@ -71,7 +70,6 @@ const OperatorSummary = ({
71
70
  title={hasSelect ? t("Operator Review") : (singleItemData?.name || "") + " " + t("Summary")}
72
71
  className="with-border-header h-w-btn-header no-px-body"
73
72
  goBackTo={!hasSelect && goBack}
74
- breadcrumbs={breadcrumbs}
75
73
  addedHeaderFirst
76
74
  actionButtons={[
77
75
  {
@@ -158,20 +158,23 @@ export const renderTooltipJsx = ({
158
158
  <span className="daf-tooltip-name">{item.label}</span>
159
159
  </Tooltip>
160
160
 
161
- <Tooltip title={item.tooltipValue || item.value}>
161
+ <Tooltip title={item.tooltipValue || (typeof item.value === 'string' ? item.value : '')}>
162
162
  <div
163
163
  style={{
164
164
  height: "20px",
165
165
  display: "flex",
166
166
  alignItems: "center",
167
+ gap: "4px",
167
168
  }}
168
169
  >
169
170
  {item.tag ? (
170
171
  <Tag color={item.tag} className="mr-none">
171
172
  {item.value}
172
173
  </Tag>
173
- ) : (
174
+ ) : typeof item.value === 'string' || typeof item.value === 'number' ? (
174
175
  <span className="daf-tooltip-value">{item.value}</span>
176
+ ) : (
177
+ item.value
175
178
  )}
176
179
  </div>
177
180
  </Tooltip>
package/src/utils.js CHANGED
@@ -58,6 +58,4 @@ export {
58
58
  buildActionWidgetsConfig,
59
59
  buildKeyIndicatorsConfig,
60
60
  buildBreadcrumbs
61
- } from './@daf/utils/adminConfigBuilders.js'
62
-
63
- export { renderBreadCrumbs, buildBreadCrumbs as buildBreadCrumbsHelper } from './helpers/breadCrumbs.js'
61
+ } from './@daf/utils/adminConfigBuilders.js'
@@ -1,26 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- const defaultBreadCrumbsLabels = {
6
- events: "Events",
7
- accounts: "Accounts",
8
- modules: "Modules",
9
- settings: "Settings",
10
- user: "Users",
11
- analysis: "Analysis",
12
- 'data-store': "Data Store",
13
- data: "Data",
14
- partners: "Partners",
15
- locations: "Locations",
16
- 'information-channels': 'Channels',
17
- 'find-information': 'Query',
18
- stakeholders: "Stakeholders",
19
- documents: "Documents",
20
- mines: "Mines",
21
- summary: "Summary",
22
- edit: "Edit",
23
- details: "Details"
24
- };
25
-
26
- exports.defaultBreadCrumbsLabels = defaultBreadCrumbsLabels;
@@ -1,20 +0,0 @@
1
- export const defaultBreadCrumbsLabels = {
2
- events: "Events",
3
- accounts: "Accounts",
4
- modules: "Modules",
5
- settings: "Settings",
6
- user: "Users",
7
- analysis: "Analysis",
8
- 'data-store': "Data Store",
9
- data: "Data",
10
- partners: "Partners",
11
- locations: "Locations",
12
- 'information-channels': 'Channels',
13
- 'find-information': 'Query',
14
- stakeholders: "Stakeholders",
15
- documents: "Documents",
16
- mines: "Mines",
17
- summary: "Summary",
18
- edit: "Edit",
19
- details: "Details",
20
- }
package/src/constants.js DELETED
@@ -1 +0,0 @@
1
- export { defaultBreadCrumbsLabels } from './constants/breadCrumbs.js';
@@ -1,347 +0,0 @@
1
-
2
- export const buildBreadCrumbs = ({
3
- config,
4
- items,
5
- t,
6
- breadCrumbsLabels,
7
- id,
8
- getRedirectLink,
9
- createOnClick,
10
- goTo,
11
- view,
12
- skipInteractions = false,
13
- }) => {
14
- const pathConfig = config.path || [];
15
-
16
- pathConfig.forEach((pathItem) => {
17
- if (typeof pathItem === 'string') {
18
- items.push({
19
- label: t(breadCrumbsLabels[pathItem]),
20
- onClick: () => {},
21
- });
22
- } else if (typeof pathItem === 'object') {
23
- const { key, link, useRedirect } = pathItem;
24
-
25
- if (key === 'id' && id) {
26
- const resolvedLink = typeof link === 'function' ? link(id) : link;
27
- const finalLink = useRedirect ? getRedirectLink(resolvedLink) : resolvedLink;
28
-
29
- items.push({
30
- label: id,
31
- onClick: skipInteractions ? () => {} : (finalLink ? createOnClick(() => goTo(finalLink)) : () => {}),
32
- });
33
- } else {
34
- const resolvedLink = typeof link === 'function' ? link(view, id) : link;
35
- const finalLink = resolvedLink && useRedirect ? getRedirectLink(resolvedLink) : resolvedLink;
36
-
37
- items.push({
38
- label: t(breadCrumbsLabels[key]),
39
- onClick: skipInteractions ? () => {} : (finalLink ? createOnClick(() => goTo(finalLink)) : () => {}),
40
- });
41
- }
42
- }
43
- });
44
-
45
- if (config.includeId && id && id !== 'user') {
46
- items.push({ label: id, onClick: () => {} });
47
- }
48
-
49
- if (config.suffix) {
50
- config.suffix.forEach((suffixItem) => {
51
- items.push({
52
- label: t(breadCrumbsLabels[suffixItem]),
53
- onClick: () => {},
54
- });
55
- });
56
- }
57
- }
58
-
59
- export const renderBreadCrumbs = ({
60
- t = () => {},
61
- goTo = () => {},
62
- view,
63
- isAnalysis = false,
64
- isEdit = false,
65
- isView = false,
66
- isDataStore = false,
67
- id,
68
- addedItems = [],
69
- changeNotificationState,
70
- breadCrumbConfig = {},
71
- breadCrumbsLabels = {},
72
- getRedirectLink = () => {},
73
- condition,
74
- conditionFallback = 'show-non-interactive', // 'show-non-interactive' | 'hide' | 'show-simplified'
75
- }) => {
76
- const items = [];
77
-
78
- const createOnClick = (callback) => {
79
- if (!callback) return () => {};
80
-
81
- return () => {
82
- if (changeNotificationState) {
83
- changeNotificationState({ onYes: callback });
84
- } else {
85
- callback();
86
- }
87
- };
88
- };
89
-
90
- const evaluateCondition = (cond, context) => {
91
- if (cond === undefined) return true; // No condition = always pass
92
- if (typeof cond === 'function') return cond(context); // Function condition
93
- return Boolean(cond); // Boolean condition
94
- };
95
-
96
- const config = breadCrumbConfig[view];
97
-
98
- console.log({config, breadCrumbConfig, breadCrumbsLabels, condition})
99
-
100
- if (config) {
101
- const conditionContext = {
102
- isDataStore,
103
- isAnalysis,
104
- isEdit,
105
- isView,
106
- id,
107
- view,
108
- t,
109
- goTo,
110
- getRedirectLink,
111
- changeNotificationState,
112
- addedItems,
113
- };
114
-
115
- const externalConditionPassed = evaluateCondition(condition, conditionContext);
116
- const configConditionPassed = evaluateCondition(config.condition, conditionContext);
117
-
118
- const shouldShowBreadcrumbs = externalConditionPassed && configConditionPassed;
119
-
120
- if (!configConditionPassed) {
121
- if (config.fallback) {
122
- buildBreadCrumbs({
123
- config: config.fallback,
124
- items,
125
- t,
126
- breadCrumbsLabels,
127
- id,
128
- getRedirectLink,
129
- createOnClick,
130
- goTo,
131
- view,
132
- });
133
- }
134
- } else if (!externalConditionPassed) {
135
- if (config.fallback) {
136
- // Use config fallback when prop condition fails
137
- buildBreadCrumbs({
138
- config: config.fallback,
139
- items,
140
- t,
141
- breadCrumbsLabels,
142
- id,
143
- getRedirectLink,
144
- createOnClick,
145
- goTo,
146
- view,
147
- });
148
- }
149
- else {
150
- switch (conditionFallback) {
151
- case 'hide':
152
- break;
153
- case 'show-simplified':{
154
- const simplifiedConfig = {
155
- ...config,
156
- path: config.path.slice(0, 2),
157
- includeId: false,
158
- suffix: undefined,
159
- };
160
-
161
- buildBreadCrumbs({
162
- config: simplifiedConfig,
163
- items,
164
- t,
165
- breadCrumbsLabels,
166
- id,
167
- getRedirectLink,
168
- createOnClick,
169
- goTo,
170
- view,
171
- });
172
- break;
173
- }
174
- case 'show-non-interactive':
175
- default:
176
- buildBreadCrumbs({
177
- config,
178
- items,
179
- t,
180
- breadCrumbsLabels,
181
- id,
182
- getRedirectLink,
183
- createOnClick,
184
- goTo,
185
- view,
186
- skipInteractions: true,
187
- });
188
- break;
189
- }
190
- }
191
- } else {
192
- buildBreadCrumbs({
193
- config,
194
- items,
195
- t,
196
- breadCrumbsLabels,
197
- id,
198
- getRedirectLink,
199
- createOnClick,
200
- goTo,
201
- view,
202
- });
203
- }
204
- }
205
-
206
-
207
- if (isView) {
208
- items.push({ label: t(breadCrumbsLabels.details) });
209
- } else if (isEdit) {
210
- items.push({ label: t(breadCrumbsLabels.edit) });
211
- } else if (isAnalysis) {
212
- items.push({ label: t(breadCrumbsLabels.summary) });
213
- }
214
-
215
- items.push(...addedItems);
216
-
217
- return items.filter((v) => !!v.label);
218
-
219
- }
220
-
221
- // Breadcrumbs Config Helper
222
-
223
- // 1.Simple static path
224
- // 'country-overview': {
225
- // path: ['analysis', 'country-overview'],
226
- // }
227
- // Result: Analysis > Country Overview
228
- // Neither is clickable
229
-
230
- // 2.Clickable Parents with Links
231
- // 'mines': {
232
- // path: [
233
- // 'modules', // Not clickable
234
- // { key: 'mines', link: '/app/mines' } // Clickable, navigates to /app/mines
235
- // ],
236
- // }
237
- // Result: Modules > Mines (clickable)
238
-
239
- // 3.Include ID at the end
240
- // 'partners': {
241
- // path: ['modules', { key: 'partners', link: '/app/partners', useRedirect: true }],
242
- // includeId: true, // ← ID will be added at the end
243
- // }
244
- // With id='ABC123':
245
- // Result: Modules > Partners (clickable) > ABC123 (not clickable)
246
-
247
- // 4.Dynamic Id in the middle
248
- // 'mine-evaluation': {
249
- // path: [
250
- // 'modules',
251
- // { key: 'mines', link: '/app/mines' },
252
- // { key: 'id', link: (id) => `/app/mines/${id}` }, // ← ID here
253
- // 'evaluation',
254
- // ],
255
- // }
256
- // With id='MINE-456':
257
- // Result: Modules > Mines > MINE-456 (clickable to /app/mines/MINE-456) > Evaluation
258
-
259
- // 5. Dynamic Links using functions
260
- // 'producers': {
261
- // path: [
262
- // 'modules',
263
- // {
264
- // key: 'producers',
265
- // link: (view) => `/app/${view}`, // ← Uses 'view' parameter
266
- // useRedirect: true
267
- // }
268
- // ],
269
- // includeId: true,
270
- // }
271
- // With view='producers':
272
- // Result: Modules > Producers (navigates to /app/producers)
273
-
274
- // 6.use Redirect link
275
- // 'settings': {
276
- // path: [
277
- // {
278
- // key: 'settings',
279
- // link: '/app/view/settings',
280
- // useRedirect: true // ← Wraps with getRedirectLink()
281
- // }
282
- // ],
283
- // }
284
- // Navigation will use getRedirectLink('/app/view/settings')
285
-
286
- // 7.Conditional Rendering
287
- // 'entities': {
288
- // condition: (opts) => opts.isDataStore, // ← Only shows if isDataStore=true
289
- // path: [
290
- // 'data',
291
- // { key: 'data-store', link: '/app/data-store', useRedirect: true },
292
- // { key: 'entities', link: '/app/data-store/entities', useRedirect: true },
293
- // ],
294
- // }
295
- // With isDataStore=false: No breadcrumbs shown
296
- // With isDataStore=true: Data > Store > Entities
297
-
298
- // 8.Conditional Fallback
299
- // 'locations': {
300
- // condition: (opts) => opts.isDataStore,
301
- // path: [
302
- // 'data',
303
- // { key: 'data-store', link: '/app/data-store', useRedirect: true },
304
- // { key: 'locations', link: '/app/data-store/locations', useRedirect: true },
305
- // ],
306
- // fallback: { // ← Alternative when condition is false
307
- // path: [
308
- // 'modules',
309
- // 'linkedSubjects',
310
- // { key: 'locations', link: '/app/locations', useRedirect: true },
311
- // ],
312
- // includeId: true,
313
- // },
314
- // }
315
- // isDataStore=true: Data > Store > Locations
316
- // isDataStore=false: Modules > Associated Information > Locations > {id}
317
-
318
- // 9. Suffix items
319
- // 'mine-monitoring': {
320
- // path: [
321
- // 'modules',
322
- // { key: 'mines', link: '/app/mines' }
323
- // ],
324
- // includeId: true,
325
- // suffix: ['visits'], // ← Added at the end
326
- // }
327
- // With id='MINE-789':
328
- // Result: Modules > Mines > MINE-789 > Visits
329
-
330
- // 10. Complex multi level path
331
- // 'monitoringReport': {
332
- // path: [
333
- // 'modules', // Static label
334
- // { key: 'mines', link: '/app/mines' }, // Clickable parent
335
- // { key: 'id', link: (id) => `/app/mines/${id}` }, // Dynamic ID with link
336
- // 'monitoringReport', // Static label at end
337
- // ],
338
- // }
339
- // With id='MINE-999':
340
- // Result: Modules > Mines (→/app/mines) > MINE-999 (→/app/mines/MINE-999) > Executive Monitoring Report
341
-
342
- // 11. Access multiple options in condition
343
- // 'custom-view': {
344
- // condition: (opts) => opts.isDataStore && opts.isEdit && opts.id,
345
- // path: ['data', 'custom'],
346
- // }
347
- // Available in opts: { isDataStore, isAnalysis, isEdit, isView, id, view }