@cccsaurora/howler-ui 2.14.0-dev.232 → 2.14.0-dev.245

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.
@@ -97,8 +97,14 @@ export type AppBarUserMenuElement = {
97
97
  element?: ReactElement<any>;
98
98
  };
99
99
  export type AppLeftNavElement = {
100
- type: 'item' | 'group' | 'divider';
101
- element: AppLeftNavItem | AppLeftNavGroup | null;
100
+ type: 'item';
101
+ element: AppLeftNavItem;
102
+ } | {
103
+ type: 'group';
104
+ element: AppLeftNavGroup;
105
+ } | {
106
+ type: 'divider';
107
+ element: null;
102
108
  };
103
109
  export type AppLeftNavItem = {
104
110
  id: number | string;
@@ -116,7 +122,7 @@ export type AppLeftNavGroup = {
116
122
  i18nKey?: string;
117
123
  title?: string;
118
124
  userPropValidators?: AppUserValidatedProp[];
119
- icon: React.ReactElement<any>;
125
+ icon?: React.ReactElement<any>;
120
126
  items: AppLeftNavItem[];
121
127
  };
122
128
  export type AppSwitcherItem = {
@@ -327,6 +327,7 @@ const router = createBrowserRouter([
327
327
  }
328
328
  ]
329
329
  },
330
+ ...howlerPluginStore.routes,
330
331
  {
331
332
  path: '*',
332
333
  element: _jsx(NotFoundPage, {})
@@ -40,7 +40,7 @@ const FavouriteProvider = ({ children }) => {
40
40
  }));
