@cccsaurora/howler-ui 2.19.0-dev.1099 → 2.19.0-dev.1143

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 (45) hide show
  1. package/components/app/App.js +4 -2
  2. package/components/app/providers/GridColumnsProvider.d.ts +52 -0
  3. package/components/app/providers/GridColumnsProvider.js +177 -0
  4. package/components/app/providers/GridColumnsProvider.test.js +255 -0
  5. package/components/elements/hit/HitContextMenu.test.d.ts +1 -0
  6. package/components/{routes/hits/search → elements/hit}/grid/ColumnHeader.d.ts +2 -1
  7. package/components/{routes/hits/search → elements/hit}/grid/ColumnHeader.js +3 -3
  8. package/components/{routes/hits/search → elements/hit}/grid/HitRow.d.ts +1 -1
  9. package/components/elements/hit/grid/HitTable.d.ts +12 -0
  10. package/components/elements/hit/grid/HitTable.js +82 -0
  11. package/components/elements/view/LayoutToggle.d.ts +8 -0
  12. package/components/elements/view/LayoutToggle.js +12 -0
  13. package/components/elements/view/ViewTitle.d.ts +3 -0
  14. package/components/elements/view/ViewTitle.js +6 -3
  15. package/components/routes/hits/search/HitBrowser.js +2 -1
  16. package/components/routes/hits/search/SearchPane.js +6 -8
  17. package/components/routes/hits/search/ViewLink.js +3 -2
  18. package/components/routes/hits/search/grid/HitGrid.js +17 -85
  19. package/components/routes/hits/search/shared/LayoutSettings.js +25 -0
  20. package/components/routes/hits/search/shared/SearchActionMenu.d.ts +4 -0
  21. package/components/routes/hits/search/shared/SearchActionMenu.js +17 -0
  22. package/components/routes/home/ViewCard.js +1 -1
  23. package/components/routes/views/ViewComposer.js +32 -6
  24. package/locales/en/translation.json +6 -3
  25. package/locales/fr/translation.json +6 -3
  26. package/models/entities/generated/Column.d.ts +7 -0
  27. package/models/entities/generated/Host.d.ts +1 -0
  28. package/models/entities/generated/Settings.d.ts +4 -0
  29. package/package.json +2 -1
  30. package/utils/stringUtils.d.ts +1 -0
  31. package/utils/stringUtils.js +7 -0
  32. package/utils/stringUtils.test.js +21 -1
  33. package/components/routes/hits/search/LayoutSettings.js +0 -24
  34. /package/components/{routes/hits/search/HitContextMenu.test.d.ts → app/providers/GridColumnsProvider.test.d.ts} +0 -0
  35. /package/components/{routes/hits/search → elements/hit}/HitContextMenu.d.ts +0 -0
  36. /package/components/{routes/hits/search → elements/hit}/HitContextMenu.js +0 -0
  37. /package/components/{routes/hits/search → elements/hit}/HitContextMenu.test.js +0 -0
  38. /package/components/{routes/hits/search → elements/hit}/grid/AddColumnModal.d.ts +0 -0
  39. /package/components/{routes/hits/search → elements/hit}/grid/AddColumnModal.js +0 -0
  40. /package/components/{routes/hits/search → elements/hit}/grid/EnhancedCell.d.ts +0 -0
  41. /package/components/{routes/hits/search → elements/hit}/grid/EnhancedCell.js +0 -0
  42. /package/components/{routes/hits/search → elements/hit}/grid/HitRow.js +0 -0
  43. /package/components/routes/hits/search/{BundleParentMenu.d.ts → shared/BundleParentMenu.d.ts} +0 -0
  44. /package/components/routes/hits/search/{BundleParentMenu.js → shared/BundleParentMenu.js} +0 -0
  45. /package/components/routes/hits/search/{LayoutSettings.d.ts → shared/LayoutSettings.d.ts} +0 -0
@@ -380,8 +380,8 @@
380
380
  "page.settings.local.details.drawer.description": "Instead of switching between a divided view and the drawer on different screen sizes, this setting forces Howler to always use the drawer.",
381
381
  "page.settings.local.flatten.json": "Flatten JSON in JSON View",
382
382
  "page.settings.local.flatten.json.description": "Instead of showing the object structure of the JSON, show it as flattened keys.",
383
- "page.settings.local.hits.display_type": "Default display type for results",
384
- "page.settings.local.hits.display_type.description": "This setting allows you to decide whether to use the list or grid view by default when searching.",
383
+ "page.settings.local.hits.display_type": "Display type for results",
384
+ "page.settings.local.hits.display_type.description": "This setting allows you to decide whether to use the list or grid view when searching.",
385
385
  "page.settings.local.hits.display_type.grid": "Grid",
