@cccsaurora/howler-ui 2.16.0-dev.378 → 2.16.0-dev.381

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.
Files changed (57) hide show
  1. package/components/app/App.js +2 -0
  2. package/components/app/hooks/useMatchers.js +0 -4
  3. package/components/app/providers/FavouritesProvider.js +2 -1
  4. package/components/app/providers/FieldProvider.d.ts +2 -2
  5. package/components/app/providers/HitProvider.d.ts +3 -3
  6. package/components/app/providers/HitSearchProvider.d.ts +7 -8
  7. package/components/app/providers/HitSearchProvider.js +64 -39
  8. package/components/app/providers/HitSearchProvider.test.d.ts +1 -0
  9. package/components/app/providers/HitSearchProvider.test.js +505 -0
  10. package/components/app/providers/ParameterProvider.d.ts +13 -5
  11. package/components/app/providers/ParameterProvider.js +240 -84
  12. package/components/app/providers/ParameterProvider.test.d.ts +1 -0
  13. package/components/app/providers/ParameterProvider.test.js +1041 -0
  14. package/components/app/providers/ViewProvider.d.ts +3 -2
  15. package/components/app/providers/ViewProvider.js +21 -14
  16. package/components/app/providers/ViewProvider.test.js +19 -29
  17. package/components/elements/display/ChipPopper.d.ts +21 -0
  18. package/components/elements/display/ChipPopper.js +36 -0
  19. package/components/elements/display/ChipPopper.test.d.ts +1 -0
  20. package/components/elements/display/ChipPopper.test.js +309 -0
  21. package/components/elements/hit/HitActions.js +3 -3
  22. package/components/elements/hit/HitSummary.d.ts +0 -1
  23. package/components/elements/hit/HitSummary.js +11 -21
  24. package/components/elements/hit/aggregate/HitGraph.d.ts +1 -3
  25. package/components/elements/hit/aggregate/HitGraph.js +9 -15
  26. package/components/routes/dossiers/DossierCard.test.js +0 -2
  27. package/components/routes/dossiers/DossierEditor.test.js +27 -33
  28. package/components/routes/hits/search/HitBrowser.js +7 -48
  29. package/components/routes/hits/search/HitContextMenu.test.js +11 -29
  30. package/components/routes/hits/search/InformationPane.js +1 -1
  31. package/components/routes/hits/search/QuerySettings.js +30 -0
  32. package/components/routes/hits/search/QuerySettings.test.d.ts +1 -0
  33. package/components/routes/hits/search/QuerySettings.test.js +553 -0
  34. package/components/routes/hits/search/SearchPane.js +8 -10
  35. package/components/routes/hits/search/ViewLink.d.ts +4 -1
  36. package/components/routes/hits/search/ViewLink.js +37 -19
  37. package/components/routes/hits/search/ViewLink.test.js +349 -303
  38. package/components/routes/hits/search/grid/HitGrid.js +2 -6
  39. package/components/routes/hits/search/shared/HitFilter.d.ts +2 -0
  40. package/components/routes/hits/search/shared/HitFilter.js +31 -23
  41. package/components/routes/hits/search/shared/HitSort.js +16 -8
  42. package/components/routes/hits/search/shared/SearchSpan.js +19 -10
  43. package/components/routes/views/ViewComposer.js +7 -6
  44. package/components/routes/views/Views.js +2 -1
  45. package/locales/en/translation.json +6 -0
  46. package/locales/fr/translation.json +6 -0
  47. package/package.json +2 -2
  48. package/setupTests.js +4 -1
  49. package/tests/mocks.d.ts +18 -0
  50. package/tests/mocks.js +65 -0
  51. package/tests/server-handlers.js +10 -28
  52. package/utils/viewUtils.d.ts +2 -0
  53. package/utils/viewUtils.js +11 -0
  54. package/components/routes/hits/search/shared/QuerySettings.js +0 -22
  55. /package/components/routes/hits/search/{shared/QuerySettings.d.ts → QuerySettings.d.ts} +0 -0
  56. /package/components/routes/hits/search/{CustomSort.d.ts → shared/CustomSort.d.ts} +0 -0
  57. /package/components/routes/hits/search/{CustomSort.js → shared/CustomSort.js} +0 -0
@@ -1,26 +1,37 @@
1
+ import { createElement as _createElement } from "react";
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Close, Edit, Language, Lock, OpenInNew, Person, Refresh, SavedSearch } from '@mui/icons-material';
3
- import { Alert, IconButton, Stack, Tooltip, Typography } from '@mui/material';
3
+ import { ArrowDropDown, Delete, Edit, Language, Lock, OpenInNew, Person, Refresh, SavedSearch, SelectAll } from '@mui/icons-material';
4
+ import { Autocomplete, Chip, CircularProgress, IconButton, Stack, TextField, Tooltip, Typography } from '@mui/material';
4
5
  import { HitSearchContext } from '@cccsaurora/howler-ui/components/app/providers/HitSearchProvider';