41
41
  if (viewElement) {
42
42
  const newViewElement = {
43
- ...viewElement,
43
+ type: 'group',
44
44
  element: {
45
45
  ...viewElement.element,
46
46
  items
@@ -90,7 +90,7 @@ const FavouriteProvider = ({ children }) => {
90
90
  .filter(v => !!v);
91
91
  if (analyticElement) {
92
92
  return {
93
- ...analyticElement,
93
+ type: 'group',
94
94
  element: {
95
95
  ...analyticElement.element,
96
96
  items
@@ -5,204 +5,221 @@ import Classification from '@cccsaurora/howler-ui/components/elements/display/Cl
5
5
  import DocumentationButton from '@cccsaurora/howler-ui/components/elements/display/DocumentationButton';
6
6
  import howlerPluginStore from '@cccsaurora/howler-ui/plugins/store';
7
7
  import { useMemo } from 'react';
8
+ import AppMenuBuilder from '@cccsaurora/howler-ui/utils/menuUtils';
8
9
  // This is your App Name that will be displayed in the left drawer and the top navbar
9
10
  const APP_NAME = 'howler';
10
11
  const useMyPreferences = () => {
11
12
  // The following menu items will show up in the Left Navigation Drawer
12
- const MENU_ITEMS = useMemo(() => [
13
- {
14
- type: 'item',
15
- element: {
16
- id: 'dashboard',
17
- i18nKey: 'route.home',
18
- route: '/',
19
- icon: _jsx(Dashboard, {})
20
- }
21
- },
22
- {
23
- type: 'group',
24
- element: {
25
- id: 'views',
26
- i18nKey: 'route.views.saved',
27
- icon: _jsx(SavedSearch, {}),
28
- items: []
29
- }
30
- },
31
- {
32
- type: 'group',
33
- element: {
34
- id: 'analytics',
35
- i18nKey: 'route.analytics.pinned',
36
- icon: _jsx(QueryStats, {}),
37
- items: []
38
- }
39
- },
40
- {
41
- type: 'item',
42
- element: {
43
- id: 'search.hit',
44
- i18nKey: 'route.search',
45
- route: '/search',
46
- icon: _jsx(Search, {})
47
- }
48
- },
49
- {
50
- type: 'item',
51
- element: {
52
- id: 'advanced',
53
- i18nKey: 'route.advanced',
54
- route: '/advanced',
55
- icon: _jsx(Code, {})
56
- }
57
- },
58
- {
59
- type: 'divider',
60
- element: null
61
- },
62
- {
63
- type: 'group',
64
- element: {
65
- id: 'manage',
66
- i18nKey: 'manage',
67
- icon: _jsx(Edit, {}),
68
- items: [
69
- {
70
- id: 'manage.views',
71
- i18nKey: 'route.views',
72
- icon: _jsx(ManageSearch, {}),
73
- nested: true,
74
- route: '/views'
75
- },
76
- {
77
- id: 'manage.analytics',
78
- i18nKey: 'route.analytics',
79
- icon: _jsx(QueryStats, {}),
80
- nested: true,
81
- route: '/analytics'
82
- },
83
- {
84
- id: 'manage.templates',
85
- i18nKey: 'route.templates',
86
- icon: _jsx(FormatListBulleted, {}),
87
- nested: true,
88
- route: '/templates'
89
- },
90
- {
91
- id: 'manage.overviews',
92
- i18nKey: 'route.overviews',
93
- icon: _jsx(Article, {}),
94
- nested: true,
95
- route: '/overviews'
96
- },
97
- {
98
- id: 'manage.dossiers',
99
- i18nKey: 'route.dossiers',
100
- icon: _jsx(Topic, {}),
101
- nested: true,
102
- route: '/dossiers'
103
- },
104
- {
105
- id: 'manage.actions',
106
- i18nKey: 'route.actions',
107
- icon: _jsx(Terminal, {}),
108
- nested: true,
109
- route: '/action',
110
- userPropValidators: [{ prop: 'roles', value: 'automation_basic' }]
111
- },
112
- {
113
- id: 'action.integrations',
114
- i18nKey: 'route.integrations',
115
- icon: _jsx(Api, {}),
116
- nested: true,
117
- route: '/action/integrations',
118
- userPropValidators: [{ prop: 'roles', value: 'automation_basic' }]
119
- }
120
- ]
121
- }
122
- },
123
- {
124
- type: 'divider',
125
- element: null
126
- },
127
- {
128
- type: 'group',
129
- element: {
130
- id: 'help',
131
- i18nKey: 'page.help',
132
- icon: _jsx(Help, {}),
133
- items: [
134
- {
135
- id: 'help.main',
136
- i18nKey: 'route.help.main',
137
- route: '/help',
138
- nested: true,
139
- icon: _jsx(HelpCenter, {})
140
- },
141
- {
142
- id: 'help.client',
143
- i18nKey: 'route.help.client',
144
- route: '/help/client',
145
- nested: true,
146
- icon: _jsx(Terminal, {})
147
- },
148
- { id: 'help.hit', i18nKey: 'route.help.hit', route: '/help/hit', nested: true, icon: _jsx(Shield, {}) },
149
- { id: 'help.search', i18nKey: 'route.help.search', route: '/help/search', nested: true, icon: _jsx(Search, {}) },
150
- {
151
- id: 'help.views',
152
- i18nKey: 'route.help.views',
153
- route: '/help/views',
154
- nested: true,
155
- icon: _jsx(SavedSearch, {})
156
- },
157
- {
158
- id: 'help.templates',
159
- i18nKey: 'route.help.templates',
160
- route: '/help/templates',
161
- nested: true,
162
- icon: _jsx(FormatListBulleted, {})
163
- },
164
- {
165
- id: 'help.overview',
166
- i18nKey: 'route.help.overviews',
167
- route: '/help/overviews',
168
- nested: true,
169
- icon: _jsx(Article, {})
170
- },
171
- { id: 'help.auth', i18nKey: 'route.help.auth', route: '/help/auth', nested: true, icon: _jsx(Key, {}) },
172
- {
173
- id: 'help.actions',
174
- i18nKey: 'route.help.actions',
175
- route: '/help/actions',
176
- nested: true,
177
- icon: _jsx(SettingsSuggest, {})
178
- },
179
- {
180
- id: 'help.notebook',
181
- i18nKey: 'route.help.notebook',
182
- route: '/help/notebook',
183
- nested: true,
184
- icon: _jsx(Description, {})
185
- },
186
- { id: 'help.api', i18nKey: 'route.help.api', route: '/help/api', nested: true, icon: _jsx(Storage, {}) },
187
- {
188
- id: 'help.retention',
189
- i18nKey: 'route.help.retention',
190
- route: '/help/retention',
191
- nested: true,
192
- icon: _jsx(Book, {})
193
- }
194
- ]
13
+ const MENU_ITEMS = useMemo(() => {
14
+ let defaultMenu = [
15
+ {
16
+ type: 'item',
17
+ element: {
18
+ id: 'dashboard',
19
+ i18nKey: 'route.home',
20
+ route: '/',
21
+ icon: _jsx(Dashboard, {})
22
+ }
23
+ },
24
+ {
25
+ type: 'group',
26
+ element: {
27
+ id: 'views',
28
+ i18nKey: 'route.views.saved',
29
+ icon: _jsx(SavedSearch, {}),
30
+ items: []
31
+ }
32
+ },
33
+ {
34
+ type: 'group',
35
+ element: {
36
+ id: 'analytics',
37
+ i18nKey: 'route.analytics.pinned',
38
+ icon: _jsx(QueryStats, {}),
39
+ items: []
40
+ }
41
+ },
42
+ {
43
+ type: 'item',
44
+ element: {
45
+ id: 'search.hit',
46
+ i18nKey: 'route.search',
47
+ route: '/search',
48
+ icon: _jsx(Search, {})
49
+ }
50
+ },
51
+ {
52
+ type: 'item',
53
+ element: {
54
+ id: 'advanced',
55
+ i18nKey: 'route.advanced',
56
+ route: '/advanced',
57
+ icon: _jsx(Code, {})
58
+ }
59
+ },
60
+ {
61
+ type: 'divider',
62
+ element: null
63
+ },
64
+ {
65
+ type: 'group',
66
+ element: {
67
+ id: 'manage',
68
+ i18nKey: 'manage',
69
+ icon: _jsx(Edit, {}),
70
+ items: [
71
+ {
72
+ id: 'manage.views',
73
+ i18nKey: 'route.views',
74
+ icon: _jsx(ManageSearch, {}),
75
+ nested: true,
76
+ route: '/views'
77
+ },
78
+ {
79
+ id: 'manage.analytics',
80
+ i18nKey: 'route.analytics',
81
+ icon: _jsx(QueryStats, {}),
82
+ nested: true,
83
+ route: '/analytics'
84
+ },
85
+ {
86
+ id: 'manage.templates',
87
+ i18nKey: 'route.templates',
88
+ icon: _jsx(FormatListBulleted, {}),
89
+ nested: true,
90
+ route: '/templates'
91
+ },
92
+ {
93
+ id: 'manage.overviews',
94
+ i18nKey: 'route.overviews',
95
+ icon: _jsx(Article, {}),
96
+ nested: true,
97
+ route: '/overviews'
98
+ },
99
+ {
100
+ id: 'manage.dossiers',
101
+ i18nKey: 'route.dossiers',
102
+ icon: _jsx(Topic, {}),
103
+ nested: true,
104
+ route: '/dossiers'
105
+ },
106
+ {
107
+ id: 'manage.actions',
108
+ i18nKey: 'route.actions',
109
+ icon: _jsx(Terminal, {}),
110
+ nested: true,
111
+ route: '/action',
112
+ userPropValidators: [
113
+ { prop: 'roles', value: 'automation_basic' },
114
+ { prop: 'roles', value: 'automation_advanced' },
115
+ { prop: 'roles', value: 'actionrunner_basic' },
116
+ { prop: 'roles', value: 'actionrunner_advanced' }
117
+ ]
118
+ },
119
+ {
120
+ id: 'action.integrations',
121
+ i18nKey: 'route.integrations',
122
+ icon: _jsx(Api, {}),
123
+ nested: true,
124
+ route: '/action/integrations',
125
+ userPropValidators: [{ prop: 'roles', value: 'automation_basic' }]
126
+ }
127
+ ]
128
+ }
129
+ },
130
+ {
131
+ type: 'divider',
132
+ element: null
133
+ },
134
+ {
135
+ type: 'group',
136
+ element: {
137
+ id: 'help',
138
+ i18nKey: 'page.help',
139
+ icon: _jsx(Help, {}),
140
+ items: [
141
+ {
142
+ id: 'help.main',
143
+ i18nKey: 'route.help.main',
144
+ route: '/help',
145
+ nested: true,
146
+ icon: _jsx(HelpCenter, {})
147
+ },
148
+ {
149
+ id: 'help.client',
150
+ i18nKey: 'route.help.client',
151
+ route: '/help/client',
152
+ nested: true,
153
+ icon: _jsx(Terminal, {})
154
+ },
155
+ { id: 'help.hit', i18nKey: 'route.help.hit', route: '/help/hit', nested: true, icon: _jsx(Shield, {}) },
156
+ {
157
+ id: 'help.search',
158
+ i18nKey: 'route.help.search',
159
+ route: '/help/search',
160
+ nested: true,
161
+ icon: _jsx(Search, {})
162
+ },
163
+ {
164
+ id: 'help.views',
165
+ i18nKey: 'route.help.views',
166
+ route: '/help/views',
167
+ nested: true,
168
+ icon: _jsx(SavedSearch, {})
169
+ },
170
+ {
171
+ id: 'help.templates',
172
+ i18nKey: 'route.help.templates',
173
+ route: '/help/templates',
174
+ nested: true,
175
+ icon: _jsx(FormatListBulleted, {})
176
+ },
177
+ {
178
+ id: 'help.overview',
179
+ i18nKey: 'route.help.overviews',
180
+ route: '/help/overviews',
181
+ nested: true,
182
+ icon: _jsx(Article, {})
183
+ },
184
+ { id: 'help.auth', i18nKey: 'route.help.auth', route: '/help/auth', nested: true, icon: _jsx(Key, {}) },
185
+ {
186
+ id: 'help.actions',
187
+ i18nKey: 'route.help.actions',
188
+ route: '/help/actions',
189
+ nested: true,
190
+ icon: _jsx(SettingsSuggest, {})
191
+ },
192
+ {
193
+ id: 'help.notebook',
194
+ i18nKey: 'route.help.notebook',
195
+ route: '/help/notebook',
196
+ nested: true,
197
+ icon: _jsx(Description, {})
198
+ },
199
+ { id: 'help.api', i18nKey: 'route.help.api', route: '/help/api', nested: true, icon: _jsx(Storage, {}) },
200
+ {
201
+ id: 'help.retention',
202
+ i18nKey: 'route.help.retention',
203
+ route: '/help/retention',
204
+ nested: true,
205
+ icon: _jsx(Book, {})
206
+ }
207
+ ]
208
+ }
195
209
  }
196
- }
197
- ],
210
+ ];
211
+ const appMenuBuilder = new AppMenuBuilder(defaultMenu);
212
+ appMenuBuilder.applyOperations(howlerPluginStore.mainMenuOperations);
213
+ return appMenuBuilder.menu;
214
+ },
198
215
  // prettier-ignore
199
216
  []);
200
217
  // This is the basic user menu, it is a menu that shows up in account avatar popover.
201
218
  const USER_MENU_ITEMS = useMemo(() => {
202
219
  // Load plugin menu items first as Settings/Logout generally
203
220
  // appear at the end of user menus.
204
- const results = howlerPluginStore.userMenuItems;
205
- results.push(...[
221
+ return [
222
+ ...howlerPluginStore.userMenuItems,
206
223
  {
207
224
  i18nKey: 'usermenu.settings',
208
225
  route: '/settings',
@@ -213,20 +230,18 @@ const useMyPreferences = () => {
213
230
  route: '/logout',
214
231
  icon: _jsx(ExitToApp, {})
215
232
  }
216
- ]);
217
- return results;
233
+ ];
218
234
  }, []);
219
235
  // This is the basic administrator menu, it is a menu that shows up under the user menu in the account avatar popover.
220
236
  const ADMIN_MENU_ITEMS = useMemo(() => {
221
- const results = [
237
+ return [
222
238
  {
223
239
  i18nKey: 'adminmenu.users',
224
240
  route: '/admin/users',
225
241
  icon: _jsx(SupervisorAccount, {})
226
- }
242
+ },
243
+ ...howlerPluginStore.adminMenuItems
227
244
  ];
228
- results.push(...howlerPluginStore.adminMenuItems);
229
- return results;
230
245
  }, []);
231
246
  // Return memoized config to prevent unnecessary re-renders.
232
247
  return useMemo(() => ({
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Article, Book, Code, CreateNewFolder, Dashboard, Description, Edit, EditNote, FormatListBulleted, Help, Info, Key, Person, PersonSearch, QueryStats, SavedSearch, Search, Settings, SettingsSuggest, Shield, Storage, Terminal, Topic, Work } from '@mui/icons-material';
3
+ import howlerPluginStore from '@cccsaurora/howler-ui/plugins/store';
3
4
  import { useMemo } from 'react';
4
5
  import { useTranslation } from 'react-i18next';
5
6
  // SiteMapContextProps configuration properties.
@@ -208,7 +209,8 @@ const useMySitemap = () => {
208
209
  },
209
210
  { path: '/home', title: t('route.home'), isRoot: true, icon: _jsx(Dashboard, {}) },
210
211
  { path: '/settings', title: t('page.settings.sitemap'), isRoot: true, icon: _jsx(Settings, {}) },
211
- { path: '/advanced', title: t('route.advanced'), isRoot: true, icon: _jsx(Code, {}) }
212
+ { path: '/advanced', title: t('route.advanced'), isRoot: true, icon: _jsx(Code, {}) },
213
+ ...howlerPluginStore.sitemaps
212
214
  ]
213
215
  }), [t]);
214
216
  };
@@ -146,8 +146,8 @@ const InformationPane = ({ onClose }) => {
146
146
  hit_worklog: () => _jsx(HitWorklog, { hit: !loading && hit, users: users }),
147
147
  hit_aggregate: () => _jsx(HitSummary, { query: `howler.bundles:(${hit?.howler?.id})` }),
148
148
  hit_related: () => _jsx(HitRelated, { hit: hit }),
149
- ...Object.fromEntries(hit?.howler.dossier?.map((lead, index) => ['lead:' + index, () => _jsx(LeadRenderer, { lead: lead })]) ?? []),
150
- ...Object.fromEntries(dossiers.flatMap((_dossier, dossierIndex) => _dossier.leads?.map((_lead, leadIndex) => [
149
+ ...Object.fromEntries((hit?.howler.dossier ?? []).map((lead, index) => ['lead:' + index, () => _jsx(LeadRenderer, { lead: lead })])),
150
+ ...Object.fromEntries(dossiers.flatMap((_dossier, dossierIndex) => (_dossier.leads ?? []).map((_lead, leadIndex) => [
151
151
  `external-lead:${dossierIndex}:${leadIndex}`,
152
152
  () => _jsx(LeadRenderer, { lead: _lead, hit: hit })
153
153
  ])))
@@ -194,7 +194,7 @@ const InformationPane = ({ onClose }) => {
194
194
  '& > svg': { zIndex: 2 }
195
195
  }, badgeContent: hit?.howler.comment?.length ?? 0, children: _jsx(Comment, {}) }) }), value: "hit_comments", onClick: () => setTab('hit_comments') }), hit?.howler?.is_bundle && (_jsx(Tab, { label: t('hit.viewer.aggregate'), value: "hit_aggregate", onClick: () => setTab('hit_aggregate') })), hasOverview && (_jsx(Tab, { label: t('hit.viewer.overview'), value: "overview", onClick: () => setTab('overview') })), _jsx(Tab, { label: t('hit.viewer.details'), value: "details", onClick: () => setTab('details') }), hit?.howler.dossier?.map((lead, index) => (_jsx(Tab
196
196
  // eslint-disable-next-line react/no-array-index-key
197
- , { label: _jsxs(Stack, { direction: "row", spacing: 0.5, children: [lead.icon && _jsx(Icon, { icon: lead.icon }), _jsx("span", { children: i18n.language === 'en' ? lead.label.en : lead.label.fr })] }), value: 'lead:' + index, onClick: () => setTab('lead:' + index) }, 'lead:' + index))), dossiers.flatMap((_dossier, dossierIndex) => _dossier.leads?.map((_lead, leadIndex) => (_jsx(Tab
197
+ , { label: _jsxs(Stack, { direction: "row", spacing: 0.5, children: [lead.icon && _jsx(Icon, { icon: lead.icon }), _jsx("span", { children: i18n.language === 'en' ? lead.label.en : lead.label.fr })] }), value: 'lead:' + index, onClick: () => setTab('lead:' + index) }, 'lead:' + index))), dossiers.flatMap((_dossier, dossierIndex) => (_dossier.leads ?? []).map((_lead, leadIndex) => (_jsx(Tab
198
198
  // eslint-disable-next-line react/no-array-index-key
199
199
  , { label: _jsxs(Stack, { direction: "row", spacing: 0.5, children: [_lead.icon && _jsx(Icon, { icon: _lead.icon }), _jsx("span", { children: i18n.language === 'en' ? _lead.label.en : _lead.label.fr })] }), value: `external-lead:${dossierIndex}:${leadIndex}`, onClick: () => setTab(`external-lead:${dossierIndex}:${leadIndex}`) }, `external-lead:${dossierIndex}:${leadIndex}`)))), _jsx(FlexOne, {}), _jsx(Tab, { sx: { px: 2, minWidth: 0 }, label: _jsx(Tooltip, { title: t('hit.viewer.data'), children: _jsx(DataObject, {}) }), value: "hit_data", onClick: () => setTab('hit_data'), disabled: !hit?.howler?.data }), _jsx(Tab, { sx: { px: 2, minWidth: 0 }, label: _jsx(Tooltip, { title: t('hit.viewer.json'), children: _jsx(Code, {}) }), value: "hit_raw", onClick: () => setTab('hit_raw') }), _jsx(Tab, { sx: { px: 2, minWidth: 0 }, label: _jsx(Tooltip, { title: t('hit.viewer.worklog'), children: _jsx(History, {}) }), value: "hit_worklog", onClick: () => setTab('hit_worklog') }), _jsx(Tab, { sx: { px: 2, minWidth: 0 }, label: _jsx(Tooltip, { title: t('hit.viewer.related'), children: _jsx(LinkSharp, {}) }), value: "hit_related", onClick: () => setTab('hit_related') })] }), ['hit_raw', 'hit_data'].includes(tab) && (_jsx(Phrase, { sx: { mt: 1, pr: 1 }, value: filter, onChange: setFilter, error: hasError, label: t('json.viewer.search.label'), placeholder: t('json.viewer.search.prompt'), endAdornment: _jsx(IconButton, { onClick: () => setFilter(''), children: _jsx(Clear, {}) }) }))] }), _jsx(ErrorBoundary, { children: _jsx(VSBoxContent, { mr: -1, ml: -1, height: "100%", children: _jsx(Stack, { height: "100%", flex: 1, children: tabContent }) }) })] }), !!hit && hit?.howler && (_jsxs(Box, { pr: 2, bgcolor: theme.palette.background.default, position: "relative", children: [_jsx(Divider, { orientation: "horizontal" }), _jsx(HitActions, { hit: hit })] }))] }));
