@cccsaurora/howler-ui 2.17.0-dev.522 → 2.17.0-dev.525

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.
@@ -25,7 +25,8 @@ const useMySitemap = () => {
25
25
  routes: [
26
26
  { path: '/', title: t('route.home'), isRoot: true, icon: _jsx(Dashboard, {}) },
27
27
  { path: '/cases', title: t('route.cases'), isRoot: true, icon: _jsx(BookRounded, {}) },
28
- { path: '/cases/:id', title: t('route.cases.view') },
28
+ { path: '/cases/:id', title: t('route.cases.view'), breadcrumbs: ['/cases'] },
29
+ { path: '/cases/:id/*', title: t('route.cases.view'), breadcrumbs: ['/cases'] },
29
30
  { path: '/admin/users', title: t('route.admin.user.search'), isRoot: true, icon: _jsx(PersonSearch, {}) },
30
31
  {
31
32
  path: '/admin/users/:id',
@@ -19,8 +19,11 @@ const AGGREGATE_FIELDS = [
19
19
  ];
20
20
  const getDuration = (case_) => {
21
21
  if (case_?.start) {
22
- return dayjs.duration(dayjs(case_?.end ?? new Date()).diff(dayjs(case_.start), 'minute'), 'minute');
22
+ return dayjs
23
+ .duration(dayjs(case_?.end ?? new Date()).diff(dayjs(case_.start), 'minute'), 'minute')
24
+ .format('HH[h] mm[m]');
23
25
  }
26
+ return '--';
24
27
  };
25
28
  const CaseDashboard = ({ case: providedCase, caseId }) => {
26
29
  const { t } = useTranslation();
@@ -41,6 +44,6 @@ const CaseDashboard = ({ case: providedCase, caseId }) => {
41
44
  if (!_case) {
42
45
  return null;
43
46
  }
44
- return (_jsxs(Grid, { container: true, spacing: 5, width: "100%", px: 3, children: [_jsx(Grid, { item: true, xs: 12, children: _jsx(CaseOverview, { case: _case, updateCase: updateCase }) }), AGGREGATE_FIELDS.map(([field, icon, iconColor, subtitle]) => (_jsx(Grid, { item: true, xs: 12, md: 6, xl: 3, children: _jsx(CaseAggregate, { icon: icon, iconColor: iconColor && get(theme.palette, iconColor), field: field, records: records, subtitle: t(subtitle) }) }, field))), _jsx(Grid, { item: true, xs: 12, md: 6, xl: 3, children: _jsx(CaseAggregate, { icon: "mingcute:heartbeat-line", iconColor: theme.palette.error.light, title: getDuration(_case)?.format('HH[h] mm[m]') ?? '--', subtitle: t('page.cases.dashboard.duration') }) }), _jsx(Grid, { item: true, xs: 12, children: _jsx(TaskPanel, { case: _case, updateCase: updateCase }) }), _jsx(Grid, { item: true, xs: 12, children: _jsx(AlertPanel, { case: _case }) }), _jsx(Grid, { item: true, xs: 12, children: _jsx(RelatedCasePanel, { case: _case }) })] }));
47
+ return (_jsxs(Grid, { container: true, spacing: 5, width: "100%", px: 3, children: [_jsx(Grid, { item: true, xs: 12, children: _jsx(CaseOverview, { case: _case, updateCase: updateCase }) }), AGGREGATE_FIELDS.map(([field, icon, iconColor, subtitle]) => (_jsx(Grid, { item: true, xs: 12, md: 6, xl: 3, children: _jsx(CaseAggregate, { icon: icon, iconColor: iconColor && get(theme.palette, iconColor), field: field, records: records, subtitle: t(subtitle) }) }, field))), _jsx(Grid, { item: true, xs: 12, md: 6, xl: 3, children: _jsx(CaseAggregate, { icon: "mingcute:heartbeat-line", iconColor: theme.palette.error.light, title: getDuration(_case), subtitle: t('page.cases.dashboard.duration') }) }), _jsx(Grid, { item: true, xs: 12, children: _jsx(TaskPanel, { case: _case, updateCase: updateCase }) }), _jsx(Grid, { item: true, xs: 12, children: _jsx(AlertPanel, { case: _case }) }), _jsx(Grid, { item: true, xs: 12, children: _jsx(RelatedCasePanel, { case: _case }) })] }));
45
48
  };
46
49
  export default CaseDashboard;
@@ -54,8 +54,8 @@ const CaseDetails = ({ case: providedCase }) => {
54
54
  position: 'relative'
55
55
  }, children: [_jsx(LinearProgress, { sx: { opacity: +loading, position: 'absolute', top: 0, left: 0, right: 0 } }), _jsxs(Stack, { spacing: 2, children: [_jsxs(Stack, { spacing: 1, children: [_jsxs(Stack, { direction: "row", spacing: 1, alignItems: "center", children: [{
56
56
  'in-progress': _jsx(HourglassBottom, { color: "warning" }),
57
- closed: _jsx(Check, { color: "success" }),
58
- 'on-hold': _jsx(Pause, { color: "disabled" })
57
+ 'on-hold': _jsx(Pause, { color: "disabled" }),
58
+ resolved: _jsx(Check, { color: "success" })
59
59
  }[_case.status] ?? _jsx(WarningRounded, { fontSize: "small" }), _jsx(Typography, { variant: "body1", children: t('page.cases.detail.status') })] }), _jsx(Autocomplete, { size: "small", disabled: loading, value: _case.status, options: config.lookups['howler.status'], renderInput: params => _jsx(TextField, { ...params, size: "small" }), onChange: (_ev, status) => handleStatus(status) })] }), _jsx(Divider, {}), _jsxs(Stack, { spacing: 1, children: [_jsxs(Stack, { direction: "row", spacing: 1, alignItems: "center", children: [_jsx(People, {}), _jsx(Typography, { variant: "body1", children: t('page.cases.detail.participants') })] }), _jsx(UserList, { buttonSx: { alignSelf: 'start' }, multiple: true, i18nLabel: "page.cases.detail.assignment", userIds: _case.participants ?? [], onChange: participants => wrappedUpdate({ participants }), disabled: loading })] }), _jsx(Divider, {}), _jsxs(Stack, { spacing: 1, children: [_jsxs(Stack, { direction: "row", spacing: 1, alignItems: "center", children: [_jsx(FormatListBulleted, {}), _jsx(Typography, { variant: "body1", children: t('page.cases.detail.properties') })] }), _jsx(Table, { sx: { '& td': { p: 1 } }, children: _jsxs(TableBody, { children: [_jsxs(TableRow, { children: [_jsx(TableCell, { children: _jsx(Typography, { variant: "caption", children: t('page.cases.escalation') }) }), _jsx(TableCell, { children: _jsx(Chip, { size: "small", label: _case.escalation }) })] }), _jsxs(TableRow, { children: [_jsx(TableCell, { children: _jsx(Typography, { variant: "caption", children: t('page.cases.created') }) }), _jsx(TableCell, { children: _jsx(Typography, { variant: "caption", children: dayjs(_case.created).toString() }) })] }), _jsxs(TableRow, { children: [_jsx(TableCell, { children: _jsx(Typography, { variant: "caption", children: t('page.cases.updated') }) }), _jsx(TableCell, { children: _jsx(Typography, { variant: "caption", children: dayjs(_case.updated).toString() }) })] }), _jsxs(TableRow, { children: [_jsx(TableCell, { children: _jsx(Typography, { variant: "caption", children: t('page.cases.sources') }) }), _jsx(TableCell, { children: _jsx(Typography, { variant: "caption", children: _jsx(SourceAggregate, { case: _case }) }) })] })] }) })] })] })] }));
60
60
  };
