@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.
- package/commons/components/app/AppConfigs.d.ts +9 -3
- package/components/app/App.js +1 -0
- package/components/app/providers/FavouritesProvider.js +2 -2
- package/components/hooks/useMyPreferences.js +208 -193
- package/components/hooks/useMySitemap.js +3 -1
- package/components/routes/hits/search/InformationPane.js +3 -3
- package/components/routes/hits/view/HitViewer.js +1 -1
- package/package.json +1 -1
- package/plugins/HowlerPlugin.d.ts +53 -1
- package/plugins/HowlerPlugin.js +146 -14
- package/plugins/store.d.ts +51 -14
- package/plugins/store.js +36 -21
- package/utils/menuUtils.d.ts +89 -0
- package/utils/menuUtils.js +243 -0
|
@@ -97,8 +97,14 @@ export type AppBarUserMenuElement = {
|
|
|
97
97
|
element?: ReactElement<any>;
|
|
98
98
|
};
|
|
99
99
|
export type AppLeftNavElement = {
|
|
100
|
-
type: 'item'
|
|
101
|
-
element: AppLeftNavItem
|
|
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
|
|
125
|
+
icon?: React.ReactElement<any>;
|
|
120
126
|
items: AppLeftNavItem[];
|
|
121
127
|
};
|
|
122
128
|
export type AppSwitcherItem = {
|
package/components/app/App.js
CHANGED
|
@@ -40,7 +40,7 @@ const FavouriteProvider = ({ children }) => {
|
|
|
40
40
|
}));
|
|
41
41
|
if (viewElement) {
|
|
42
42
|
const newViewElement = {
|
|
43
|
-
|
|
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
|
-
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
nested: true,
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
nested: true,
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
-
|
|
205
|
-
|
|
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
|
-
|
|
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
|
|
150
|
-
...Object.fromEntries(dossiers.flatMap((_dossier, dossierIndex) => _dossier.leads
|
|
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
|
|
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
|
|
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
|
@@ -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;
|