5
6
  import { ParameterContext } from '@cccsaurora/howler-ui/components/app/providers/ParameterProvider';
6
7
  import { ViewContext } from '@cccsaurora/howler-ui/components/app/providers/ViewProvider';
7
- import { has } from 'lodash-es';
8
- import { memo, useMemo } from 'react';
8
+ import ChipPopper from '@cccsaurora/howler-ui/components/elements/display/ChipPopper';
9
+ import { memo, useEffect, useMemo, useState } from 'react';
9
10
  import { useTranslation } from 'react-i18next';
10
11
  import { Link } from 'react-router-dom';
11
12
  import { useContextSelector } from 'use-context-selector';
12
- const ViewLink = () => {
13
+ const ViewLink = ({ id, viewId }) => {
13
14
  const { t } = useTranslation();
15
+ const getCurrentViews = useContextSelector(ViewContext, ctx => ctx.getCurrentViews);
16
+ const views = useContextSelector(ViewContext, ctx => ctx.views);
14
17
  const query = useContextSelector(ParameterContext, ctx => ctx.query);
15
18
  const sort = useContextSelector(ParameterContext, ctx => ctx.sort);
16
19
  const span = useContextSelector(ParameterContext, ctx => ctx.span);
17
- const viewId = useContextSelector(HitSearchContext, ctx => ctx.viewId);
20
+ const currentViews = useContextSelector(ParameterContext, ctx => ctx.views);
21
+ const removeView = useContextSelector(ParameterContext, ctx => ctx.removeView);
22
+ const setParamView = useContextSelector(ParameterContext, ctx => ctx.setView);
18
23
  const search = useContextSelector(HitSearchContext, ctx => ctx.search);
19
- const viewsReady = useContextSelector(ViewContext, ctx => has(ctx.views, viewId));
20
- const selectedView = useContextSelector(ViewContext, ctx => ctx.views[viewId]);
24
+ const [loading, setLoading] = useState(true);
25
+ const [view, setView] = useState(null);
26
+ useEffect(() => {
27
+ setLoading(true);
28
+ getCurrentViews({ viewId, ignoreParams: true })
29
+ .then(result => setView(result[0]))
30
+ .finally(() => setLoading(false));
31
+ }, [getCurrentViews, viewId]);
21
32
  const viewUrl = useMemo(() => {
22
- if (viewId) {
23
- return `/views/${viewId}/edit`;
33
+ if (view?.view_id) {
34
+ return `/views/${view.view_id}/edit`;
24
35
  }
25
36
  const keys = [];
26
37
  if (query) {
@@ -33,15 +44,22 @@ const ViewLink = () => {
33
44
  keys.push(`span=${span}`);
34
45
  }
35
46
  return keys.length > 0 ? `/views/create?${keys.join('&')}` : '/views/create';
36
- }, [query, sort, span, viewId]);
37
- const viewButton = useMemo(() => (_jsx(Tooltip, { title: viewId ? t('route.views.edit') : t('route.views.create'), children: _jsx(IconButton, { "aria-label": viewId ? t('route.views.edit') : t('route.views.create'), size: "small", component: Link, disabled: (!viewId && !query) || span?.endsWith('custom'), to: viewUrl, role: "link", children: viewId ? _jsx(Edit, { fontSize: "small" }) : _jsx(SavedSearch, {}) }) })), [query, span, t, viewId, viewUrl]);
38
- if (!viewId) {
39
- return null;
47
+ }, [query, sort, span, view]);
48
+ const options = useMemo(() => Object.values(views).filter(_view => !!_view && !currentViews?.includes(_view.view_id)), [currentViews, views]);
49
+ if (loading) {
50
+ return _jsx(Chip, { size: "small", icon: _jsx(CircularProgress, { size: 12 }) });
40
51
  }
41
- return selectedView ? (_jsxs(Stack, { direction: "row", spacing: 1, alignItems: "center", children: [_jsx(Tooltip, { title: t(`route.views.manager.${selectedView.type}`), children: {
42
- readonly: _jsx(Lock, { fontSize: "small", "aria-label": t(`route.views.manager.${selectedView.type}`) }),
43
- global: _jsx(Language, { fontSize: "small", "aria-label": t(`route.views.manager.${selectedView.type}`) }),
44
- personal: _jsx(Person, { fontSize: "small", "aria-label": t(`route.views.manager.${selectedView.type}`) })
45
- }[selectedView.type] }), _jsx(Tooltip, { title: selectedView.query, children: _jsx(Typography, { role: "link", sx: { color: 'text.primary' }, variant: "body1", component: Link, to: `/views/${selectedView.view_id}/edit`, "aria-label": `${t(selectedView.title)} - ${selectedView.query ?? t('unknown')}`, children: t(selectedView.title) }) }), viewButton, _jsx(Tooltip, { title: t('view.refresh'), children: _jsx(IconButton, { size: "small", onClick: () => search(query), "aria-label": t('view.refresh'), children: _jsx(Refresh, { fontSize: "small" }) }) }), _jsx(Tooltip, { title: t('view.open'), children: _jsx(IconButton, { size: "small", component: Link, to: `/search?query=${selectedView.query}`, "aria-label": t('view.open'), role: "link", children: _jsx(OpenInNew, { fontSize: "small" }) }) })] })) : (viewsReady && (_jsx(Alert, { role: "alert", variant: "outlined", severity: "error", "aria-live": "assertive", "aria-atomic": "true", action: _jsx(IconButton, { size: "small", component: Link, to: "/search", children: _jsx(Close, { fontSize: "small" }) }), children: t('view.notfound') })));
52
+ if (viewId === '') {
53
+ return (_jsx(ChipPopper, { icon: _jsx(SelectAll, {}), label: t('hit.search.view.select'), deleteIcon: _jsx(ArrowDropDown, {}), toggleOnDelete: true, slotProps: { chip: { size: 'small', color: 'warning' } }, children: _jsxs(Stack, { spacing: 1, direction: "row", children: [_jsx(Autocomplete, { fullWidth: true, size: "small", options: options, getOptionLabel: _view => t(_view.title), renderOption: ({ key, ...props }, o) => (_createElement("li", { ...props, key: key },
54
+ _jsxs(Stack, { children: [_jsx(Typography, { variant: "body1", children: t(o.title) }), _jsx(Typography, { variant: "caption", children: _jsx("code", { style: { wordBreak: 'break-all' }, children: o.query }) })] }))), renderInput: _params => (_jsx(TextField, { ..._params, label: t('hit.search.view.select'), sx: { minWidth: '210px' } })), onChange: (_event, _view) => setParamView(id, _view.view_id), sx: { minWidth: '300px' } }), _jsx(Tooltip, { title: t('hit.search.view.remove'), children: _jsx(IconButton, { "aria-label": t('hit.search.view.remove'), onClick: () => removeView(viewId), children: _jsx(Delete, {}) }) })] }) }));
55
+ }
56
+ if (!view) {
57
+ return (_jsx(Chip, { size: "small", role: "alert", color: "error", "aria-live": "assertive", "aria-atomic": "true", label: t('view.notfound'), onDelete: () => removeView(viewId) }));
58
+ }
59
+ return (_jsx(ChipPopper, { slotProps: { chip: { size: 'small' } }, icon: _jsx(Tooltip, { title: t(`route.views.manager.${view.type}`), children: {
60
+ readonly: _jsx(Lock, { fontSize: "small", "aria-label": t(`route.views.manager.${view.type}`) }),
61
+ global: _jsx(Language, { fontSize: "small", "aria-label": t(`route.views.manager.${view.type}`) }),
62
+ personal: _jsx(Person, { fontSize: "small", "aria-label": t(`route.views.manager.${view.type}`) })
63
+ }[view.type] }), label: _jsx(Tooltip, { title: view.query, children: _jsx(Typography, { role: "link", sx: { color: 'text.primary' }, variant: "body2", component: Link, to: `/views/${view.view_id}/edit`, "aria-label": `${t(view.title)} - ${view.query ?? t('unknown')}`, children: t(view.title) }) }), onDelete: () => removeView(viewId), children: _jsxs(Stack, { direction: "row", spacing: 0.5, alignItems: "center", children: [_jsx(Tooltip, { title: view ? t('route.views.edit') : t('route.views.create'), children: _jsx(IconButton, { "aria-label": view ? t('route.views.edit') : t('route.views.create'), size: "small", component: Link, disabled: (!view && !query) || span?.endsWith('custom'), to: viewUrl, role: "link", children: view ? _jsx(Edit, { fontSize: "small" }) : _jsx(SavedSearch, {}) }) }), _jsx(Tooltip, { title: t('view.refresh'), children: _jsx(IconButton, { size: "small", onClick: () => search(query), "aria-label": t('view.refresh'), children: _jsx(Refresh, { fontSize: "small" }) }) }), _jsx(Tooltip, { title: t('view.open'), children: _jsx(IconButton, { size: "small", component: Link, to: `/search?query=${view.query}`, "aria-label": t('view.open'), role: "link", children: _jsx(OpenInNew, { fontSize: "small" }) }) })] }) }));
46
64
  };
47
65
  export default memo(ViewLink);