386
386
  "page.settings.local.hits.display_type.list": "List",
387
387
  "page.settings.local.hits.field_count": "Template Field Count",
@@ -763,9 +763,12 @@
763
763
  "usermenu.settings": "Settings",
764
764
  "using": "using",
765
765
  "view.assigned_to_me": "Assigned to Me",
766
+ "view.display.grid.inactive_warning": "The view has grid properties which cannot be applied",
766
767
  "view.notfound": "This view is not available to you, or does not exist.",
767
768
  "view.open": "Open View Query",
768
769
  "view.refresh": "Refresh View",
770
+ "view.settings": "View Settings",
769
771
  "view.settings.advance_on_triage": "Advance to next hit on triage",
770
- "view.settings.advance_on_triage.description": "If this is enabled, triaging a hit on this view will automatically move to the next hit in line, making rapid triage of hits easier."
772
+ "view.settings.advance_on_triage.description": "If this is enabled, triaging a hit on this view will automatically move to the next hit in line, making rapid triage of hits easier.",
773
+ "view.settings.layout": "Default layout in search"
771
774
  }
@@ -380,8 +380,8 @@
380
380
  "page.settings.local.details.drawer.description": "Au lieu de basculer entre une vue divisée et le tiroir en fonction de la taille de l'écran, ce paramètre oblige Howler à toujours utiliser le tiroir.",
381
381
  "page.settings.local.flatten.json": "Aplatir le JSON dans la vue JSON",
382
382
  "page.settings.local.flatten.json.description": "Au lieu d'afficher la structure d'objet du JSON, affichez-la sous forme de clés aplaties",
383
- "page.settings.local.hits.display_type": "Type d'affichage par défaut pour les résultats",
384
- "page.settings.local.hits.display_type.description": "Ce paramètre vous permet de choisir entre l'affichage sous forme de liste ou de grille par défaut lors d'une recherche.",
383
+ "page.settings.local.hits.display_type": "Type d'affichage pour les résultats",
384
+ "page.settings.local.hits.display_type.description": "Ce paramètre vous permet de choisir entre l'affichage sous forme de liste ou de grille lors d'une recherche.",
385
385
  "page.settings.local.hits.display_type.grid": "Grille",
386
386
  "page.settings.local.hits.display_type.list": "Liste",
387
387
  "page.settings.local.hits.field_count": "Nombre de champs du modèle",
@@ -763,9 +763,12 @@
763
763
  "usermenu.settings": "Paramètres",
764
764
  "using": "utilisant",
765
765
  "view.assigned_to_me": "Assigné à moi",
766
+ "view.display.grid.inactive_warning": "La vue possède des propriétés de grille qui ne peuvent pas être appliquées",
766
767
  "view.notfound": "Cette vue n'est pas disponible pour vous, ou n'existe pas.",
767
768
  "view.open": "Ouvrir requête de la vue",
768
769
  "view.refresh": "Rafraîchir la vue",
770
+ "view.settings": "Paramètres de vue",
769
771
  "view.settings.advance_on_triage": "Passer à la hit suivant lors du triage",
770
- "view.settings.advance_on_triage.description": "Si cette option est activée, le triage d'une hit sur cette vue passera automatiquement à la hit suivant, ce qui facilitera le triage rapide des résultats."
772
+ "view.settings.advance_on_triage.description": "Si cette option est activée, le triage d'une hit sur cette vue passera automatiquement à la hit suivant, ce qui facilitera le triage rapide des résultats.",
773
+ "view.settings.layout": "Mise en page par défaut dans la recherche"
771
774
  }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * NOTE: This is an auto-generated file. Don't edit this manually.
3
+ */
4
+ export interface Column {
5
+ field?: string;
6
+ width?: number;
7
+ }
@@ -3,6 +3,7 @@
3
3
  */
4
4
  export interface Host {
5
5
  domain?: string;
6
+ hostname?: string;
6
7
  id?: string;
7
8
  ip?: string[];
8
9
  mac?: string[];
@@ -1,6 +1,10 @@
1
+ import type { Column } from './Column';
2
+
1
3
  /**
2
4
  * NOTE: This is an auto-generated file. Don't edit this manually.
3
5
  */
4
6
  export interface Settings {
5
7
  advance_on_triage?: boolean;
8
+ columns?: Column[];
9
+ display?: string;
6
10
  }
package/package.json CHANGED
@@ -93,7 +93,7 @@
93
93
  "url": "https://github.com/CybercentreCanada/howler"
94
94
  },
95
95
  "type": "module",