200
200
  };
@@ -144,7 +144,7 @@ const HitViewer = () => {
144
144
  right: theme.spacing(-6)
145
145
  }, children: [_jsx(Tooltip, { title: t('page.hits.view.layout'), children: _jsx(IconButton, { onClick: onOrientationChange, children: _jsx(ViewAgenda, { sx: { transition: 'rotate 250ms', rotate: orientation === 'vertical' ? '90deg' : '0deg' } }) }) }), _jsx(SocketBadge, { size: "medium" }), analytic && (_jsx(Tooltip, { title: t('hit.panel.analytic.open'), children: _jsx(IconButton, { onClick: () => navigate(`/analytics/${analytic.analytic_id}`), children: _jsx(QueryStats, {}) }) })), hit?.howler.bundles?.length > 0 && _jsx(BundleButton, { ids: hit.howler.bundles })] }))] }), _jsx(HowlerCard, { sx: [orientation === 'horizontal' && { height: '0px' }], children: _jsx(CardContent, { sx: { padding: 1, position: 'relative' }, children: _jsx(HitActions, { hit: hit, orientation: "vertical" }) }) }), _jsx(Box, { sx: { gridColumn: '1 / span 2', mb: 1 }, children: _jsxs(Tabs, { value: tab === 'overview' && !hasOverview ? 'details' : tab, sx: { display: 'flex', flexDirection: 'row', pr: 2, alignItems: 'center' }, children: [hit?.howler?.is_bundle && (_jsx(Tab, { label: t('hit.viewer.aggregate'), value: "hit_aggregate", onClick: () => setTab('hit_aggregate') })), hasOverview && (_jsx(Tab, { label: t('hit.viewer.overview'), value: "overview", onClick: () => setTab('overview') })), _jsx(Tab, { label: t('hit.viewer.details'), value: "details", onClick: () => setTab('details') }), hit?.howler.dossier?.map((lead, index) => (_jsx(Tab
146
146
  // eslint-disable-next-line react/no-array-index-key
147
- , { label: _jsxs(Stack, { direction: "row", spacing: 0.5, children: [lead.icon && _jsx(Icon, { icon: lead.icon }), _jsx("span", { children: i18n.language === 'en' ? lead.label.en : lead.label.fr })] }), value: 'lead:' + index, onClick: () => setTab('lead:' + index) }, 'lead:' + index))), dossiers.flatMap((_dossier, dossierIndex) => _dossier.leads?.map((_lead, leadIndex) => (_jsx(Tab
147
+ , { label: _jsxs(Stack, { direction: "row", spacing: 0.5, children: [lead.icon && _jsx(Icon, { icon: lead.icon }), _jsx("span", { children: i18n.language === 'en' ? lead.label.en : lead.label.fr })] }), value: 'lead:' + index, onClick: () => setTab('lead:' + index) }, 'lead:' + index))), dossiers.flatMap((_dossier, dossierIndex) => (_dossier.leads ?? []).map((_lead, leadIndex) => (_jsx(Tab
148
148
  // eslint-disable-next-line react/no-array-index-key
149
149
  , { label: _jsxs(Stack, { direction: "row", spacing: 0.5, children: [_lead.icon && _jsx(Icon, { icon: _lead.icon }), _jsx("span", { children: i18n.language === 'en' ? _lead.label.en : _lead.label.fr })] }), value: `external-lead:${dossierIndex}:${leadIndex}`, onClick: () => setTab(`external-lead:${dossierIndex}:${leadIndex}`) }, `external-lead:${dossierIndex}:${leadIndex}`)))), _jsx(FlexOne, {}), _jsx(Tab, { sx: { px: 2, minWidth: 0 }, label: _jsx(Tooltip, { title: t('hit.viewer.data'), children: _jsx(DataObject, {}) }), value: "hit_data", onClick: () => setTab('hit_data'), disabled: !hit?.howler?.data }), _jsx(Tab, { sx: { px: 2, minWidth: 0 }, label: _jsx(Tooltip, { title: t('hit.viewer.json'), children: _jsx(Code, {}) }), value: "hit_raw", onClick: () => setTab('hit_raw') }), _jsx(Tab, { sx: { px: 2, minWidth: 0 }, label: _jsx(Tooltip, { title: t('hit.viewer.comments'), children: _jsx(Badge, { sx: {
150
150
  '& > .MuiBadge-badge': {
package/package.json CHANGED
@@ -95,7 +95,7 @@
95
95
  "internal-slot": "1.0.7"
96
96
  },
97
97
  "type": "module",
98
- "version": "2.14.0-dev.232",
98
+ "version": "2.14.0-dev.245",
99
99
  "exports": {
100
100
  "./i18n": "./i18n.js",
101
101
  "./index.css": "./index.css",
@@ -13,6 +13,7 @@ import type { Hit } from '@cccsaurora/howler-ui/models/entities/generated/Hit';
13
13
  import type React from 'react';
14
14
  import type { PropsWithChildren } from 'react';
15
15
  import type { IPlugin, PluginStore } from 'react-pluggable';
16
+ import type { MainMenuInsertOperation } from './store';
16
17
  declare abstract class HowlerPlugin implements IPlugin {
17
18
  abstract name: string;
18
19
  abstract version: string;
@@ -27,7 +28,6 @@ declare abstract class HowlerPlugin implements IPlugin {
27
28
  deactivate(): void;
28
29
  addLead(format: string, form: (props: LeadFormProps) => React.ReactNode, renderer: (content: string, metadata: any, hit?: Hit) => React.ReactNode): void;
29
30
  addPivot(format: string, form: (props: PivotFormProps) => React.ReactNode, renderer: (props: PivotLinkProps) => React.ReactNode): void;
30
- addOperation(format: string, form: (props: CustomActionProps) => React.ReactNode, documentation: PluginDocumentation): void;
31
31
  /**
32
32
  * Adds a single menu item to the User Menu group under the Avatar Menu,
33
33
  * items are added before the 'Settings' and 'Logout' menu items.
@@ -46,6 +46,58 @@ declare abstract class HowlerPlugin implements IPlugin {
46
46
  * @param icon JSX Icon element, <Settings/> for example
47
47
  */
48
48
  addAdminMenuItem(i18nKey: string, route: string, icon: JSX.Element): void;
49
+ /**
50
+ * Adds a single route to the system to load, items are added to the end of
51
+ * base routes defined.
52
+ *
53
+ * @param path Route path, should not start with /
54
+ * @param element Element the route directs to
55
+ * @param children Child routes if required
56
+ */
57
+ addRoute(path: string, element: JSX.Element, children?: []): void;
58
+ /**
59
+ * Adds a sitemap entry to the sitemap table, this is used to populate
60
+ * information on the Breadcrumb component
61
+ *
62
+ * @param path The react router path to this route
63
+ * @param title The title/label to display in breadcrumbs for this route
64
+ * @param icon The icon component to show beside the title/label
65
+ * @param isRoot When true, indicates that the breadcrumbs will reset to this one path each time it is encountered
66
+ * @param isLeaf When true, indicates that this path does not aggregate in breadcrumbs, i.e. will be replaced by next path
67
+ * @param excluded When true, indicates to breadcrumbs component to not render this route
68
+ * @param breadcrumbs Static list of breadcrumb paths to be rendered for the given route
69
+ * @param textWidth The max width of the text when rendering the breadcrumb
70
+ */
71
+ addSitemap(path: string, title: string, icon?: JSX.Element, isRoot?: boolean, isLeaf?: boolean, excluded?: boolean, breadcrumbs?: string[], textWidth?: number): void;
72
+ /**
73
+ * Adds a route as well as a simple sitemap entry with values derived from the path
74
+ *
75
+ * @param path Route path, should not start with /
76
+ * @param element Element the route directs to
77
+ * @param children Child routes if required
78
+ * @param title The title/label to display in breadcrumbs for this route
79
+ * @param icon The icon component to show beside the title/label
80
+ */
81
+ addRouteAndSitemap(path: string, element: JSX.Element, title: string, icon?: JSX.Element, children?: []): void;
82
+ /**
83
+ * Adds a new menu item to the Main Menu
84
+ *
85
+ * @param operation Insert operation to perform
86
+ * @param targetId Reference Menu Id
87
+ * @param id Identifier for new menu entry
88
+ * @param i18nKey Translation key for new menu entry
89
+ * @param route Route for new menu entry
90
+ * @param icon Icon for new menu entry
91
+ */
92
+ addMainMenuItem(operation: MainMenuInsertOperation, targetId: string, id: string, i18nKey: string, route: string, icon: JSX.Element): void;
93
+ /**
94
+ * Adds a divider to the main menu
95
+ *
96
+ * @param operation Insert operation to perform
97
+ * @param targetId Reference menu id
98
+ */
99
+ addMainMenuDivider(operation: MainMenuInsertOperation, targetId: string): void;
100
+ addOperation(format: string, form: (props: CustomActionProps) => React.ReactNode, documentation: PluginDocumentation): void;
49
101
  on(_event: string, _hit: Hit): any;
50
102
  provider(): React.FC<PropsWithChildren<{}>> | null;
51
103
  setup(): void;