@cccsaurora/howler-ui 3.1.0-dev.1466 → 3.1.0-dev.1493

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.
@@ -28,16 +28,15 @@ import RecordRelated from '@cccsaurora/howler-ui/components/elements/record/Reco
28
28
  import RecordWorklog from '@cccsaurora/howler-ui/components/elements/record/RecordWorklog';
29
29
  import useMyUserList from '@cccsaurora/howler-ui/components/hooks/useMyUserList';
30
30
  import ErrorBoundary from '@cccsaurora/howler-ui/components/routes/ErrorBoundary';
31
- import howlerPluginStore from '@cccsaurora/howler-ui/plugins/store';
32
31
  import { useContext, useEffect, useMemo, useState } from 'react';
33
32
  import { useTranslation } from 'react-i18next';
34
- import { usePluginStore } from 'react-pluggable';
35
33
  import { useLocation } from 'react-router-dom';
36
34
  import { useContextSelector } from 'use-context-selector';
37
35
  import { getUserList } from '@cccsaurora/howler-ui/utils/recordFunctions';
38
36
  import { validateRegex } from '@cccsaurora/howler-ui/utils/stringUtils';
39
37
  import { isHit } from '@cccsaurora/howler-ui/utils/typeUtils';
40
38
  import { tryParse } from '@cccsaurora/howler-ui/utils/utils';
39
+ import PluginViewing from '../shared/PluginViewing';
41
40
  import LeadRenderer from '../view/LeadRenderer';
