@cccsaurora/howler-ui 2.18.0 → 2.19.0-cases.1051
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/api/action/index.d.ts +5 -4
- package/api/action/index.js +8 -8
- package/api/analytic/index.d.ts +3 -2
- package/api/analytic/index.js +4 -4
- package/api/analytic/owner.d.ts +2 -1
- package/api/analytic/owner.js +2 -2
- package/api/analytic/rules.d.ts +2 -1
- package/api/analytic/rules.js +2 -2
- package/api/dossier/index.d.ts +4 -3
- package/api/dossier/index.js +6 -6
- package/api/hit/index.d.ts +3 -2
- package/api/hit/index.js +4 -4
- package/api/hit/labels.d.ts +3 -2
- package/api/hit/labels.js +4 -4
- package/api/hit/overwrite.d.ts +2 -1
- package/api/hit/overwrite.js +2 -2
- package/api/hit/transition.d.ts +2 -1
- package/api/hit/transition.js +2 -2
- package/api/index.d.ts +9 -4
- package/api/index.js +18 -10
- package/api/overview/index.d.ts +4 -3
- package/api/overview/index.js +6 -6
- package/api/search/case.d.ts +4 -0
- package/api/search/case.js +8 -0
- package/api/search/facet/hit.d.ts +1 -3
- package/api/search/facet/index.d.ts +3 -1
- package/api/search/index.d.ts +2 -1
- package/api/search/index.js +2 -1
- package/api/search/overview.d.ts +2 -2
- package/api/socket/index.d.ts +3 -0
- package/api/socket/index.js +6 -0
- package/api/socket/viewers.d.ts +2 -0
- package/api/socket/viewers.js +8 -0
- package/api/socket/viewers.test.js +44 -0
- package/api/template/index.d.ts +4 -3
- package/api/template/index.js +6 -6
- package/api/user/index.d.ts +2 -1
- package/api/user/index.js +2 -2
- package/api/v2/case/index.d.ts +9 -0
- package/api/v2/case/index.js +21 -0
- package/api/v2/case/items.d.ts +6 -0
- package/api/v2/case/items.js +18 -0
- package/api/v2/case/rules.d.ts +6 -0
- package/api/v2/case/rules.js +18 -0
- package/api/v2/index.d.ts +4 -0
- package/api/v2/index.js +6 -0
- package/api/v2/search/facet.d.ts +3 -0
- package/api/v2/search/facet.js +12 -0
- package/api/v2/search/index.d.ts +5 -0
- package/api/v2/search/index.js +24 -0
- package/api/view/index.d.ts +4 -3
- package/api/view/index.js +6 -6
- package/commons/components/leftnav/LeftNavDrawer.js +1 -1
- package/components/app/App.d.ts +1 -0
- package/components/app/App.js +64 -13
- package/components/app/hooks/useMatchers.d.ts +1 -1
- package/components/app/hooks/useMatchers.js +23 -11
- package/components/app/hooks/useMatchers.test.js +22 -22
- package/components/app/hooks/useTitle.js +5 -5
- package/components/app/providers/FavouritesProvider.js +2 -6
- package/components/app/providers/ModalProvider.d.ts +2 -0
- package/components/app/providers/ModalProvider.js +5 -1
- package/components/app/providers/ParameterProvider.d.ts +9 -2
- package/components/app/providers/ParameterProvider.js +165 -240
- package/components/app/providers/ParameterProvider.test.js +346 -94
- package/components/app/providers/RecordProvider.d.ts +23 -0
- package/components/app/providers/{HitProvider.js → RecordProvider.js} +42 -42
- package/components/app/providers/{HitSearchProvider.d.ts → RecordSearchProvider.d.ts} +6 -6
- package/components/app/providers/{HitSearchProvider.js → RecordSearchProvider.js} +12 -17
- package/components/app/providers/{HitSearchProvider.test.js → RecordSearchProvider.test.js} +52 -71
- package/components/app/providers/SearchResponseProvider.d.ts +21 -0
- package/components/app/providers/SearchResponseProvider.js +81 -0
- package/components/app/providers/SearchResponseProvider.test.d.ts +1 -0
- package/components/app/providers/SearchResponseProvider.test.js +406 -0
- package/components/app/providers/SocketProvider.d.ts +11 -2
- package/components/app/providers/SocketProvider.js +18 -5
- package/components/app/providers/UserListProvider.js +28 -8
- package/components/app/providers/ViewProvider.test.js +4 -1
- package/components/elements/ContextMenu.d.ts +56 -0
- package/components/elements/ContextMenu.js +109 -0
- package/components/elements/ContextMenu.test.d.ts +1 -0
- package/components/elements/ContextMenu.test.js +215 -0
- package/components/{routes/overviews/OverviewEditor.js → elements/MarkdownEditor.js} +3 -3
- package/components/elements/ObjectDetails.d.ts +6 -0
- package/components/elements/{hit/HitDetails.js → ObjectDetails.js} +17 -17
- package/components/elements/PluginTypography.d.ts +2 -1
- package/components/elements/PluginTypography.js +3 -2
- package/components/elements/UserList.d.ts +5 -2
- package/components/elements/UserList.js +18 -8
- package/components/elements/addons/buttons/CustomButton.test.d.ts +1 -0
- package/components/elements/addons/buttons/CustomButton.test.js +106 -0
- package/components/elements/addons/layout/FlexOne.test.d.ts +1 -0
- package/components/elements/addons/layout/FlexOne.test.js +30 -0
- package/components/elements/addons/lists/TuiListBase.js +4 -0
- package/components/elements/addons/lists/TuiListElement.js +6 -3
- package/components/elements/addons/lists/index.d.ts +1 -0
- package/components/elements/addons/search/SearchPagination.d.ts +2 -1
- package/components/elements/addons/search/SearchPagination.js +4 -4
- package/components/elements/addons/search/SearchPagination.test.d.ts +1 -0
- package/components/elements/addons/search/SearchPagination.test.js +80 -0
- package/components/elements/addons/search/SearchTotal.test.d.ts +1 -0
- package/components/elements/addons/search/SearchTotal.test.js +47 -0
- package/components/elements/addons/search/phrase/Phrase.js +1 -1
- package/components/elements/case/CaseCard.d.ts +12 -0
- package/components/elements/case/CaseCard.js +42 -0
- package/components/elements/case/CasePreview.d.ts +6 -0
- package/components/elements/case/CasePreview.js +17 -0
- package/components/elements/case/StatusIcon.d.ts +5 -0
- package/components/elements/case/StatusIcon.js +13 -0
- package/components/elements/display/ChipPopper.d.ts +1 -1
- package/components/elements/display/ChipPopper.js +6 -5
- package/components/elements/display/DocumentationButton.test.d.ts +1 -0
- package/components/elements/display/DocumentationButton.test.js +84 -0
- package/components/elements/display/DynamicTabs.test.d.ts +1 -0
- package/components/elements/display/DynamicTabs.test.js +93 -0
- package/components/elements/display/HowlerAvatar.js +2 -1
- package/components/elements/display/HowlerCard.js +1 -1
- package/components/elements/display/HowlerCard.test.d.ts +1 -0
- package/components/elements/display/HowlerCard.test.js +51 -0
- package/components/elements/display/Image.test.d.ts +1 -0
- package/components/elements/display/Image.test.js +79 -0
- package/components/elements/display/ItemManager.d.ts +2 -2
- package/components/elements/display/ItemManager.js +1 -1
- package/components/elements/display/Markdown.js +9 -2
- package/components/elements/display/Modal.js +2 -0
- package/components/elements/display/QueryResultText.test.d.ts +1 -0
- package/components/elements/display/QueryResultText.test.js +48 -0
- package/components/elements/display/TextDivider.test.d.ts +1 -0
- package/components/elements/display/TextDivider.test.js +43 -0
- package/components/elements/display/TypingIndicator.test.d.ts +1 -0
- package/components/elements/display/TypingIndicator.test.js +33 -0
- package/components/elements/display/modals/ConfirmDeleteModal.d.ts +4 -0
- package/components/elements/display/modals/ConfirmDeleteModal.js +4 -2
- package/components/elements/hit/HitActions.js +4 -4
- package/components/elements/hit/HitBanner.d.ts +1 -0
- package/components/elements/hit/HitBanner.js +34 -51
- package/components/elements/hit/HitCard.d.ts +2 -0
- package/components/elements/hit/HitCard.js +7 -7
- package/components/elements/hit/HitLabels.js +2 -2
- package/components/elements/hit/HitOutline.d.ts +1 -0
- package/components/elements/hit/HitOutline.js +3 -3
- package/components/elements/hit/{HitQuickSearch.d.ts → HitPreview.d.ts} +3 -3
- package/components/elements/hit/{HitQuickSearch.js → HitPreview.js} +10 -4
- package/components/elements/hit/HitSummary.d.ts +2 -1
- package/components/elements/hit/HitSummary.js +9 -7
- package/components/elements/hit/aggregate/HitGraph.js +8 -8
- package/components/elements/hit/elements/AnalyticLink.d.ts +9 -0
- package/components/elements/hit/elements/AnalyticLink.js +22 -0
- package/components/elements/hit/elements/Assigned.d.ts +2 -0
- package/components/elements/hit/elements/Assigned.js +21 -16
- package/components/elements/hit/elements/Assigned.test.d.ts +1 -0
- package/components/elements/hit/elements/Assigned.test.js +65 -0
- package/components/elements/hit/outlines/DefaultOutline.js +1 -1
- package/components/elements/hit/related/RelatedRecords.js +63 -0
- package/components/elements/observable/ObservableCard.d.ts +6 -0
- package/components/elements/observable/ObservableCard.js +22 -0
- package/components/elements/observable/ObservablePreview.d.ts +6 -0
- package/components/elements/observable/ObservablePreview.js +12 -0
- package/components/elements/{hit/HitComments.d.ts → record/RecordComments.d.ts} +5 -4
- package/components/elements/{hit/HitComments.js → record/RecordComments.js} +29 -28
- package/components/{routes/hits/search/HitContextMenu.d.ts → elements/record/RecordContextMenu.d.ts} +3 -3
- package/components/elements/record/RecordContextMenu.js +268 -0
- package/components/elements/record/RecordContextMenu.test.d.ts +1 -0
- package/components/{routes/hits/search/HitContextMenu.test.js → elements/record/RecordContextMenu.test.js} +190 -39
- package/components/elements/record/RecordRelated.d.ts +7 -0
- package/components/elements/record/RecordRelated.js +34 -0
- package/components/elements/{hit/HitWorklog.d.ts → record/RecordWorklog.d.ts} +4 -3
- package/components/elements/{hit/HitWorklog.js → record/RecordWorklog.js} +15 -13
- package/components/elements/view/ViewTitle.d.ts +1 -0
- package/components/elements/view/ViewTitle.js +9 -2
- package/components/hooks/useHitActions.d.ts +1 -1
- package/components/hooks/useHitActions.js +4 -4
- package/components/hooks/useMyApi.d.ts +1 -1
- package/components/hooks/useMyPreferences.js +12 -2
- package/components/hooks/useMySearch.js +2 -2
- package/components/hooks/useMySitemap.js +4 -1
- package/components/hooks/useMyTheme.js +9 -2
- package/components/hooks/{useHitSelection.d.ts → useRecordSelection.d.ts} +2 -2
- package/components/hooks/{useHitSelection.js → useRecordSelection.js} +12 -33
- package/components/hooks/useRelatedRecords.d.ts +13 -0
- package/components/hooks/useRelatedRecords.js +32 -0
- package/components/routes/403.d.ts +3 -0
- package/components/routes/403.js +10 -0
- package/components/routes/403.test.d.ts +1 -0
- package/components/routes/403.test.js +27 -0
- package/components/routes/404.test.d.ts +1 -0
- package/components/routes/404.test.js +26 -0
- package/components/routes/ErrorBoundary.test.d.ts +1 -0
- package/components/routes/ErrorBoundary.test.js +43 -0
- package/components/routes/ErrorOccured.test.d.ts +1 -0
- package/components/routes/ErrorOccured.test.js +35 -0
- package/components/routes/Logout.test.d.ts +1 -0
- package/components/routes/Logout.test.js +59 -0
- package/components/routes/action/edit/ActionEditor.js +3 -3
- package/components/routes/action/useMyActionFunctions.js +9 -3
- package/components/routes/action/view/ActionDetails.js +15 -2
- package/components/routes/action/view/ActionSearch.js +32 -20
- package/components/routes/action/view/markdown/integrations.en.md.js +1 -1
- package/components/routes/action/view/markdown/integrations.fr.md.js +1 -1
- package/components/routes/advanced/QueryBuilder.js +1 -1
- package/components/routes/advanced/QueryEditor.js +3 -3
- package/components/routes/advanced/historyCompletionProvider.js +3 -3
- package/components/routes/analytics/AnalyticDetails.js +12 -8
- package/components/routes/analytics/AnalyticSearch.js +7 -7
- package/components/routes/cases/CaseViewer.d.ts +2 -0
- package/components/routes/cases/CaseViewer.js +44 -0
- package/components/routes/cases/CaseViewer.test.d.ts +1 -0
- package/components/routes/cases/CaseViewer.test.js +133 -0
- package/components/routes/cases/Cases.d.ts +2 -0
- package/components/routes/cases/Cases.js +147 -0
- package/components/routes/cases/constants.d.ts +6 -0
- package/components/routes/cases/constants.js +6 -0
- package/components/routes/cases/detail/AlertPanel.d.ts +6 -0
- package/components/routes/cases/detail/AlertPanel.js +33 -0
- package/components/routes/cases/detail/CaseAssets.d.ts +11 -0
- package/components/routes/cases/detail/CaseAssets.js +104 -0
- package/components/routes/cases/detail/CaseAssets.test.d.ts +1 -0
- package/components/routes/cases/detail/CaseAssets.test.js +167 -0
- package/components/routes/cases/detail/CaseDashboard.d.ts +7 -0
- package/components/routes/cases/detail/CaseDashboard.js +66 -0
- package/components/routes/cases/detail/CaseDetails.d.ts +6 -0
- package/components/routes/cases/detail/CaseDetails.js +70 -0
- package/components/routes/cases/detail/CaseOverview.d.ts +7 -0
- package/components/routes/cases/detail/CaseOverview.js +43 -0
- package/components/routes/cases/detail/CaseRules.d.ts +7 -0
- package/components/routes/cases/detail/CaseRules.js +57 -0
- package/components/routes/cases/detail/CaseRules.test.d.ts +1 -0
- package/components/routes/cases/detail/CaseRules.test.js +221 -0
- package/components/routes/cases/detail/CaseSidebar.d.ts +8 -0
- package/components/routes/cases/detail/CaseSidebar.js +107 -0
- package/components/routes/cases/detail/CaseSidebar.test.d.ts +1 -0
- package/components/routes/cases/detail/CaseSidebar.test.js +266 -0
- package/components/routes/cases/detail/CaseTask.d.ts +11 -0
- package/components/routes/cases/detail/CaseTask.js +66 -0
- package/components/routes/cases/detail/CaseTimeline.d.ts +12 -0
- package/components/routes/cases/detail/CaseTimeline.js +106 -0
- package/components/routes/cases/detail/CaseTimeline.test.d.ts +1 -0
- package/components/routes/cases/detail/CaseTimeline.test.js +320 -0
- package/components/routes/cases/detail/CreateRuleDialog.d.ts +9 -0
- package/components/routes/cases/detail/CreateRuleDialog.js +163 -0
- package/components/routes/cases/detail/CreateRuleDialog.test.d.ts +1 -0
- package/components/routes/cases/detail/CreateRuleDialog.test.js +259 -0
- package/components/routes/cases/detail/ItemPage.d.ts +6 -0
- package/components/routes/cases/detail/ItemPage.js +95 -0
- package/components/routes/cases/detail/RelatedCasePanel.d.ts +6 -0
- package/components/routes/cases/detail/RelatedCasePanel.js +34 -0
- package/components/routes/cases/detail/TaskPanel.d.ts +7 -0
- package/components/routes/cases/detail/TaskPanel.js +52 -0
- package/components/routes/cases/detail/aggregates/CaseAggregate.d.ts +11 -0
- package/components/routes/cases/detail/aggregates/CaseAggregate.js +24 -0
- package/components/routes/cases/detail/aggregates/SourceAggregate.d.ts +6 -0
- package/components/routes/cases/detail/aggregates/SourceAggregate.js +26 -0
- package/components/routes/cases/detail/assets/Asset.d.ts +14 -0
- package/components/routes/cases/detail/assets/Asset.js +12 -0
- package/components/routes/cases/detail/assets/Asset.test.d.ts +1 -0
- package/components/routes/cases/detail/assets/Asset.test.js +72 -0
- package/components/routes/cases/detail/sidebar/CaseFolder.d.ts +20 -0
- package/components/routes/cases/detail/sidebar/CaseFolder.js +83 -0
- package/components/routes/cases/detail/sidebar/CaseFolder.test.d.ts +1 -0
- package/components/routes/cases/detail/sidebar/CaseFolder.test.js +295 -0
- package/components/routes/cases/detail/sidebar/CaseFolderContextMenu.d.ts +34 -0
- package/components/routes/cases/detail/sidebar/CaseFolderContextMenu.js +103 -0
- package/components/routes/cases/detail/sidebar/CaseFolderContextMenu.test.d.ts +1 -0
- package/components/routes/cases/detail/sidebar/CaseFolderContextMenu.test.js +363 -0
- package/components/routes/cases/detail/sidebar/FolderEntry.d.ts +25 -0
- package/components/routes/cases/detail/sidebar/FolderEntry.js +88 -0
- package/components/routes/cases/detail/sidebar/FolderEntry.test.d.ts +1 -0
- package/components/routes/cases/detail/sidebar/FolderEntry.test.js +206 -0
- package/components/routes/cases/detail/sidebar/RootDropZone.d.ts +5 -0
- package/components/routes/cases/detail/sidebar/RootDropZone.js +33 -0
- package/components/routes/cases/detail/sidebar/types.d.ts +9 -0
- package/components/routes/cases/detail/sidebar/utils.d.ts +3 -0
- package/components/routes/cases/detail/sidebar/utils.js +29 -0
- package/components/routes/cases/detail/sidebar/utils.test.d.ts +1 -0
- package/components/routes/cases/detail/sidebar/utils.test.js +82 -0
- package/components/routes/cases/hooks/useCase.d.ts +13 -0
- package/components/routes/cases/hooks/useCase.js +69 -0
- package/components/routes/cases/hooks/useCase.test.d.ts +1 -0
- package/components/routes/cases/hooks/useCase.test.js +141 -0
- package/components/routes/cases/modals/AddToCaseModal.d.ts +7 -0
- package/components/routes/cases/modals/AddToCaseModal.js +59 -0
- package/components/routes/cases/modals/AddToCaseModal.test.d.ts +1 -0
- package/components/routes/cases/modals/AddToCaseModal.test.js +313 -0
- package/components/routes/cases/modals/CaseRecordRow.d.ts +9 -0
- package/components/routes/cases/modals/CaseRecordRow.js +15 -0
- package/components/routes/cases/modals/CreateCaseModal.d.ts +7 -0
- package/components/routes/cases/modals/CreateCaseModal.js +55 -0
- package/components/routes/cases/modals/CreateCaseModal.test.d.ts +1 -0
- package/components/routes/cases/modals/CreateCaseModal.test.js +358 -0
- package/components/routes/cases/modals/RenameItemModal.d.ts +9 -0
- package/components/routes/cases/modals/RenameItemModal.js +48 -0
- package/components/routes/cases/modals/ResolveModal.d.ts +7 -0
- package/components/routes/cases/modals/ResolveModal.js +116 -0
- package/components/routes/cases/modals/ResolveModal.test.d.ts +1 -0
- package/components/routes/cases/modals/ResolveModal.test.js +454 -0
- package/components/routes/cases/modals/hooks.d.ts +7 -0
- package/components/routes/cases/modals/hooks.js +44 -0
- package/components/routes/cases/modals/types.d.ts +5 -0
- package/components/routes/cases/search/CaseAssigneeFilter.d.ts +6 -0
- package/components/routes/cases/search/CaseAssigneeFilter.js +33 -0
- package/components/routes/cases/search/CaseAssigneeFilter.test.d.ts +1 -0
- package/components/routes/cases/search/CaseAssigneeFilter.test.js +127 -0
- package/components/routes/cases/search/CaseDateFilter.d.ts +13 -0
- package/components/routes/cases/search/CaseDateFilter.js +26 -0
- package/components/routes/cases/search/CaseDateFilter.test.d.ts +1 -0
- package/components/routes/cases/search/CaseDateFilter.test.js +115 -0
- package/components/routes/cases/search/CaseStatusFilter.d.ts +6 -0
- package/components/routes/cases/search/CaseStatusFilter.js +13 -0
- package/components/routes/cases/search/CaseStatusFilter.test.d.ts +1 -0
- package/components/routes/cases/search/CaseStatusFilter.test.js +86 -0
- package/components/routes/dossiers/DossierEditor.js +2 -2
- package/components/routes/dossiers/DossierEditor.test.js +1 -1
- package/components/routes/dossiers/Dossiers.js +25 -19
- package/components/routes/help/ActionIntroductionDocumentation.js +1 -1
- package/components/routes/help/ApiDocumentation.js +1 -1
- package/components/routes/help/HitBannerDocumentation.js +1 -0
- package/components/routes/help/HitDocumentation.js +1 -3
- package/components/routes/help/markdown/en/client.md.js +1 -1
- package/components/routes/help/markdown/en/retention.md.js +1 -1
- package/components/routes/help/markdown/fr/client.md.js +1 -1
- package/components/routes/help/markdown/fr/retention.md.js +1 -1
- package/components/routes/hits/search/InformationPane.d.ts +1 -0
- package/components/routes/hits/search/InformationPane.js +50 -63
- package/components/routes/hits/search/LayoutSettings.js +3 -3
- package/components/routes/hits/search/QuerySettings.js +2 -1
- package/components/routes/hits/search/QuerySettings.test.js +14 -9
- package/components/routes/hits/search/{HitBrowser.js → RecordBrowser.js} +9 -9
- package/components/routes/hits/search/{HitQuery.d.ts → RecordQuery.d.ts} +2 -2
- package/components/routes/hits/search/{HitQuery.js → RecordQuery.js} +6 -6
- package/components/routes/hits/search/SearchPane.js +26 -49
- package/components/routes/hits/search/ViewLink.js +3 -3
- package/components/routes/hits/search/ViewLink.test.js +8 -8
- package/components/routes/hits/search/grid/AddColumnModal.js +5 -4
- package/components/routes/hits/search/grid/EnhancedCell.d.ts +2 -1
- package/components/routes/hits/search/grid/EnhancedCell.js +2 -2
- package/components/routes/hits/search/grid/HitGrid.js +20 -18
- package/components/routes/hits/search/grid/{HitRow.d.ts → RecordRow.d.ts} +3 -2
- package/components/routes/hits/search/grid/{HitRow.js → RecordRow.js} +10 -8
- package/components/routes/hits/search/shared/CustomSpan.js +7 -7
- package/components/routes/hits/search/shared/CustomSpan.test.d.ts +1 -0
- package/components/routes/hits/search/shared/CustomSpan.test.js +170 -0
- package/components/routes/hits/search/shared/IndexPicker.d.ts +2 -0
- package/components/routes/hits/search/shared/IndexPicker.js +20 -0
- package/components/routes/hits/view/HitViewer.js +12 -13
- package/components/routes/home/AddNewCard.js +1 -1
- package/components/routes/home/AddNewCard.test.d.ts +1 -0
- package/components/routes/home/AddNewCard.test.js +86 -0
- package/components/routes/home/ViewCard.js +47 -41
- package/components/routes/home/ViewRefresh.test.d.ts +1 -0
- package/components/routes/home/ViewRefresh.test.js +79 -0
- package/components/routes/observables/ObservableViewer.d.ts +7 -0
- package/components/routes/observables/ObservableViewer.js +27 -0
- package/components/routes/overviews/OverviewCard.test.d.ts +1 -0
- package/components/routes/overviews/OverviewCard.test.js +108 -0
- package/components/routes/overviews/OverviewViewer.js +18 -10
- package/components/routes/overviews/Overviews.js +25 -19
- package/components/routes/overviews/template/en.md.js +1 -1
- package/components/routes/overviews/template/fr.md.js +1 -1
- package/components/routes/settings/LocalSection.js +2 -1
- package/components/routes/settings/SettingsSection.test.d.ts +1 -0
- package/components/routes/settings/SettingsSection.test.js +19 -0
- package/components/routes/templates/TemplateCard.d.ts +3 -1
- package/components/routes/templates/TemplateCard.js +8 -4
- package/components/routes/templates/TemplateCard.test.d.ts +1 -0
- package/components/routes/templates/TemplateCard.test.js +115 -0
- package/components/routes/templates/TemplateViewer.js +62 -16
- package/components/routes/templates/Templates.js +35 -13
- package/components/routes/views/ViewComposer.js +46 -19
- package/components/routes/views/Views.js +21 -14
- package/locales/en/translation.json +146 -8
- package/locales/fr/translation.json +144 -8
- package/models/WithMetadata.d.ts +2 -1
- package/models/entities/generated/ApiType.d.ts +1 -1
- package/models/entities/generated/AttachmentsFile.d.ts +12 -0
- package/models/entities/generated/Case.d.ts +28 -0
- package/models/entities/generated/DestinationOriginal.d.ts +19 -0
- package/models/entities/generated/EmailAttachment.d.ts +8 -0
- package/models/entities/generated/EmailParent.d.ts +19 -0
- package/models/entities/generated/Enrichments.d.ts +7 -0
- package/models/entities/generated/EnrichmentsIndicator.d.ts +21 -0
- package/models/entities/generated/Hit.d.ts +2 -0
- package/models/entities/generated/Howler.d.ts +1 -5
- package/models/entities/generated/HttpResponse.d.ts +11 -0
- package/models/entities/generated/Item.d.ts +9 -0
- package/models/entities/generated/Observable.d.ts +85 -0
- package/models/entities/generated/ObservableCloud.d.ts +20 -0
- package/models/entities/generated/ObservableDestination.d.ts +23 -0
- package/models/entities/generated/ObservableEmail.d.ts +30 -0
- package/models/entities/generated/ObservableFile.d.ts +36 -0
- package/models/entities/generated/ObservableHowler.d.ts +42 -0
- package/models/entities/generated/ObservableHttp.d.ts +11 -0
- package/models/entities/generated/ObservableObserver.d.ts +21 -0
- package/models/entities/generated/ObservableOrganization.d.ts +7 -0
- package/models/entities/generated/ObservableProcess.d.ts +34 -0
- package/models/entities/generated/ObservableSource.d.ts +23 -0
- package/models/entities/generated/ObservableThreat.d.ts +21 -0
- package/models/entities/generated/ObservableTls.d.ts +12 -0
- package/models/entities/generated/ObserverIngress.d.ts +9 -0
- package/models/entities/generated/Rule.d.ts +6 -9
- package/models/entities/generated/Task.d.ts +10 -0
- package/models/entities/generated/Threat.d.ts +2 -2
- package/models/entities/generated/{Enrichment.d.ts → ThreatEnrichment.d.ts} +1 -1
- package/models/entities/generated/UserUser.d.ts +2 -0
- package/models/entities/generated/View.d.ts +1 -0
- package/models/socket/CaseUpdate.d.ts +5 -0
- package/models/socket/ViewersUpdate.d.ts +4 -0
- package/package.json +147 -132
- package/plugins/clue/components/ClueTypography.js +2 -2
- package/plugins/clue/utils.d.ts +2 -1
- package/rest/FetchClient.test.d.ts +1 -0
- package/rest/FetchClient.test.js +81 -0
- package/setupTests.js +5 -0
- package/tests/mocks.d.ts +11 -1
- package/tests/mocks.js +12 -7
- package/tests/server-handlers.js +6 -1
- package/tests/utils.d.ts +4 -0
- package/tests/utils.js +20 -0
- package/utils/Throttler.test.d.ts +1 -0
- package/utils/Throttler.test.js +135 -0
- package/utils/actionUtils.test.d.ts +1 -0
- package/utils/actionUtils.test.js +140 -0
- package/utils/constants.d.ts +5 -3
- package/utils/constants.js +7 -0
- package/utils/hitFunctions.d.ts +2 -1
- package/utils/hitFunctions.js +4 -4
- package/utils/hitFunctions.test.d.ts +1 -0
- package/utils/hitFunctions.test.js +52 -0
- package/utils/localStorage.test.d.ts +1 -0
- package/utils/localStorage.test.js +96 -0
- package/utils/menuUtils.js +1 -1
- package/utils/menuUtils.test.d.ts +1 -0
- package/utils/menuUtils.test.js +198 -0
- package/utils/sessionStorage.test.d.ts +1 -0
- package/utils/sessionStorage.test.js +81 -0
- package/utils/socketUtils.d.ts +14 -0
- package/utils/socketUtils.js +17 -1
- package/utils/socketUtils.test.d.ts +1 -0
- package/utils/socketUtils.test.js +59 -0
- package/utils/stringUtils.test.d.ts +1 -0
- package/utils/stringUtils.test.js +159 -0
- package/utils/typeUtils.d.ts +7 -0
- package/utils/typeUtils.js +27 -0
- package/utils/utils.test.d.ts +1 -0
- package/utils/utils.test.js +292 -0
- package/utils/viewUtils.js +3 -0
- package/utils/viewUtils.test.d.ts +1 -0
- package/utils/viewUtils.test.js +45 -0
- package/utils/xsrf.test.d.ts +1 -0
- package/utils/xsrf.test.js +41 -0
- package/components/app/providers/HitProvider.d.ts +0 -22
- package/components/elements/display/icons/BundleButton.d.ts +0 -6
- package/components/elements/display/icons/BundleButton.js +0 -32
- package/components/elements/hit/HitRelated.d.ts +0 -6
- package/components/elements/hit/HitRelated.js +0 -7
- package/components/routes/help/BundleDocumentation.d.ts +0 -3
- package/components/routes/help/BundleDocumentation.js +0 -12
- package/components/routes/help/markdown/en/bundles.md.js +0 -1
- package/components/routes/help/markdown/fr/bundles.md.js +0 -1
- package/components/routes/hits/search/BundleParentMenu.d.ts +0 -6
- package/components/routes/hits/search/BundleParentMenu.js +0 -32
- package/components/routes/hits/search/BundleScroller.d.ts +0 -2
- package/components/routes/hits/search/BundleScroller.js +0 -6
- package/components/routes/hits/search/HitContextMenu.js +0 -229
- /package/{components/app/providers/HitSearchProvider.test.d.ts → api/socket/viewers.test.d.ts} +0 -0
- /package/components/{routes/hits/search/HitContextMenu.test.d.ts → app/providers/RecordSearchProvider.test.d.ts} +0 -0
- /package/components/{routes/overviews/OverviewEditor.d.ts → elements/MarkdownEditor.d.ts} +0 -0
- /package/components/elements/hit/{HitDetails.d.ts → related/RelatedRecords.d.ts} +0 -0
- /package/components/routes/hits/search/{HitBrowser.d.ts → RecordBrowser.d.ts} +0 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as items from '@cccsaurora/howler-ui/api/v2/case/items';
|
|
2
|
+
import * as rules from '@cccsaurora/howler-ui/api/v2/case/rules';
|
|
3
|
+
import type { Case } from '@cccsaurora/howler-ui/models/entities/generated/Case';
|
|
4
|
+
export declare const uri: (id?: string) => string;
|
|
5
|
+
export declare const get: (id: string) => Promise<Case>;
|
|
6
|
+
export declare const post: (newData: Partial<Case>) => Promise<Case>;
|
|
7
|
+
export declare const put: (id: string, _case: Partial<Case>) => Promise<Case>;
|
|
8
|
+
export declare const del: (id: string) => Promise<void>;
|
|
9
|
+
export { items, rules };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// eslint-disable-next-line import/no-cycle
|
|
2
|
+
import { hdelete, hget, hpost, hput, joinAllUri, joinUri } from '@cccsaurora/howler-ui/api';
|
|
3
|
+
import { uri as parentUri } from '@cccsaurora/howler-ui/api/v2';
|
|
4
|
+
import * as items from '@cccsaurora/howler-ui/api/v2/case/items';
|
|
5
|
+
import * as rules from '@cccsaurora/howler-ui/api/v2/case/rules';
|
|
6
|
+
export const uri = (id) => {
|
|
7
|
+
return id ? joinAllUri(parentUri(), 'case', id) : joinUri(parentUri(), 'case');
|
|
8
|
+
};
|
|
9
|
+
export const get = (id) => {
|
|
10
|
+
return hget(uri(id));
|
|
11
|
+
};
|
|
12
|
+
export const post = (newData) => {
|
|
13
|
+
return hpost(uri(), newData);
|
|
14
|
+
};
|
|
15
|
+
export const put = (id, _case) => {
|
|
16
|
+
return hput(uri(id), _case);
|
|
17
|
+
};
|
|
18
|
+
export const del = (id) => {
|
|
19
|
+
return hdelete(uri(id));
|
|
20
|
+
};
|
|
21
|
+
export { items, rules };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Case } from '@cccsaurora/howler-ui/models/entities/generated/Case';
|
|
2
|
+
import type { Item } from '@cccsaurora/howler-ui/models/entities/generated/Item';
|
|
3
|
+
export declare const uri: (id: string) => string;
|
|
4
|
+
export declare const post: (id: string, newData: Item) => Promise<Case>;
|
|
5
|
+
export declare const del: (id: string, values: string | string[]) => Promise<Case>;
|
|
6
|
+
export declare const put: (id: string, value: string, newPath: string) => Promise<Case>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// eslint-disable-next-line import/no-cycle
|
|
2
|
+
import { hdelete, hpost, hput, joinUri } from '@cccsaurora/howler-ui/api';
|
|
3
|
+
import { uri as parentUri } from '@cccsaurora/howler-ui/api/v2/case';
|
|
4
|
+
export const uri = (id) => {
|
|
5
|
+
return joinUri(parentUri(id), 'items');
|
|
6
|
+
};
|
|
7
|
+
export const post = (id, newData) => {
|
|
8
|
+
return hpost(uri(id), newData);
|
|
9
|
+
};
|
|
10
|
+
export const del = (id, values) => {
|
|
11
|
+
if (!Array.isArray(values)) {
|
|
12
|
+
values = [values];
|
|
13
|
+
}
|
|
14
|
+
return hdelete(uri(id), { values });
|
|
15
|
+
};
|
|
16
|
+
export const put = (id, value, newPath) => {
|
|
17
|
+
return hput(uri(id), { value, new_path: newPath });
|
|
18
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Case } from '@cccsaurora/howler-ui/models/entities/generated/Case';
|
|
2
|
+
import type { Rule } from '@cccsaurora/howler-ui/models/entities/generated/Rule';
|
|
3
|
+
export declare const uri: (caseId: string, ruleId?: string) => string;
|
|
4
|
+
export declare const post: (caseId: string, ruleData: Partial<Rule>) => Promise<Case>;
|
|
5
|
+
export declare const del: (caseId: string, ruleId: string) => Promise<Case>;
|
|
6
|
+
export declare const put: (caseId: string, ruleId: string, data: Partial<Rule>) => Promise<Case>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// eslint-disable-next-line import/no-cycle
|
|
2
|
+
import { hdelete, hpost, hput, joinAllUri } from '@cccsaurora/howler-ui/api';
|
|
3
|
+
import { uri as parentUri } from '@cccsaurora/howler-ui/api/v2/case';
|
|
4
|
+
export const uri = (caseId, ruleId) => {
|
|
5
|
+
if (ruleId) {
|
|
6
|
+
return joinAllUri(parentUri(caseId), 'rules', ruleId);
|
|
7
|
+
}
|
|
8
|
+
return joinAllUri(parentUri(caseId), 'rules');
|
|
9
|
+
};
|
|
10
|
+
export const post = (caseId, ruleData) => {
|
|
11
|
+
return hpost(uri(caseId), ruleData);
|
|
12
|
+
};
|
|
13
|
+
export const del = (caseId, ruleId) => {
|
|
14
|
+
return hdelete(uri(caseId, ruleId));
|
|
15
|
+
};
|
|
16
|
+
export const put = (caseId, ruleId, data) => {
|
|
17
|
+
return hput(uri(caseId, ruleId), data);
|
|
18
|
+
};
|
package/api/v2/index.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { HowlerFacetSearchRequest, HowlerFacetSearchResponse } from '@cccsaurora/howler-ui/api/search/facet';
|
|
2
|
+
export declare const uri: (indexes: string[]) => string;
|
|
3
|
+
export declare const post: (indexes: string | string[], request?: HowlerFacetSearchRequest) => Promise<HowlerFacetSearchResponse>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// eslint-disable-next-line import/no-cycle
|
|
2
|
+
import { hpost, joinAllUri } from '@cccsaurora/howler-ui/api';
|
|
3
|
+
import { uri as parentUri } from '@cccsaurora/howler-ui/api/v2';
|
|
4
|
+
export const uri = (indexes) => {
|
|
5
|
+
return joinAllUri(parentUri(), 'search', 'facet', indexes.join(','));
|
|
6
|
+
};
|
|
7
|
+
export const post = (indexes, request) => {
|
|
8
|
+
if (typeof indexes === 'string') {
|
|
9
|
+
indexes = indexes.split(',');
|
|
10
|
+
}
|
|
11
|
+
return hpost(uri(indexes), { ...(request || {}), query: request?.query || 'howler.id:*' });
|
|
12
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { HowlerSearchRequest, HowlerSearchResponse } from '@cccsaurora/howler-ui/api/search';
|
|
2
|
+
import * as facet from './facet';
|
|
3
|
+
export declare const uri: (indexes: string[]) => string;
|
|
4
|
+
export declare const post: <T = any>(indexes: string | string[], request?: HowlerSearchRequest) => Promise<HowlerSearchResponse<T>>;
|
|
5
|
+
export { facet };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// eslint-disable-next-line import/no-cycle
|
|
2
|
+
import { hpost, joinAllUri } from '@cccsaurora/howler-ui/api';
|
|
3
|
+
import { uri as parentUri } from '@cccsaurora/howler-ui/api/v2';
|
|
4
|
+
import { identity, isNil } from 'lodash-es';
|
|
5
|
+
import * as facet from './facet';
|
|
6
|
+
export const uri = (indexes) => {
|
|
7
|
+
return joinAllUri(parentUri(), 'search', indexes.join(','));
|
|
8
|
+
};
|
|
9
|
+
export const post = (indexes, request) => {
|
|
10
|
+
if (isNil(indexes)) {
|
|
11
|
+
throw new Error('Indexes cannot be null or undefined.');
|
|
12
|
+
}
|
|
13
|
+
if (typeof indexes === 'string') {
|
|
14
|
+
indexes = indexes.split(',').filter(identity);
|
|
15
|
+
}
|
|
16
|
+
if (indexes.some(index => !['hit', 'observable', 'case'].includes(index))) {
|
|
17
|
+
throw new Error('Only hit, case, and observable indexes should be used currently.');
|
|
18
|
+
}
|
|
19
|
+
if (indexes.length < 1) {
|
|
20
|
+
throw new Error('indexes must have length of at least 1.');
|
|
21
|
+
}
|
|
22
|
+
return hpost(uri(indexes), { ...(request || {}), query: request?.query || 'howler.id:*' });
|
|
23
|
+
};
|
|
24
|
+
export { facet };
|
package/api/view/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { type HowlerRefreshParam } from '@cccsaurora/howler-ui/api';
|
|
1
2
|
import * as favourite from '@cccsaurora/howler-ui/api/view/favourite';
|
|
2
3
|
import type { View } from '@cccsaurora/howler-ui/models/entities/generated/View';
|
|
3
4
|
export declare const uri: (id?: string) => string;
|
|
4
5
|
export declare const get: () => Promise<View[]>;
|
|
5
|
-
export declare const post: (newData: Partial<View
|
|
6
|
-
export declare const put: (id: string, partialView: Partial<Omit<View, "view_id"
|
|
7
|
-
export declare const del: (id: string) => Promise<void>;
|
|
6
|
+
export declare const post: (newData: Partial<View>, refresh?: HowlerRefreshParam) => Promise<View>;
|
|
7
|
+
export declare const put: (id: string, partialView: Partial<Omit<View, "view_id">>, refresh?: HowlerRefreshParam) => Promise<View>;
|
|
8
|
+
export declare const del: (id: string, refresh?: HowlerRefreshParam) => Promise<void>;
|
|
8
9
|
export { favourite };
|
package/api/view/index.js
CHANGED
|
@@ -6,13 +6,13 @@ export const uri = (id) => {
|
|
|
6
6
|
export const get = () => {
|
|
7
7
|
return hget(uri());
|
|
8
8
|
};
|
|
9
|
-
export const post = (newData) => {
|
|
10
|
-
return hpost(uri(), newData);
|
|
9
|
+
export const post = (newData, refresh) => {
|
|
10
|
+
return hpost(uri(), newData, undefined, refresh ? new URLSearchParams({ refresh }) : undefined);
|
|
11
11
|
};
|
|
12
|
-
export const put = (id, partialView) => {
|
|
13
|
-
return hput(uri(id), partialView);
|
|
12
|
+
export const put = (id, partialView, refresh) => {
|
|
13
|
+
return hput(uri(id), partialView, undefined, refresh ? new URLSearchParams({ refresh }) : undefined);
|
|
14
14
|
};
|
|
15
|
-
export const del = (id) => {
|
|
16
|
-
return hdelete(uri(id));
|
|
15
|
+
export const del = (id, refresh) => {
|
|
16
|
+
return hdelete(uri(id), undefined, undefined, refresh ? new URLSearchParams({ refresh }) : undefined);
|
|
17
17
|
};
|
|
18
18
|
export { favourite };
|
|
@@ -75,7 +75,7 @@ const LeftNavDrawer = () => {
|
|
|
75
75
|
}
|
|
76
76
|
}, children: _jsx(AppName, {}) }), !isTopLayout && _jsx(Divider, {})] }));
|
|
77
77
|
const hide = (_jsx(List, { disablePadding: true, children: _jsxs(ListItemButton, { onClick: leftnav.toggle, children: [_jsx(ListItemIcon, { children: leftnav.open ? _jsx(ChevronLeftIcon, {}) : _jsx(ChevronRightIcon, {}) }), _jsx(ListItemText, { primary: t('drawer.collapse') })] }, "chevron") }));
|
|
78
|
-
return (_jsx(ClickAwayListener, { mouseEvent: "onMouseDown", touchEvent: "onTouchStart", onClickAway: onCloseDrawerIfOpen, children: _jsxs(StyledDrawer, {
|
|
78
|
+
return (_jsx(ClickAwayListener, { mouseEvent: "onMouseDown", touchEvent: "onTouchStart", onClickAway: onCloseDrawerIfOpen, children: _jsxs(StyledDrawer, { variant: "permanent", style: { height: '100%' }, width: preferences.leftnav.width, open: leftnav.open, children: [leftnav.open ? (header) : (_jsx(Tooltip, { title: preferences.appName, "aria-label": preferences.appName, placement: "right", children: header })), _jsx(List, { disablePadding: true, children: leftnav.elements.map((e, i) => {
|
|
79
79
|
if (e.type === 'item') {
|
|
80
80
|
const item = e.element;
|
|
81
81
|
return _jsx(LeftNavItem, { item: item, onClick: isSmDown && onCloseDrawerIfOpen }, item.id);
|
package/components/app/App.d.ts
CHANGED
package/components/app/App.js
CHANGED
|
@@ -13,6 +13,7 @@ import useMyTheme from '@cccsaurora/howler-ui/components/hooks/useMyTheme';
|
|
|
13
13
|
import useMyUser from '@cccsaurora/howler-ui/components/hooks/useMyUser';
|
|
14
14
|
import LoginScreen from '@cccsaurora/howler-ui/components/logins/Login';
|
|
15
15
|
import useLogin from '@cccsaurora/howler-ui/components/logins/hooks/useLogin';
|
|
16
|
+
import PermissionDeniedPage from '@cccsaurora/howler-ui/components/routes/403';
|
|
16
17
|
import NotFoundPage from '@cccsaurora/howler-ui/components/routes/404';
|
|
17
18
|
import ErrorBoundary from '@cccsaurora/howler-ui/components/routes/ErrorBoundary';
|
|
18
19
|
import Logout from '@cccsaurora/howler-ui/components/routes/Logout';
|
|
@@ -25,6 +26,13 @@ import UserSearchProvider from '@cccsaurora/howler-ui/components/routes/admin/us
|
|
|
25
26
|
import QueryBuilder from '@cccsaurora/howler-ui/components/routes/advanced/QueryBuilder';
|
|
26
27
|
import AnalyticDetails from '@cccsaurora/howler-ui/components/routes/analytics/AnalyticDetails';
|
|
27
28
|
import AnalyticSearch from '@cccsaurora/howler-ui/components/routes/analytics/AnalyticSearch';
|
|
29
|
+
import CaseViewer from '@cccsaurora/howler-ui/components/routes/cases/CaseViewer';
|
|
30
|
+
import Cases from '@cccsaurora/howler-ui/components/routes/cases/Cases';
|
|
31
|
+
import CaseAssets from '@cccsaurora/howler-ui/components/routes/cases/detail/CaseAssets';
|
|
32
|
+
import CaseDashboard from '@cccsaurora/howler-ui/components/routes/cases/detail/CaseDashboard';
|
|
33
|
+
import CaseRules from '@cccsaurora/howler-ui/components/routes/cases/detail/CaseRules';
|
|
34
|
+
import CaseTimeline from '@cccsaurora/howler-ui/components/routes/cases/detail/CaseTimeline';
|
|
35
|
+
import ItemPage from '@cccsaurora/howler-ui/components/routes/cases/detail/ItemPage';
|
|
28
36
|
import DossierEditor from '@cccsaurora/howler-ui/components/routes/dossiers/DossierEditor';
|
|
29
37
|
import Dossiers from '@cccsaurora/howler-ui/components/routes/dossiers/Dossiers';
|
|
30
38
|
import ActionDocumentation from '@cccsaurora/howler-ui/components/routes/help/ActionDocumentation';
|
|
@@ -39,7 +47,7 @@ import RetentionDocumentation from '@cccsaurora/howler-ui/components/routes/help
|
|
|
39
47
|
import SearchDocumentation from '@cccsaurora/howler-ui/components/routes/help/SearchDocumentation';
|
|
40
48
|
import TemplateDocumentation from '@cccsaurora/howler-ui/components/routes/help/TemplateDocumentation';
|
|
41
49
|
import ViewDocumentation from '@cccsaurora/howler-ui/components/routes/help/ViewDocumentation';
|
|
42
|
-
import
|
|
50
|
+
import RecordBrowser from '@cccsaurora/howler-ui/components/routes/hits/search/RecordBrowser';
|
|
43
51
|
import HitViewer from '@cccsaurora/howler-ui/components/routes/hits/view/HitViewer';
|
|
44
52
|
import Home from '@cccsaurora/howler-ui/components/routes/home';
|
|
45
53
|
import OverviewViewer from '@cccsaurora/howler-ui/components/routes/overviews/OverviewViewer';
|
|
@@ -50,14 +58,16 @@ import Templates from '@cccsaurora/howler-ui/components/routes/templates/Templat
|
|
|
50
58
|
import ViewComposer from '@cccsaurora/howler-ui/components/routes/views/ViewComposer';
|
|
51
59
|
import Views from '@cccsaurora/howler-ui/components/routes/views/Views';
|
|
52
60
|
import dayjs from 'dayjs';
|
|
61
|
+
import 'dayjs/locale/fr-ca';
|
|
53
62
|
import duration from 'dayjs/plugin/duration';
|
|
54
63
|
import localizedFormat from 'dayjs/plugin/localizedFormat';
|
|
64
|
+
import minMax from 'dayjs/plugin/minMax';
|
|
55
65
|
import relativeTime from 'dayjs/plugin/relativeTime';
|
|
56
66
|
import utc from 'dayjs/plugin/utc';
|
|
57
67
|
import i18n from '@cccsaurora/howler-ui/i18n';
|
|
58
68
|
import * as monaco from 'monaco-editor';
|
|
59
69
|
import howlerPluginStore from '@cccsaurora/howler-ui/plugins/store';
|
|
60
|
-
import { useContext, useEffect, useMemo } from 'react';
|
|
70
|
+
import { useCallback, useContext, useEffect, useMemo } from 'react';
|
|
61
71
|
import { I18nextProvider } from 'react-i18next';
|
|
62
72
|
import { PluginProvider, usePluginStore } from 'react-pluggable';
|
|
63
73
|
import { createBrowserRouter, Outlet, RouterProvider, useLocation, useNavigate } from 'react-router-dom';
|
|
@@ -71,11 +81,11 @@ import AvatarProvider from './providers/AvatarProvider';
|
|
|
71
81
|
import CustomPluginProvider from './providers/CustomPluginProvider';
|
|
72
82
|
import FavouriteProvider from './providers/FavouritesProvider';
|
|
73
83
|
import FieldProvider from './providers/FieldProvider';
|
|
74
|
-
import HitProvider from './providers/HitProvider';
|
|
75
84
|
import LocalStorageProvider from './providers/LocalStorageProvider';
|
|
76
85
|
import ModalProvider from './providers/ModalProvider';
|
|
77
86
|
import OverviewProvider from './providers/OverviewProvider';
|
|
78
87
|
import ParameterProvider from './providers/ParameterProvider';
|
|
88
|
+
import RecordProvider from './providers/RecordProvider';
|
|
79
89
|
import SocketProvider from './providers/SocketProvider';
|
|
80
90
|
import UserListProvider from './providers/UserListProvider';
|
|
81
91
|
import ViewProvider from './providers/ViewProvider';
|
|
@@ -83,13 +93,15 @@ dayjs.extend(utc);
|
|
|
83
93
|
dayjs.extend(duration);
|
|
84
94
|
dayjs.extend(relativeTime);
|
|
85
95
|
dayjs.extend(localizedFormat);
|
|
96
|
+
dayjs.extend(minMax);
|
|
97
|
+
dayjs.locale(i18n.language === 'en' ? 'en' : 'fr-ca');
|
|
86
98
|
loader.config({ monaco });
|
|
87
|
-
const RoleRoute = ({
|
|
99
|
+
const RoleRoute = ({ roles }) => {
|
|
88
100
|
const appUser = useAppUser();
|
|
89
|
-
if (appUser.user?.roles?.includes(role)) {
|
|
101
|
+
if (roles.some((role) => appUser.user?.roles?.includes(role))) {
|
|
90
102
|
return _jsx(Outlet, {});
|
|
91
103
|
}
|
|
92
|
-
return _jsx(
|
|
104
|
+
return _jsx(PermissionDeniedPage, {});
|
|
93
105
|
};
|
|
94
106
|
// Your application's initialization flow.
|
|
95
107
|
const MyApp = () => {
|
|
@@ -104,6 +116,13 @@ const MyApp = () => {
|
|
|
104
116
|
const { setItems } = useAppSwitcher();
|
|
105
117
|
const { get, set, remove } = useMyLocalStorage();
|
|
106
118
|
const pluginStore = usePluginStore();
|
|
119
|
+
const onLanguageChange = useCallback((language) => dayjs.locale(language === 'en' ? 'en' : 'fr-ca'), []);
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
i18n.on('languageChanged', onLanguageChange);
|
|
122
|
+
return () => {
|
|
123
|
+
i18n.off('languageChanged', onLanguageChange);
|
|
124
|
+
};
|
|
125
|
+
}, [onLanguageChange]);
|
|
107
126
|
// Simulate app loading time...
|
|
108
127
|
// e.g. fetching initial app data, etc.
|
|
109
128
|
useEffect(() => {
|
|
@@ -148,7 +167,7 @@ const MyAppProvider = ({ children }) => {
|
|
|
148
167
|
const mySitemap = useMySitemap();
|
|
149
168
|
const myUser = useMyUser();
|
|
150
169
|
const mySearch = useMySearch();
|
|
151
|
-
return (_jsx(ErrorBoundary, { children: _jsx(AppProvider, { preferences: myPreferences, theme: myTheme, sitemap: mySitemap, user: myUser, search: mySearch, children: _jsx(CustomPluginProvider, { children: _jsx(ErrorBoundary, { children: _jsx(ErrorBoundary, { children: _jsx(ViewProvider, { children: _jsx(AvatarProvider, { children: _jsx(ModalProvider, { children: _jsx(FieldProvider, { children: _jsx(LocalStorageProvider, { children: _jsx(SocketProvider, { children: _jsx(
|
|
170
|
+
return (_jsx(ErrorBoundary, { children: _jsx(AppProvider, { preferences: myPreferences, theme: myTheme, sitemap: mySitemap, user: myUser, search: mySearch, children: _jsx(CustomPluginProvider, { children: _jsx(ErrorBoundary, { children: _jsx(ErrorBoundary, { children: _jsx(ViewProvider, { children: _jsx(AvatarProvider, { children: _jsx(ModalProvider, { children: _jsx(FieldProvider, { children: _jsx(LocalStorageProvider, { children: _jsx(SocketProvider, { children: _jsx(RecordProvider, { children: _jsx(OverviewProvider, { children: _jsx(AnalyticProvider, { children: _jsx(FavouriteProvider, { children: _jsx(UserListProvider, { children: children }) }) }) }) }) }) }) }) }) }) }) }) }) }) }) }));
|
|
152
171
|
};
|
|
153
172
|
const AppProviderWrapper = () => {
|
|
154
173
|
return (_jsx(I18nextProvider, { i18n: i18n, defaultNS: "translation", children: _jsx(ApiConfigProvider, { children: _jsx(PluginProvider, { pluginStore: howlerPluginStore.pluginStore, children: _jsx(AppBarProvider, { children: _jsxs(MyAppProvider, { children: [_jsx(MyApp, {}), _jsx(Modal, {})] }) }) }) }) }));
|
|
@@ -172,19 +191,45 @@ const createRouter = () => createBrowserRouter([
|
|
|
172
191
|
},
|
|
173
192
|
{
|
|
174
193
|
path: 'hits',
|
|
175
|
-
element: _jsx(
|
|
194
|
+
element: _jsx(RecordBrowser, {})
|
|
176
195
|
},
|
|
177
196
|
{
|
|
178
197
|
path: 'search',
|
|
179
|
-
element: _jsx(
|
|
198
|
+
element: _jsx(RecordBrowser, {})
|
|
180
199
|
},
|
|
181
200
|
{
|
|
182
201
|
path: 'hits/:id',
|
|
183
202
|
element: _jsx(HitViewer, {})
|
|
184
203
|
},
|
|
185
204
|
{
|
|
186
|
-
path: '
|
|
187
|
-
element: _jsx(
|
|
205
|
+
path: 'cases',
|
|
206
|
+
element: _jsx(Cases, {})
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
path: 'cases/:id',
|
|
210
|
+
element: (_jsx(ParameterProvider, { children: _jsx(CaseViewer, {}) })),
|
|
211
|
+
children: [
|
|
212
|
+
{
|
|
213
|
+
index: true,
|
|
214
|
+
element: _jsx(CaseDashboard, {})
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
path: 'assets',
|
|
218
|
+
element: _jsx(CaseAssets, {})
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
path: 'timeline',
|
|
222
|
+
element: _jsx(CaseTimeline, {})
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
path: 'rules',
|
|
226
|
+
element: _jsx(CaseRules, {})
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
path: '*',
|
|
230
|
+
element: _jsx(ItemPage, {})
|
|
231
|
+
}
|
|
232
|
+
]
|
|
188
233
|
},
|
|
189
234
|
{
|
|
190
235
|
path: 'templates',
|
|
@@ -224,7 +269,7 @@ const createRouter = () => createBrowserRouter([
|
|
|
224
269
|
},
|
|
225
270
|
{
|
|
226
271
|
path: 'views/:id',
|
|
227
|
-
element: _jsx(
|
|
272
|
+
element: _jsx(RecordBrowser, {})
|
|
228
273
|
},
|
|
229
274
|
{
|
|
230
275
|
path: 'views/:id/edit',
|
|
@@ -304,7 +349,13 @@ const createRouter = () => createBrowserRouter([
|
|
|
304
349
|
},
|
|
305
350
|
{
|
|
306
351
|
path: 'action',
|
|
307
|
-
element: _jsx(RoleRoute, {
|
|
352
|
+
element: (_jsx(RoleRoute, { roles: [
|
|
353
|
+
'admin',
|
|
354
|
+
'automation_basic',
|
|
355
|
+
'automation_advanced',
|
|
356
|
+
'actionrunner_basic',
|
|
357
|
+
'actionrunner_advanced'
|
|
358
|
+
] })),
|
|
308
359
|
children: [
|
|
309
360
|
{
|
|
310
361
|
index: true,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Hit } from '@cccsaurora/howler-ui/models/entities/generated/Hit';
|
|
2
2
|
import type { WithMetadata } from '@cccsaurora/howler-ui/models/WithMetadata';
|
|
3
|
-
declare const useMatchers: () => {
|
|
3
|
+
declare const useMatchers: (lazy?: boolean) => {
|
|
4
4
|
getMatchingDossiers: (hit: WithMetadata<Hit>) => Promise<import("../../../models/entities/generated/Dossier").Dossier[]>;
|
|
5
5
|
getMatchingOverview: (hit: WithMetadata<Hit>) => Promise<import("../../../models/entities/generated/Overview").Overview>;
|
|
6
6
|
getMatchingTemplate: (hit: WithMetadata<Hit>) => Promise<import("../../../models/entities/generated/Template").Template>;
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import { has } from 'lodash-es';
|
|
3
3
|
import { useCallback } from 'react';
|
|
4
4
|
import { useContextSelector } from 'use-context-selector';
|
|
5
|
-
import {
|
|
6
|
-
const useMatchers = () => {
|
|
7
|
-
const
|
|
5
|
+
import { RecordContext } from '../providers/RecordProvider';
|
|
6
|
+
const useMatchers = (lazy = false) => {
|
|
7
|
+
const getRecord = useContextSelector(RecordContext, ctx => ctx.getRecord);
|
|
8
8
|
const getMatchingTemplate = useCallback(async (hit) => {
|
|
9
9
|
if (!hit) {
|
|
10
10
|
return null;
|
|
@@ -12,15 +12,18 @@ const useMatchers = () => {
|
|
|
12
12
|
if (has(hit, '__template')) {
|
|
13
13
|
return hit.__template;
|
|
14
14
|
}
|
|
15
|
+
if (lazy) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
15
18
|
// This is a fallback in case metadata is not included. In most cases templates are shown, the template metadata
|
|
16
19
|
// should also exist
|
|
17
20
|
try {
|
|
18
|
-
return (await
|
|
21
|
+
return (await getRecord(hit.howler.id, true)).__template;
|
|
19
22
|
}
|
|
20
23
|
catch (e) {
|
|
21
24
|
return null;
|
|
22
25
|
}
|
|
23
|
-
}, [
|
|
26
|
+
}, [getRecord, lazy]);
|
|
24
27
|
const getMatchingOverview = useCallback(async (hit) => {
|
|
25
28
|
if (!hit) {
|
|
26
29
|
return null;
|
|
@@ -28,15 +31,18 @@ const useMatchers = () => {
|
|
|
28
31
|
if (has(hit, '__overview')) {
|
|
29
32
|
return hit.__overview;
|
|
30
33
|
}
|
|
34
|
+
if (lazy) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
31
37
|
// This is a fallback in case metadata is not included. In most cases templates are shown, the template metadata
|
|
32
38
|
// should also exist
|
|
33
39
|
try {
|
|
34
|
-
return (await
|
|
40
|
+
return (await getRecord(hit.howler.id, true)).__overview;
|
|
35
41
|
}
|
|
36
42
|
catch (e) {
|
|
37
43
|
return null;
|
|
38
44
|
}
|
|
39
|
-
}, [
|
|
45
|
+
}, [getRecord, lazy]);
|
|
40
46
|
const getMatchingDossiers = useCallback(async (hit) => {
|
|
41
47
|
if (!hit) {
|
|
42
48
|
return null;
|
|
@@ -44,15 +50,18 @@ const useMatchers = () => {
|
|
|
44
50
|
if (has(hit, '__dossiers')) {
|
|
45
51
|
return hit.__dossiers;
|
|
46
52
|
}
|
|
53
|
+
if (lazy) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
47
56
|
// This is a fallback in case metadata is not included. In most cases templates are shown, the template metadata
|
|
48
57
|
// should also exist
|
|
49
58
|
try {
|
|
50
|
-
return (await
|
|
59
|
+
return (await getRecord(hit.howler.id, true)).__dossiers ?? [];
|
|
51
60
|
}
|
|
52
61
|
catch (e) {
|
|
53
62
|
return [];
|
|
54
63
|
}
|
|
55
|
-
}, [
|
|
64
|
+
}, [getRecord, lazy]);
|
|
56
65
|
const getMatchingAnalytic = useCallback(async (hit) => {
|
|
57
66
|
if (!hit) {
|
|
58
67
|
return null;
|
|
@@ -60,14 +69,17 @@ const useMatchers = () => {
|
|
|
60
69
|
if (has(hit, '__analytic')) {
|
|
61
70
|
return hit.__analytic;
|
|
62
71
|
}
|
|
72
|
+
if (lazy) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
63
75
|
// This is a fallback in case metadata is not included.
|
|
64
76
|
try {
|
|
65
|
-
return (await
|
|
77
|
+
return (await getRecord(hit.howler.id, true)).__analytic;
|
|
66
78
|
}
|
|
67
79
|
catch (e) {
|
|
68
80
|
return null;
|
|
69
81
|
}
|
|
70
|
-
}, [
|
|
82
|
+
}, [getRecord, lazy]);
|
|
71
83
|
return {
|
|
72
84
|
getMatchingDossiers,
|
|
73
85
|
getMatchingOverview,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { renderHook } from '@testing-library/react';
|
|
2
2
|
import { useContextSelector } from 'use-context-selector';
|
|
3
3
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
4
|
-
import {
|
|
4
|
+
import { RecordContext } from '../providers/RecordProvider';
|
|
5
5
|
import useMatchers from './useMatchers';
|
|
6
6
|
// Mock the useContextSelector hook
|
|
7
7
|
vi.mock('use-context-selector', () => ({
|
|
@@ -40,14 +40,14 @@ const mockHitWithMetadata = {
|
|
|
40
40
|
__overview: mockOverview,
|
|
41
41
|
__dossiers: mockDossiers
|
|
42
42
|
};
|
|
43
|
-
const
|
|
43
|
+
const mockGetRecord = vi.fn();
|
|
44
44
|
describe('useMatchers', () => {
|
|
45
45
|
beforeEach(() => {
|
|
46
46
|
vi.clearAllMocks();
|
|
47
47
|
// Mock useContextSelector to return our mock getHit function
|
|
48
48
|
useContextSelector.mockImplementation((context, selector) => {
|
|
49
|
-
if (context ===
|
|
50
|
-
return selector({
|
|
49
|
+
if (context === RecordContext) {
|
|
50
|
+
return selector({ getRecord: mockGetRecord });
|
|
51
51
|
}
|
|
52
52
|
return null;
|
|
53
53
|
});
|
|
@@ -69,25 +69,25 @@ describe('useMatchers', () => {
|
|
|
69
69
|
const { result } = renderHook(() => useMatchers());
|
|
70
70
|
const template = await result.current.getMatchingTemplate(mockHitWithMetadata);
|
|
71
71
|
expect(template).toBe(mockTemplate);
|
|
72
|
-
expect(
|
|
72
|
+
expect(mockGetRecord).not.toHaveBeenCalled();
|
|
73
73
|
});
|
|
74
74
|
it('should fetch hit with metadata when template is not present', async () => {
|
|
75
75
|
const { has } = await import('lodash-es');
|
|
76
76
|
has.mockReturnValue(false);
|
|
77
77
|
const hitWithFetchedMetadata = { ...mockHit, __template: mockTemplate };
|
|
78
|
-
|
|
78
|
+
mockGetRecord.mockResolvedValue(hitWithFetchedMetadata);
|
|
79
79
|
const { result } = renderHook(() => useMatchers());
|
|
80
80
|
const template = await result.current.getMatchingTemplate(mockHit);
|
|
81
81
|
expect(template).toBe(mockTemplate);
|
|
82
|
-
expect(
|
|
82
|
+
expect(mockGetRecord).toHaveBeenCalledWith('test-hit-id', true);
|
|
83
83
|
});
|
|
84
84
|
it('should handle getHit rejection gracefully', async () => {
|
|
85
85
|
const { has } = await import('lodash-es');
|
|
86
86
|
has.mockReturnValue(false);
|
|
87
|
-
|
|
87
|
+
mockGetRecord.mockRejectedValue(new Error('Failed to fetch hit'));
|
|
88
88
|
const { result } = renderHook(() => useMatchers());
|
|
89
89
|
await expect(result.current.getMatchingTemplate(mockHit)).resolves.toBeNull();
|
|
90
|
-
expect(
|
|
90
|
+
expect(mockGetRecord).toHaveBeenCalledWith('test-hit-id', true);
|
|
91
91
|
});
|
|
92
92
|
});
|
|
93
93
|
describe('getMatchingOverview', () => {
|
|
@@ -107,25 +107,25 @@ describe('useMatchers', () => {
|
|
|
107
107
|
const { result } = renderHook(() => useMatchers());
|
|
108
108
|
const overview = await result.current.getMatchingOverview(mockHitWithMetadata);
|
|
109
109
|
expect(overview).toBe(mockOverview);
|
|
110
|
-
expect(
|
|
110
|
+
expect(mockGetRecord).not.toHaveBeenCalled();
|
|
111
111
|
});
|
|
112
112
|
it('should fetch hit with metadata when overview is not present', async () => {
|
|
113
113
|
const { has } = await import('lodash-es');
|
|
114
114
|
has.mockReturnValue(false);
|
|
115
115
|
const hitWithFetchedMetadata = { ...mockHit, __overview: mockOverview };
|
|
116
|
-
|
|
116
|
+
mockGetRecord.mockResolvedValue(hitWithFetchedMetadata);
|
|
117
117
|
const { result } = renderHook(() => useMatchers());
|
|
118
118
|
const overview = await result.current.getMatchingOverview(mockHit);
|
|
119
119
|
expect(overview).toBe(mockOverview);
|
|
120
|
-
expect(
|
|
120
|
+
expect(mockGetRecord).toHaveBeenCalledWith('test-hit-id', true);
|
|
121
121
|
});
|
|
122
122
|
it('should handle getHit rejection gracefully', async () => {
|
|
123
123
|
const { has } = await import('lodash-es');
|
|
124
124
|
has.mockReturnValue(false);
|
|
125
|
-
|
|
125
|
+
mockGetRecord.mockRejectedValue(new Error('Failed to fetch hit'));
|
|
126
126
|
const { result } = renderHook(() => useMatchers());
|
|
127
127
|
await expect(result.current.getMatchingOverview(mockHit)).resolves.toBeNull();
|
|
128
|
-
expect(
|
|
128
|
+
expect(mockGetRecord).toHaveBeenCalledWith('test-hit-id', true);
|
|
129
129
|
});
|
|
130
130
|
});
|
|
131
131
|
describe('getMatchingDossiers', () => {
|
|
@@ -145,25 +145,25 @@ describe('useMatchers', () => {
|
|
|
145
145
|
const { result } = renderHook(() => useMatchers());
|
|
146
146
|
const dossiers = await result.current.getMatchingDossiers(mockHitWithMetadata);
|
|
147
147
|
expect(dossiers).toBe(mockDossiers);
|
|
148
|
-
expect(
|
|
148
|
+
expect(mockGetRecord).not.toHaveBeenCalled();
|
|
149
149
|
});
|
|
150
150
|
it('should fetch hit with metadata when dossiers are not present', async () => {
|
|
151
151
|
const { has } = await import('lodash-es');
|
|
152
152
|
has.mockReturnValue(false);
|
|
153
153
|
const hitWithFetchedMetadata = { ...mockHit, __dossiers: mockDossiers };
|
|
154
|
-
|
|
154
|
+
mockGetRecord.mockResolvedValue(hitWithFetchedMetadata);
|
|
155
155
|
const { result } = renderHook(() => useMatchers());
|
|
156
156
|
const dossiers = await result.current.getMatchingDossiers(mockHit);
|
|
157
157
|
expect(dossiers).toBe(mockDossiers);
|
|
158
|
-
expect(
|
|
158
|
+
expect(mockGetRecord).toHaveBeenCalledWith('test-hit-id', true);
|
|
159
159
|
});
|
|
160
160
|
it('should handle getHit rejection gracefully', async () => {
|
|
161
161
|
const { has } = await import('lodash-es');
|
|
162
162
|
has.mockReturnValue(false);
|
|
163
|
-
|
|
163
|
+
mockGetRecord.mockRejectedValue(new Error('Failed to fetch hit'));
|
|
164
164
|
const { result } = renderHook(() => useMatchers());
|
|
165
165
|
await expect(result.current.getMatchingDossiers(mockHit)).resolves.toEqual([]);
|
|
166
|
-
expect(
|
|
166
|
+
expect(mockGetRecord).toHaveBeenCalledWith('test-hit-id', true);
|
|
167
167
|
});
|
|
168
168
|
});
|
|
169
169
|
describe('integration tests', () => {
|
|
@@ -177,7 +177,7 @@ describe('useMatchers', () => {
|
|
|
177
177
|
...mockHit,
|
|
178
178
|
__template: mockTemplate
|
|
179
179
|
};
|
|
180
|
-
|
|
180
|
+
mockGetRecord.mockResolvedValue({
|
|
181
181
|
...mockHit,
|
|
182
182
|
__overview: mockOverview,
|
|
183
183
|
__dossiers: mockDossiers
|
|
@@ -200,7 +200,7 @@ describe('useMatchers', () => {
|
|
|
200
200
|
it('should handle empty or undefined metadata gracefully', async () => {
|
|
201
201
|
const { has } = await import('lodash-es');
|
|
202
202
|
has.mockReturnValue(false);
|
|
203
|
-
|
|
203
|
+
mockGetRecord.mockResolvedValue({
|
|
204
204
|
...mockHit,
|
|
205
205
|
__template: undefined,
|
|
206
206
|
__overview: null,
|
|
@@ -213,7 +213,7 @@ describe('useMatchers', () => {
|
|
|
213
213
|
expect(template).toBeUndefined();
|
|
214
214
|
expect(overview).toBeNull();
|
|
215
215
|
expect(dossiers).toEqual([]);
|
|
216
|
-
expect(
|
|
216
|
+
expect(mockGetRecord).toHaveBeenCalledTimes(3);
|
|
217
217
|
});
|
|
218
218
|
it('should maintain referential equality of returned functions', () => {
|
|
219
219
|
const { result, rerender } = renderHook(() => useMatchers());
|