61
61
  export default CaseDetails;
@@ -0,0 +1 @@
1
+ export default "<h3>Actions</h3>\n\n<ul class=\"actions_list\">\n\n<li>\n\n</li>\n\n<li>\n\n</li>\n\n</ul>\n\n<h3>Data</h3>\n\n<table class=\"table_overview\">\n\n<tbody>\n\n<tr>\n\n<td style=\"padding:8px;font-weight:bold;\">Tangent</td>\n\n<td style=\"padding:8px;\">Triangle</td>\n\n</tr>\n\n<tr>\n\n<td style=\"padding:8px;font-weight:bold;\">Start date</td>\n\n<td style=\"padding:8px;\">1</td>\n\n</tr>\n\n<tr>\n\n<td style=\"padding:8px;font-weight:bold;\">End date</td>\n\n<td style=\"padding:8px;\">1</td>\n\n</tr>\n\n<tr>\n\n<td style=\"padding:8px;font-weight:bold;\">Country</td>\n\n<td style=\"padding:8px;\"><span style=\"text-transform: uppercase;\">Canada</span> / <span style=\"text-transform: capitalize;\">Canada / <span style=\"text-transform: capitalize;\">Canada</span></td>\n\n</tr>\n\n</tbody>\n\n</table>\n\n<h3>Visualization</h3>\n\n```mermaid\n\ngraph LR\n\nA[Password Spraying IP] -- Login Failure Account A --> D{ Entra ID }\n\nA[Password Spraying IP] -- Login Failure Account B --> D{ Entra ID }\n\nA[Password Spraying IP] -- Login Failure Account C --> D{ Entra ID }\n\nA[Password Spraying IP] -- Login Failure Account D --> D{ Entra ID }\n\nA[Password Spraying IP] -- Login Failure Account E --> D{ Entra ID }\n\nA[Password Spraying IP] -- Login Failure Account E --> D{ Entra ID }\n\nA[Password Spraying IP] == Login Attempt Account E ==> D{ Entra ID }\n\nD{ Entra ID } == \u00a0Entra ID Returns Code {{error.code}} ==> A\n\nclassDef orange fill:#f96,stroke:#333,stroke-width:2px\n\nclassDef blue fill:#32bedd,stroke:#333,stroke-width:2px\n\nclass D blue\n\nclass A orange\n\n```\n\n<style>\n\n/* Actions */\n\n.actions_list li {\n\ndisplay:inline!important;\n\nmargin-right: 45px!important;\n\nmargin-bottom: 15px!important;\n\n}\n\n.actions_list {\n\nlist-style: none!important;\n\nmargin: 0px!important;\n\npadding: 0px!important;\n\n}\n\n.actions_list img {\n\nheight:20px!important;\n\nmargin-bottom:-7px!important;\n\npadding-right:5px!important;\n\n}\n\n/* Tables */\n\n.MuiPaper-root.MuiPaper-elevation.MuiPaper-rounded.MuiPaper-elevation1.MuiTableContainer-root {\n\nbox-shadow:unset !important;\n\nwidth: fit-content !important;\n\n}\n\n/* General */\n\nh3 {\n\nborder-bottom: 2px solid #2d7dc9;\n\n/*border-bottom: 5px solid rgba(255, 255, 255, 0.12);*/\n\n/*color: #393939;*/\n\n}\n\n/* Visualization */\n\n.mermaid {\n\nbackground-color:#fff;\n\npadding:15px;\n\ntext-align: center;\n\n}\n\n/* Boites */\n\n.actor.actor-top {\n\nstroke: #393939 !important;\n\nfill: lightgrey !important;\n\n}\n\n/* T\u00eate du bonhomme */\n\n.actor-man circle {\n\nstroke: #393939 !important;\n\nfill: #28A745 !important;\n\n}\n\n/* Corps du bonhomme */\n\n.actor-man line {\n\nstroke: #393939 !important;\n\nfill: #393939 !important;\n\n}\n\n/* Lignes verticales */\n\n.actor-line {\n\nstroke: #393939 !important;\n\nfill: #393939 !important;\n\n}\n\n/* Description des fl\u00e8ches horizontales */\n\n.messageText {\n\nfill: #393939 !important;\n\nstroke: none;\n\n}\n\n/* T\u00eates de fl\u00e8ches */\n\nmarker#arrowhead path {\n\nfill: #DC3545 !important;\n\n}\n\n/* Texte en-dessous du bonhomme */\n\ntext.actor > tspan {\n\nfill: #393939 !important;\n\n}\n\n/* Fl\u00e8ches horizontales */\n\n.messageLine0, .messageLine1 {\n\nstroke-width: 1.5;\n\nstroke-dasharray: none;\n\nstroke: #393939 !important;\n\n}\n\n/* Texte dans boites */\n\n.actor-box {\n\nfont-weight: bold !important;\n\ncolor: #393939 !important;\n\n}\n\n/* Cacher le bonhomme du bas */\n\n.actor-bottom {\n\ndisplay:None;\n\n}\n\n</style>\n"
@@ -44,21 +44,15 @@ const CaseFolder = ({ case: _case, folder, name, step = -1, rootCaseId, pathPref
44
44
  const currentRootCaseId = rootCaseId || _case?.case_id;
45
45
  // Metadata for hit-type items
46
46
  useEffect(() => {
47
- tree.leaves
48
- ?.filter(leaf => leaf.type?.toLowerCase() === 'hit')
49
- .forEach(leaf => {
50
- dispatchApi(api.hit.get(leaf.id), { throwError: false }).then(hit => {
51
- if (!hit)
52
- return;
53
- setHitMetadata(prev => ({
54
- ...prev,
55
- [leaf.id]: {
56
- status: hit.howler?.status,
57
- escalation: hit.howler?.escalation,
58
- assessment: hit.howler?.assessment
59
- }
60
- }));
61
- });
47
+ const ids = tree.leaves?.filter(leaf => leaf.type?.toLowerCase() === 'hit').map(leaf => leaf.id);
48
+ if (!ids || ids.length < 1) {
49
+ return;
50
+ }
51
+ dispatchApi(api.search.hit.post({ query: `howler.id:(${ids.join(' OR ')})` }), { throwError: false }).then(result => {
52
+ if (result?.items?.length < 1) {
53
+ return;
54
+ }
55
+ setHitMetadata(Object.fromEntries(result.items.map(hit => [hit.howler.id, hit.howler])));
62
56
  });
63
57
  }, [tree.leaves, dispatchApi]);
64
58
  const getIconColor = (itemType, itemKey, leafId) => {
package/package.json CHANGED
@@ -101,7 +101,7 @@
101
101
  "internal-slot": "1.0.7"
102
102
  },
103
103
  "type": "module",
104
- "version": "2.17.0-dev.522",
104
+ "version": "2.17.0-dev.525",
105
105
  "exports": {
106
106
  "./i18n": "./i18n.js",
107
107
  "./index.css": "./index.css",