96
- "version": "2.19.0-dev.1099",
96
+ "version": "2.19.0-dev.1143",
97
97
  "exports": {
98
98
  "./i18n": "./i18n.js",
99
99
  "./index.css": "./index.css",
@@ -211,6 +211,7 @@
211
211
  "./components/elements/hit/aggregate/*": "./components/elements/hit/aggregate/*.js",
212
212
  "./components/elements/hit/outlines/*": "./components/elements/hit/outlines/*.js",
213
213
  "./components/elements/hit/actions/*": "./components/elements/hit/actions/*.js",
214
+ "./components/elements/hit/grid/*": "./components/elements/hit/grid/*.js",
214
215
  "./components/elements/hit/elements/*": "./components/elements/hit/elements/*.js",
215
216
  "./components/elements/hit/outlines/al/*": "./components/elements/hit/outlines/al/*.js",
216
217
  "./components/elements/addons/search/*": "./components/elements/addons/search/*.js",
@@ -6,3 +6,4 @@ export declare const sanitizeLuceneQuery: (query: string) => string;
6
6
  export declare const safeStringPropertyCompare: (propertyPath: string) => (a: unknown, b: unknown) => any;
7
7
  export declare const sanitizeMultilineLucene: (query: string) => string;
8
8
  export declare const validateRegex: (regex: string) => boolean;
9
+ export declare const parsePixelSizeStringToInt: (size: string) => number;
@@ -45,3 +45,10 @@ export const validateRegex = (regex) => {
45
45
  return false;
46
46
  }
47
47
  };
48
+ export const parsePixelSizeStringToInt = (size) => {
49
+ const match = size.match(/^(\d+(\.\d+)?)(px)?$/);
50
+ if (match) {
51
+ return parseInt(match[1]);
52
+ }
53
+ return null;
54
+ };
@@ -1,6 +1,6 @@
1
1
  /// <reference types="vitest" />
2
2
  import { describe, expect, it } from 'vitest';