42
41
  const InformationPane = ({ onClose, selected: _selected }) => {
43
42
  const { t, i18n } = useTranslation();
@@ -46,7 +45,6 @@ const InformationPane = ({ onClose, selected: _selected }) => {
46
45
  const { emit, open } = useContext(SocketContext);
47
46
  const { getMatchingOverview, getMatchingDossiers, getMatchingAnalytic } = useMatchers();
48
47
  const selected = useContextSelector(ParameterContext, ctx => ctx?.selected) ?? _selected;
49
- const { executeFunction } = usePluginStore();
50
48
  const getRecord = useContextSelector(RecordContext, ctx => ctx.getRecord);
51
49
  const [userIds, setUserIds] = useState(new Set());
52
50
  const [analytic, setAnalytic] = useState();
@@ -59,14 +57,6 @@ const InformationPane = ({ onClose, selected: _selected }) => {
59
57
  const dossiers = useMemo(() => _dossiers ?? [], [_dossiers]);
60
58
  const users = useMyUserList(userIds);
61
59
  const record = useContextSelector(RecordContext, ctx => ctx.records[selected]);
62
- useEffect(() => {
63
- if (!selected) {
64
- return;
65
- }
66
- howlerPluginStore.plugins.forEach(plugin => {
67
- executeFunction(`${plugin}.on`, 'viewing');
68
- });
69
- }, [executeFunction, selected]);
70
60
  useEffect(() => {
71
61
  if (!selected) {
72
62
  return;
@@ -154,7 +144,7 @@ const InformationPane = ({ onClose, selected: _selected }) => {
154
144
  }[tab]?.();
155
145
  }, [dossiers, filter, record, loading, tab, users]);
156
146
  const hasError = useMemo(() => !validateRegex(filter), [filter]);
157
- return (_jsxs(VSBox, { top: 10, sx: { height: '100%', flex: 1 }, children: [_jsxs(Stack, { direction: "column", flex: 1, sx: { overflowY: 'auto', flexGrow: 1 }, position: "relative", spacing: 1, ml: 2, children: [_jsxs(Stack, { direction: "row", alignItems: "center", spacing: 0.5, flexShrink: 0, pr: 2, children: [_jsx(FlexOne, {}), onClose && !location.pathname.startsWith('/bundles') && (_jsx(TuiIconButton, { size: "small", onClick: onClose, tooltip: t('hit.panel.details.exit'), children: _jsx(Clear, {}) })), _jsx(SocketBadge, { size: "small" }), analytic && (_jsx(TuiIconButton, { size: "small", tooltip: t('analytic.open'), disabled: !analytic || loading, route: `/analytics/${analytic.analytic_id}`, children: _jsx(QueryStats, {}) })), !!record && (_jsx(TuiIconButton, { tooltip: t(`${record.__index}.open`), href: `/${record.__index}s/${selected}`, disabled: !record || loading, size: "small", target: "_blank", children: _jsx(OpenInNew, {}) }))] }), isHit(record) && (_jsxs(_Fragment, { children: [_jsx(Box, { pr: 2, children: _jsx(HitBanner, { layout: HitLayout.DENSE, hit: record }) }), !loading && (_jsxs(_Fragment, { children: [_jsx(HitOutline, { hit: record, layout: HitLayout.DENSE, forceAllFields: true }), _jsx(HitLabels, { hit: record })] })), _jsx(HitLinks, { hit: record, analytic: analytic, dossiers: dossiers })] })), loading && (_jsxs(_Fragment, { children: [_jsx(Skeleton, { variant: "rounded", height: 152 }), _jsx(Skeleton, { height: 124 })] })), _jsxs(VSBoxHeader, { ml: -1, mr: -1, pb: 1, sx: { top: '0px' }, children: [_jsxs(Tabs, { value: tab === 'overview' && !hasOverview ? 'details' : tab, sx: {
147
+ return (_jsxs(VSBox, { top: 10, sx: { height: '100%', flex: 1 }, children: [isHit(record) && _jsx(PluginViewing, { hit: record }), _jsxs(Stack, { direction: "column", flex: 1, sx: { overflowY: 'auto', flexGrow: 1 }, position: "relative", spacing: 1, ml: 2, children: [_jsxs(Stack, { direction: "row", alignItems: "center", spacing: 0.5, flexShrink: 0, pr: 2, children: [_jsx(FlexOne, {}), onClose && !location.pathname.startsWith('/bundles') && (_jsx(TuiIconButton, { size: "small", onClick: onClose, tooltip: t('hit.panel.details.exit'), children: _jsx(Clear, {}) })), _jsx(SocketBadge, { size: "small" }), analytic && (_jsx(TuiIconButton, { size: "small", tooltip: t('analytic.open'), disabled: !analytic || loading, route: `/analytics/${analytic.analytic_id}`, children: _jsx(QueryStats, {}) })), !!record && (_jsx(TuiIconButton, { tooltip: t(`${record.__index}.open`), href: `/${record.__index}s/${selected}`, disabled: !record || loading, size: "small", target: "_blank", children: _jsx(OpenInNew, {}) }))] }), isHit(record) && (_jsxs(_Fragment, { children: [_jsx(Box, { pr: 2, children: _jsx(HitBanner, { layout: HitLayout.DENSE, hit: record }) }), !loading && (_jsxs(_Fragment, { children: [_jsx(HitOutline, { hit: record, layout: HitLayout.DENSE, forceAllFields: true }), _jsx(HitLabels, { hit: record })] })), _jsx(HitLinks, { hit: record, analytic: analytic, dossiers: dossiers })] })), loading && (_jsxs(_Fragment, { children: [_jsx(Skeleton, { variant: "rounded", height: 152 }), _jsx(Skeleton, { height: 124 })] })), _jsxs(VSBoxHeader, { ml: -1, mr: -1, pb: 1, sx: { top: '0px' }, children: [_jsxs(Tabs, { value: tab === 'overview' && !hasOverview ? 'details' : tab, sx: {
158
148
  display: 'flex',
159
149
  flexDirection: 'row',
160
150
  pr: 2,
@@ -0,0 +1,10 @@
1
+ import type { Hit } from '@cccsaurora/howler-ui/models/entities/generated/Hit';
2
+ import { type FC } from 'react';
3
+ /**
4
+ * Plugin viewing handlers must be rendered because plugin implementations may use React hooks.
5
+ * Memoization prevents them from running again when the surrounding hit view rerenders unchanged.
6
+ */
7
+ declare const PluginViewing: FC<{
8
+ hit: Hit;
9
+ }>;
10
+ export default PluginViewing;
@@ -0,0 +1,13 @@
1
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
+ import howlerPluginStore from '@cccsaurora/howler-ui/plugins/store';
3
+ import { memo } from 'react';
4
+ import { usePluginStore } from 'react-pluggable';
5
+ /**
6
+ * Plugin viewing handlers must be rendered because plugin implementations may use React hooks.
7
+ * Memoization prevents them from running again when the surrounding hit view rerenders unchanged.
8
+ */
9
+ const PluginViewing = memo(({ hit }) => {
10
+ const pluginStore = usePluginStore();
11
+ return _jsx(_Fragment, { children: howlerPluginStore.plugins.map(plugin => pluginStore.executeFunction(`${plugin}.on`, 'viewing', hit)) });
12
+ });
13
+ export default PluginViewing;
@@ -23,15 +23,14 @@ import RecordRelated from '@cccsaurora/howler-ui/components/elements/record/Reco
23
23
  import RecordWorklog from '@cccsaurora/howler-ui/components/elements/record/RecordWorklog';
24
24
  import { useMyLocalStorageItem } from '@cccsaurora/howler-ui/components/hooks/useMyLocalStorage';
25
25
  import useMyUserList from '@cccsaurora/howler-ui/components/hooks/useMyUserList';
26
- import howlerPluginStore from '@cccsaurora/howler-ui/plugins/store';
27
26
  import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
28
27
  import { useTranslation } from 'react-i18next';
29
- import { usePluginStore } from 'react-pluggable';
30
28
  import { useNavigate, useParams } from 'react-router-dom';
31
29
  import { useContextSelector } from 'use-context-selector';
32
30
  import { StorageKey } from '@cccsaurora/howler-ui/utils/constants';
33
31
  import { getUserList } from '@cccsaurora/howler-ui/utils/recordFunctions';
34
32
  import { tryParse } from '@cccsaurora/howler-ui/utils/utils';
33
+ import PluginViewing from '../shared/PluginViewing';
35
34
  import LeadRenderer from './LeadRenderer';
36
35
  export var Orientation;
37
36
  (function (Orientation) {
@@ -47,7 +46,6 @@ const HitViewer = () => {
47
46
  const [orientation, setOrientation] = useMyLocalStorageItem(StorageKey.VIEWER_ORIENTATION, Orientation.VERTICAL);
48
47
  const { getMatchingOverview, getMatchingDossiers, getMatchingAnalytic } = useMatchers();
49
48
  const { emit, open } = useContext(SocketContext);
50
- const { executeFunction } = usePluginStore();
51
49
  const getHit = useContextSelector(RecordContext, ctx => ctx.getRecord);
52
50
  const hit = useContextSelector(RecordContext, ctx => ctx.records[params.id]);
53
51
  const [userIds, setUserIds] = useState(new Set());
@@ -76,14 +74,6 @@ const HitViewer = () => {
76
74
  setOrientation(Orientation.HORIZONTAL);
77
75
  }
78
76
  }, [isUnderLg, setOrientation]);
79
- useEffect(() => {
80
- if (!hit) {
81
- return;
82
- }
83
- howlerPluginStore.plugins.forEach(plugin => {
84
- executeFunction(`${plugin}.on`, 'viewing');
85
- });
86
- }, [executeFunction, hit]);
87
77
  useEffect(() => {
88
78
  void fetchData();
89
79
  }, [params.id, fetchData, hit]);
@@ -145,37 +135,37 @@ const HitViewer = () => {
145
135
  if (!hit) {
146
136
  return (_jsx(PageCenter, { children: _jsx(Skeleton, { variant: "rounded", height: "520px" }) }));
147
137
  }
148
- return (_jsx(PageCenter, { maxWidth: "1500px", children: _jsxs(Box, { sx: {
149
- display: 'grid',
150
- position: 'relative',
151
- gridTemplateColumns: `1fr ${orientation === 'vertical' ? '300px' : '0px'}`,
152
- alignItems: 'stretch',
153
- gap: theme.spacing(2),
154
- transition: `${theme.transitions.duration.standard}ms`,
155
- mb: 1
156
- }, textAlign: "left", children: [_jsx(Collapse, { sx: { gridColumn: '1 / span 2', '& [class*=MuiStack-root]': { padding: '0 !important' } }, in: orientation === 'horizontal', children: _jsx(HitActions, { hit: hit, orientation: "horizontal" }) }), _jsxs(Box, { sx: {
157
- display: 'flex',
158
- '& > .MuiPaper-root': { flex: 1 },
159
- mr: orientation === 'vertical' ? 0 : -2
160
- }, children: [_jsx(HowlerCard, { tabIndex: 0, sx: { position: 'relative' }, children: _jsxs(CardContent, { children: [_jsx(HitBanner, { hit: hit, layout: HitLayout.COMFY, useListener: true }), _jsx(HitOutline, { hit: hit, layout: HitLayout.COMFY, forceAllFields: true }), _jsx(HitLabels, { hit: hit }), _jsx(HitLinks, { hit: hit, analytic: analytic, dossiers: dossiers })] }) }), !isUnderLg && (_jsxs(Stack, { spacing: 1, sx: {
161
- position: 'absolute',
162
- top: theme.spacing(2),
163
- right: theme.spacing(-6)
164
- }, children: [_jsx(Tooltip, { title: t('hit.panel.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('analytic.open'), children: _jsx(IconButton, { onClick: () => navigate(`/analytics/${analytic.analytic_id}`), children: _jsx(QueryStats, {}) }) }))] }))] }), _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: [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
165
- // eslint-disable-next-line react/no-array-index-key
166
- , { 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
167
- // eslint-disable-next-line react/no-array-index-key
168
- , { 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: {
169
- '& > .MuiBadge-badge': {
170
- backgroundColor: theme.palette.divider,
171
- zIndex: 1,
172
- right: theme.spacing(-0.5)
173
- },
174
- '& > svg': { zIndex: 2 }
175
- }, badgeContent: hit?.howler.comment?.length ?? 0, children: _jsx(Comment, {}) }) }), value: "hit_comments", onClick: () => setTab('hit_comments') }), _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') })] }) }), _jsx(Box, { sx: {
176
- gridColumn: '1 / span 2',
177
- '& > div': { padding: 0 },
178
- '& .react-json-view': { backgroundColor: 'transparent !important' }
179
- }, children: tabContent })] }) }));
138
+ return (_jsxs(PageCenter, { maxWidth: "1500px", children: [_jsx(PluginViewing, { hit: hit }), _jsxs(Box, { sx: {
139
+ display: 'grid',
140
+ position: 'relative',
141
+ gridTemplateColumns: `1fr ${orientation === 'vertical' ? '300px' : '0px'}`,
142
+ alignItems: 'stretch',
143
+ gap: theme.spacing(2),
144
+ transition: `${theme.transitions.duration.standard}ms`,
145
+ mb: 1
146
+ }, textAlign: "left", children: [_jsx(Collapse, { sx: { gridColumn: '1 / span 2', '& [class*=MuiStack-root]': { padding: '0 !important' } }, in: orientation === 'horizontal', children: _jsx(HitActions, { hit: hit, orientation: "horizontal" }) }), _jsxs(Box, { sx: {
147
+ display: 'flex',
148
+ '& > .MuiPaper-root': { flex: 1 },
149
+ mr: orientation === 'vertical' ? 0 : -2
150
+ }, children: [_jsx(HowlerCard, { tabIndex: 0, sx: { position: 'relative' }, children: _jsxs(CardContent, { children: [_jsx(HitBanner, { hit: hit, layout: HitLayout.COMFY, useListener: true }), _jsx(HitOutline, { hit: hit, layout: HitLayout.COMFY, forceAllFields: true }), _jsx(HitLabels, { hit: hit }), _jsx(HitLinks, { hit: hit, analytic: analytic, dossiers: dossiers })] }) }), !isUnderLg && (_jsxs(Stack, { spacing: 1, sx: {
151
+ position: 'absolute',
152
+ top: theme.spacing(2),
153
+ right: theme.spacing(-6)
154
+ }, children: [_jsx(Tooltip, { title: t('hit.panel.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('analytic.open'), children: _jsx(IconButton, { onClick: () => navigate(`/analytics/${analytic.analytic_id}`), children: _jsx(QueryStats, {}) }) }))] }))] }), _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: [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
155
+ // eslint-disable-next-line react/no-array-index-key
156
+ , { 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
157
+ // eslint-disable-next-line react/no-array-index-key
158
+ , { 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: {
159
+ '& > .MuiBadge-badge': {
160
+ backgroundColor: theme.palette.divider,
161
+ zIndex: 1,
162
+ right: theme.spacing(-0.5)
163
+ },
164
+ '& > svg': { zIndex: 2 }
165
+ }, badgeContent: hit?.howler.comment?.length ?? 0, children: _jsx(Comment, {}) }) }), value: "hit_comments", onClick: () => setTab('hit_comments') }), _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') })] }) }), _jsx(Box, { sx: {
166
+ gridColumn: '1 / span 2',
167
+ '& > div': { padding: 0 },
168
+ '& .react-json-view': { backgroundColor: 'transparent !important' }
169
+ }, children: tabContent })] })] }));
180
170
  };
181
171
  export default HitViewer;
@@ -5,7 +5,9 @@ import { RecordContext } from '@cccsaurora/howler-ui/components/app/providers/Re
5
5
  import { SocketContext } from '@cccsaurora/howler-ui/components/app/providers/SocketProvider';
6
6
  import { beforeEach, describe, expect, it, vi } from 'vitest';
7
7
  const mockEmit = vi.hoisted(() => vi.fn());
8
- const mockExecutePlugin = vi.hoisted(() => vi.fn());
8
+ const mockExecutePlugin = vi.hoisted(() => vi.fn(function () {
9
+ return this.functionArray;
10
+ }));
9
11
  const mockOpen = vi.hoisted(() => ({ current: true }));
10
12
  const mockParams = vi.hoisted(() => ({ id: 'hit-1' }));
11
13
  const mockGetHit = vi.hoisted(() => vi.fn().mockResolvedValue(undefined));
@@ -28,7 +30,7 @@ vi.mock('plugins/store', () => ({
28
30
  }
29
31
  }));
30
32
  vi.mock('react-pluggable', () => ({
31
- usePluginStore: () => ({ executeFunction: mockExecutePlugin })
33
+ usePluginStore: () => ({ executeFunction: mockExecutePlugin, functionArray: [] })
32
34
  }));
33
35
  vi.mock('react-i18next', () => ({
34
36
  useTranslation: () => ({
@@ -142,7 +144,7 @@ const createWrapper = () => {
142
144
  const renderViewer = () => render(_jsx(HitViewer, {}), { wrapper: createWrapper() });
143
145
  beforeEach(() => {
144
146
  mockEmit.mockReset();
145
- mockExecutePlugin.mockReset();
147
+ mockExecutePlugin.mockClear();
146
148
  mockOpen.current = true;
147
149
  mockParams.id = 'hit-1';
148
150
  mockUseMediaQuery.mockReset().mockReturnValue(false);
@@ -180,7 +182,7 @@ describe('HitViewer', () => {
180
182
  });
181
183
  expect(screen.getByText('details-content')).toBeInTheDocument();
182
184
  expect(mockExecutePlugin).toHaveBeenCalledTimes(1);
183
- expect(mockExecutePlugin).toHaveBeenCalledWith('test-plugin.on', 'viewing');
185
+ expect(mockExecutePlugin).toHaveBeenCalledWith('test-plugin.on', 'viewing', hit);
184
186
  });
185
187
  it('emits viewing and stop_viewing socket events', async () => {
186
188
  const { unmount } = renderViewer();
package/package.json CHANGED
@@ -93,7 +93,7 @@
93
93
  "url": "https://github.com/CybercentreCanada/howler"
94
94
  },
95
95
  "type": "module",
96
- "version": "3.1.0-dev.1466",
96
+ "version": "3.1.0-dev.1493",
97
97
  "exports": {
98
98
  "./i18n": "./i18n.js",
99
99
  "./index.css": "./index.css",
@@ -243,6 +243,7 @@
243
243
  "./components/routes/overviews/template/*": "./components/routes/overviews/template/*.js",
244
244
  "./components/routes/hits/search/*": "./components/routes/hits/search/*.js",
245
245
  "./components/routes/hits/view/*": "./components/routes/hits/view/*.js",
246
+ "./components/routes/hits/shared/*": "./components/routes/hits/shared/*.js",
246
247
  "./components/routes/hits/search/shared/*": "./components/routes/hits/search/shared/*.js",
247
248
  "./components/routes/hits/search/grid/*": "./components/routes/hits/search/grid/*.js",
248
249
  "./components/routes/analytics/widgets/*": "./components/routes/analytics/widgets/*.js",