3
- import { maxLenStr, nameToInitials, safeFieldValue, safeFieldValueURI, safeStringPropertyCompare, sanitizeLuceneQuery, sanitizeMultilineLucene, validateRegex } from './stringUtils';
3
+ import { maxLenStr, nameToInitials, parsePixelSizeStringToInt, safeFieldValue, safeFieldValueURI, safeStringPropertyCompare, sanitizeLuceneQuery, sanitizeMultilineLucene, validateRegex } from './stringUtils';
4
4
  describe('nameToInitials', () => {
5
5
  it('returns initials from a standard first-last name', () => {
6
6
  expect(nameToInitials('John Doe')).toEqual(['J', 'D']);
@@ -157,3 +157,23 @@ describe('validateRegex', () => {
157
157
  expect(validateRegex('a{2,5}')).toBe(true);
158
158
  });
159
159
  });
160
+ describe('parsePixelSizeStringToInt', () => {
161
+ it('parses a pixel size string with "px" suffix', () => {
162
+ expect(parsePixelSizeStringToInt('100px')).toBe(100);
163
+ });
164
+ it('parses a pixel size string without "px" suffix', () => {
165
+ expect(parsePixelSizeStringToInt('200')).toBe(200);
166
+ });
167
+ it('parses a pixel size string with decimal value', () => {
168
+ expect(parsePixelSizeStringToInt('150.5px')).toBe(150);
169
+ });
170
+ it('returns null for a non-numeric string', () => {
171
+ expect(parsePixelSizeStringToInt('abc')).toBeNull();
172
+ });
173
+ it('returns null for an empty string', () => {
174
+ expect(parsePixelSizeStringToInt('')).toBeNull();
175
+ });
176
+ it('returns null for a string with an invalid unit', () => {
177
+ expect(parsePixelSizeStringToInt('50rem')).toBeNull();
178
+ });
179
+ });
@@ -1,24 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { ArrowDropDown, InfoOutlined, List, Settings, TableChart, ViewComfy, ViewCompact, ViewModule } from '@mui/icons-material';
3
- import { Checkbox, Divider, FormLabel, Stack, TextField, ToggleButton, ToggleButtonGroup, Tooltip } from '@mui/material';
4
- import { HitSearchContext } from '@cccsaurora/howler-ui/components/app/providers/HitSearchProvider';
5
- import ChipPopper from '@cccsaurora/howler-ui/components/elements/display/ChipPopper';
6
- import { HitLayout } from '@cccsaurora/howler-ui/components/elements/hit/HitLayout';
7
- import { useMyLocalStorageItem } from '@cccsaurora/howler-ui/components/hooks/useMyLocalStorage';
8
- import { useTranslation } from 'react-i18next';
9
- import { useContextSelector } from 'use-context-selector';
10
- import { StorageKey } from '@cccsaurora/howler-ui/utils/constants';
11
- const LayoutSettings = () => {
12
- const { t } = useTranslation();
13
- const displayType = useContextSelector(HitSearchContext, ctx => ctx.displayType);
14
- const setDisplayType = useContextSelector(HitSearchContext, ctx => ctx.setDisplayType);
15
- const [hitLayout, setHitLayout] = useMyLocalStorageItem(StorageKey.HIT_LAYOUT, false);
16
- const [templateFieldCount, setTemplateFieldCount] = useMyLocalStorageItem(StorageKey.TEMPLATE_FIELD_COUNT, null);
17
- return (_jsx(ChipPopper, { icon: _jsx(Tooltip, { title: t('search.layout.settings'), children: _jsx(Settings, {}) }), deleteIcon: _jsx(ArrowDropDown, {}), toggleOnDelete: true, disablePortal: false, slotProps: { chip: { size: 'medium', 'aria-label': t('search.layout.settings') } }, placement: "bottom-end", children: _jsxs(Stack, { spacing: 1, alignItems: "start", children: [_jsxs(Stack, { direction: "row", spacing: 0.5, alignItems: "center", alignSelf: "stretch", children: [_jsx(FormLabel, { id: "display_type", children: t('page.settings.local.hits.display_type') }), _jsx("div", { style: { flex: 1 } }), _jsx(Tooltip, { title: t('page.settings.local.hits.display_type.description'), children: _jsx(InfoOutlined, { fontSize: "inherit" }) })] }), _jsxs(ToggleButtonGroup, { exclusive: true, value: displayType, onChange: (__, value) => setDisplayType(value), size: "small", "aria-labelledby": "display_type", children: [_jsx(ToggleButton, { value: "list", children: _jsxs(Stack, { direction: "row", spacing: 0.5, children: [_jsx(List, {}), _jsx("span", { children: t('page.settings.local.hits.display_type.list') })] }) }), _jsx(ToggleButton, { value: "grid", children: _jsxs(Stack, { direction: "row", spacing: 0.5, children: [_jsx(TableChart, {}), _jsx("span", { children: t('page.settings.local.hits.display_type.grid') })] }) })] }), _jsx(Divider, { flexItem: true }), _jsxs(Stack, { direction: "row", spacing: 0.5, alignItems: "center", alignSelf: "stretch", children: [_jsx(FormLabel, { id: "layout", children: t('page.settings.local.hits.layout') }), _jsx("div", { style: { flex: 1 } }), _jsx(Tooltip, { title: t('page.settings.local.hits.layout.description'), children: _jsx(InfoOutlined, { fontSize: "inherit" }) })] }), _jsxs(ToggleButtonGroup, { exclusive: true, size: "small", value: hitLayout, onChange: (_, value) => setHitLayout(value), "aria-labelledby": "layout", children: [_jsx(ToggleButton, { value: HitLayout.DENSE, children: _jsxs(Stack, { direction: "row", spacing: 0.5, children: [_jsx(ViewCompact, {}), _jsx("span", { children: t('page.settings.local.hits.layout.dense') })] }) }), _jsx(ToggleButton, { value: HitLayout.NORMAL, children: _jsxs(Stack, { direction: "row", spacing: 0.5, children: [_jsx(ViewModule, {}), _jsx("span", { children: t('page.settings.local.hits.layout.normal') })] }) }), _jsx(ToggleButton, { value: HitLayout.COMFY, children: _jsxs(Stack, { direction: "row", spacing: 0.5, children: [_jsx(ViewComfy, {}), _jsx("span", { children: t('page.settings.local.hits.layout.comfy') })] }) })] }), _jsx(Divider, { flexItem: true }), _jsxs(Stack, { direction: "row", spacing: 0.5, alignItems: "center", alignSelf: "stretch", children: [_jsx(FormLabel, { id: "field_count", children: t('page.settings.local.hits.field_count') }), _jsx("div", { style: { flex: 1 } }), _jsx(Tooltip, { title: t('page.settings.local.hits.field_count.description'), children: _jsx(InfoOutlined, { fontSize: "inherit" }) })] }), _jsxs(Stack, { direction: "row", spacing: 0.5, alignSelf: "stretch", children: [_jsx(Checkbox, { checked: templateFieldCount !== null, onChange: (_, checked) => setTemplateFieldCount(checked ? 3 : null), size: "small" }), _jsx(TextField, { type: "number", size: "small", disabled: templateFieldCount === null, value: templateFieldCount ?? 3, fullWidth: true, onChange: e => {
18
- const val = parseInt(e.target.value);
19
- if (!isNaN(val)) {
20
- setTemplateFieldCount(Math.min(15, Math.max(0, val)));
21
- }
22
- }, inputProps: { min: 0, max: 15, 'aria-labelledby': 'field_count' } })] })] }) }));
23
- };
24
- export default LayoutSettings;