@eeacms/volto-cca-policy 1.0.25 → 1.0.26

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 (23) hide show
  1. package/CHANGELOG.md +20 -13
  2. package/package.json +1 -1
  3. package/src/components/Search/NavigatorCatalogue/NavigatorCatalogueCardItem.jsx +16 -24
  4. package/src/components/Search/NavigatorCatalogue/NavigatorCatalogueCardItem.test.jsx +21 -2
  5. package/src/components/Search/NavigatorGuide/NavigatorGuideContentView.jsx +153 -135
  6. package/src/components/Search/NavigatorGuide/NavigatorGuideContentView.test.jsx +108 -2
  7. package/src/components/Search/NavigatorGuide/utils.js +15 -0
  8. package/src/components/Search/NavigatorGuide/utils.test.js +18 -1
  9. package/src/components/index.js +2 -0
  10. package/src/components/manage/Blocks/ChatbotCatalogue/astUtils.js +129 -3
  11. package/src/components/manage/Blocks/ChatbotCatalogue/astUtils.test.js +207 -0
  12. package/src/components/manage/Blocks/ChatbotCatalogue/docCards.js +8 -0
  13. package/src/components/manage/Blocks/ChatbotCatalogue/docCards.test.js +72 -0
  14. package/src/components/manage/Blocks/ChatbotCatalogue/nextSteps.js +4 -0
  15. package/src/components/manage/Blocks/ChatbotCatalogue/nextSteps.test.js +48 -0
  16. package/src/components/theme/CompareTools/CompareToolsPanel.jsx +1 -1
  17. package/src/components/theme/CompareTools/CompareToolsView.jsx +1 -1
  18. package/src/components/theme/Content/Sections/MetadataItemList.jsx +7 -24
  19. package/src/components/theme/TagOverflowPopup.jsx +28 -0
  20. package/src/components/theme/Views/RelatedTools.jsx +7 -25
  21. package/src/search/navigator_guide/facets.js +1 -0
  22. package/src/search/navigator_guide/guideSteps.js +1 -1
  23. package/theme/globals/navigator.less +11 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,26 @@ All notable changes to this project will be documented in this file. Dates are d
4
4
 
5
5
  Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
6
6
 
7
+ ### [1.0.26](https://github.com/eea/volto-cca-policy/compare/1.0.25...1.0.26) - 21 September 2026
8
+
9
+ #### :rocket: New Features
10
+
11
+ - feat(navigator): implement TagOverflowPopup component and replace Popup in navigator [kreafox - [`42a66c8`](https://github.com/eea/volto-cca-policy/commit/42a66c826f2e19ebd0102fc05a2df5ccd1648f14)]
12
+
13
+ #### :bug: Bug Fixes
14
+
15
+ - fix(navigator): rename adaptation support cycle step and improve guide me layout [kreafox - [`2806e1b`](https://github.com/eea/volto-cca-policy/commit/2806e1b258dc3b1172c21a567f5d76328d855bb9)]
16
+ - fix(navigator): update climate impacts to climate hazards - refs #304609 [kreafox - [`cf2af49`](https://github.com/eea/volto-cca-policy/commit/cf2af49836f3b5a1b33621ae29650b14fb38c078)]
17
+
18
+ #### :nail_care: Enhancements
19
+
20
+ - refactor: update import paths for ToolThumbnail and TagOverflowPopup components [kreafox - [`c174abe`](https://github.com/eea/volto-cca-policy/commit/c174abeafcfb8040e43cb496a3f0b10747c057a8)]
21
+ - refactor(navigator): consolidate ToolThumbnail import paths and update related components [kreafox - [`5996b0b`](https://github.com/eea/volto-cca-policy/commit/5996b0b28814cb24c4167d9eb72cf6c632eb2a36)]
22
+
23
+ #### :house: Internal changes
24
+
25
+ - style: Automated code fix [eea-jenkins - [`851dcd2`](https://github.com/eea/volto-cca-policy/commit/851dcd27a6fd162e723b2e6e8fe542d8ab3bc8d1)]
26
+
7
27
  ### [1.0.25](https://github.com/eea/volto-cca-policy/compare/1.0.24...1.0.25) - 17 September 2026
8
28
 
9
29
  #### :rocket: New Features
@@ -441,7 +461,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
441
461
 
442
462
  #### :house: Internal changes
443
463
 
444
- - chore: [JENKINSFILE] sanitize sonarqube command Refs #305084 [valentinab25 - [`8106a44`](https://github.com/eea/volto-cca-policy/commit/8106a44e8f40dd360a274cede4b3f9c215d026cf)]
445
464
 
446
465
  #### :hammer_and_wrench: Others
447
466
 
@@ -772,7 +791,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
772
791
 
773
792
  #### :house: Internal changes
774
793
 
775
- - chore: [JENKINSFILE] sanitize sonarqube command Refs #305084 [valentinab25 - [`8106a44`](https://github.com/eea/volto-cca-policy/commit/8106a44e8f40dd360a274cede4b3f9c215d026cf)]
776
794
 
777
795
  #### :hammer_and_wrench: Others
778
796
 
@@ -1309,7 +1327,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
1309
1327
 
1310
1328
  #### :house: Internal changes
1311
1329
 
1312
- - chore: [JENKINSFILE] add package version in sonarqube [valentinab25 - [`e901251`](https://github.com/eea/volto-cca-policy/commit/e901251592eb54609fbc7eb8fcf7bd452c2da9cd)]
1313
1330
 
1314
1331
  ### [0.3.102](https://github.com/eea/volto-cca-policy/compare/0.3.101...0.3.102) - 24 February 2026
1315
1332
 
@@ -1319,7 +1336,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
1319
1336
 
1320
1337
  #### :house: Internal changes
1321
1338
 
1322
- - chore: [JENKINSFILE] use sonarqube branches [EEA Jenkins - [`8b3699a`](https://github.com/eea/volto-cca-policy/commit/8b3699a6cbaef662b5e80884ac2c1f7dc9c6591e)]
1323
1339
 
1324
1340
  ### [0.3.101](https://github.com/eea/volto-cca-policy/compare/0.3.100...0.3.101) - 28 January 2026
1325
1341
 
@@ -1607,7 +1623,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
1607
1623
  - style: fix item spacing [kreafox - [`7d4535d`](https://github.com/eea/volto-cca-policy/commit/7d4535dbc486e6cb80fc55d6ac8c7c01d9cf48af)]
1608
1624
  - chore: code cleanup [kreafox - [`842419b`](https://github.com/eea/volto-cca-policy/commit/842419b1bce3dc624755c81c9dea672198cab9e2)]
1609
1625
  - style: update teaser block styling [kreafox - [`1e0cad8`](https://github.com/eea/volto-cca-policy/commit/1e0cad8e1ed3ae827ee868dce8ad50b292a937ba)]
1610
- - chore: update Makefile, run yarn i18n [kreafox - [`61e6962`](https://github.com/eea/volto-cca-policy/commit/61e6962901068ae6512265417a730bd9befd65fe)]
1611
1626
  - chore: move styling to theme folder [kreafox - [`8cf6a1b`](https://github.com/eea/volto-cca-policy/commit/8cf6a1b8b14abf472a9c61b28db574f6d9e0bd3b)]
1612
1627
  - chore: remove ArrayWidget customization [kreafox - [`249bf93`](https://github.com/eea/volto-cca-policy/commit/249bf93054f7726c3d57a8b8ca01b75cd0d30522)]
1613
1628
  - chore: remove Footer customization [kreafox - [`7038af3`](https://github.com/eea/volto-cca-policy/commit/7038af37d48a328dfc31746f3fa84973e2f840ab)]
@@ -4370,13 +4385,10 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
4370
4385
  - Refs #260715 rast-block wip [Tripon Eugen - [`f19d54e`](https://github.com/eea/volto-cca-policy/commit/f19d54e0b9a6a86bf344eb85b6a1cda7f3de91bf)]
4371
4386
  - Refs #260715 rast-block wip [Tripon Eugen - [`2828537`](https://github.com/eea/volto-cca-policy/commit/2828537b6c084cd1a82162d552fb4ef025b71f9f)]
4372
4387
  - Refs #260715 rast-block updates [Tripon Eugen - [`1e803e5`](https://github.com/eea/volto-cca-policy/commit/1e803e5bd3d3fb7558f261c76c68866be7beb8b5)]
4373
- - test: [JENKINS] Use java17 for sonarqube scanner [valentinab25 - [`0a15e1b`](https://github.com/eea/volto-cca-policy/commit/0a15e1b2ad081233685e80d5b3c60a8663f6b896)]
4374
- - test: [JENKINS] Run cypress in started frontend container [valentinab25 - [`9554e44`](https://github.com/eea/volto-cca-policy/commit/9554e44c92a621a52b2adb5a4830fb084ee5734b)]
4375
4388
  ### [0.1.49](https://github.com/eea/volto-cca-policy/compare/0.1.48...0.1.49) - 15 November 2023
4376
4389
 
4377
4390
  #### :house: Internal changes
4378
4391
 
4379
- - chore: [JENKINS] Refactor automated testing [valentinab25 - [`7b820a6`](https://github.com/eea/volto-cca-policy/commit/7b820a6369c2ddd5203b1a4abe352cb4bb43db7a)]
4380
4392
  - chore: husky, lint-staged use fixed versions [valentinab25 - [`f0a8061`](https://github.com/eea/volto-cca-policy/commit/f0a8061c275c236deb00087c23fac9860a073106)]
4381
4393
 
4382
4394
  #### :hammer_and_wrench: Others
@@ -4393,9 +4405,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
4393
4405
  - Refs #259267 - jenkins test [Tripon Eugen - [`cacd31e`](https://github.com/eea/volto-cca-policy/commit/cacd31e7b1afe0983674ed5c7632d2e1d7fa752e)]
4394
4406
  - Refs #259267 - jenkins [Tripon Eugen - [`5b3affe`](https://github.com/eea/volto-cca-policy/commit/5b3affee8401239de10097884c1b7f2349d15ec0)]
4395
4407
  - Refs #259267 - add When, lead image and title to files [Tripon Eugen - [`2cedb23`](https://github.com/eea/volto-cca-policy/commit/2cedb237f898af9057e13fba94b615ef71077204)]
4396
- - test: [JENKINS] Add cpu limit on cypress docker [valentinab25 - [`4d607a5`](https://github.com/eea/volto-cca-policy/commit/4d607a576e9d0a5c34e48c41b409e7df616ee3d6)]
4397
- - test: [JENKINS] Increase shm-size to cypress docker [valentinab25 - [`b7f74d5`](https://github.com/eea/volto-cca-policy/commit/b7f74d53513a6edbfbca5cb6d19687929bb1e5db)]
4398
- - test: [JENKINS] Improve cypress time [valentinab25 - [`db65617`](https://github.com/eea/volto-cca-policy/commit/db656173391f65157098d95d388c25f6429753d8)]
4399
4408
  - Refs #259267 - cca event blocks attachments and check not mandatoty fields [Tripon Eugen - [`3138e5a`](https://github.com/eea/volto-cca-policy/commit/3138e5afb5bfbdbed14e27ed457b16867b7fa414)]
4400
4409
  - Refs #256681 - Fix error in CCA Event view menu. ([React Intl] An id must be provided to format a message.) [GhitaB - [`517eeb8`](https://github.com/eea/volto-cca-policy/commit/517eeb817264a47bbfd6b9b7d22aaf22d44ed224)]
4401
4410
  - Refs #161485 - Fix ECDE name conflict. [GhitaB - [`8bfd99f`](https://github.com/eea/volto-cca-policy/commit/8bfd99ff68bb82a04d1c0ed625fa514fcf46289e)]
@@ -4612,7 +4621,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
4612
4621
 
4613
4622
  #### :house: Internal changes
4614
4623
 
4615
- - chore: [JENKINS] Remove alpha testing version [valentinab25 - [`ad1ced0`](https://github.com/eea/volto-cca-policy/commit/ad1ced0971ba116c13a3b5fcc039172cc915c919)]
4616
4624
 
4617
4625
  #### :hammer_and_wrench: Others
4618
4626
 
@@ -5093,7 +5101,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
5093
5101
  #### :hammer_and_wrench: Others
5094
5102
 
5095
5103
  - Refs #158294 - Update supported languages list. [GhitaB - [`0a4f91f`](https://github.com/eea/volto-cca-policy/commit/0a4f91f39b7edc367bd4c127d6a8f273c7788361)]
5096
- - Add Sonarqube tag using cca-frontend addons list [EEA Jenkins - [`8f1f9ce`](https://github.com/eea/volto-cca-policy/commit/8f1f9ce6c22805670cc0800d3c779b6d619d0f31)]
5097
5104
  ### [0.1.1](https://github.com/eea/volto-cca-policy/compare/0.1.0...0.1.1) - 13 December 2022
5098
5105
 
5099
5106
  #### :hammer_and_wrench: Others
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-cca-policy",
3
- "version": "1.0.25",
3
+ "version": "1.0.26",
4
4
  "description": "@eeacms/volto-cca-policy: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -1,9 +1,10 @@
1
1
  import React from 'react';
2
- import { Checkbox, Icon, Popup } from 'semantic-ui-react';
2
+ import { Checkbox, Icon } from 'semantic-ui-react';
3
3
  import { defineMessages, useIntl } from 'react-intl';
4
4
  import ExternalLink from '@eeacms/search/components/Result/ExternalLink';
5
5
  import ResultContext from '@eeacms/search/components/Result/ResultContext';
6
- import ToolThumbnail from '../../theme/ToolThumbnail/ToolThumbnail';
6
+ import TagOverflowPopup from '@eeacms/volto-cca-policy/components/theme/TagOverflowPopup';
7
+ import ToolThumbnail from '@eeacms/volto-cca-policy/components/theme/ToolThumbnail/ToolThumbnail';
7
8
  import { getToolThumbnailUrl } from '../../theme/ToolThumbnail/utils';
8
9
  import {
9
10
  getCompareToolTitle,
@@ -78,27 +79,10 @@ const TagGroup = ({ typeLabel, values, type, maxItems }) => {
78
79
  </span>
79
80
  ))}
80
81
  {remaining > 0 && (
81
- <Popup
82
- className="catalogue-tag-popup"
83
- content={
84
- <div className="catalogue-tag-tooltip">
85
- <ul>
86
- {hidden.map((value) => (
87
- <li key={`${type}-hidden-${value}`}>{value}</li>
88
- ))}
89
- </ul>
90
- </div>
91
- }
92
- position="bottom left"
93
- trigger={
94
- <button
95
- type="button"
96
- className={`navigator-tag ${type} more`}
97
- aria-label={`${typeLabel}: ${hidden.join(', ')}`}
98
- >
99
- + {remaining}
100
- </button>
101
- }
82
+ <TagOverflowPopup
83
+ items={hidden}
84
+ className={`navigator-tag ${type} more`}
85
+ ariaLabel={`${typeLabel}: ${hidden.join(', ')}`}
102
86
  />
103
87
  )}
104
88
  </div>
@@ -107,6 +91,7 @@ const TagGroup = ({ typeLabel, values, type, maxItems }) => {
107
91
 
108
92
  const CycleElements = ({ intl, values }) => {
109
93
  const visible = values.slice(0, 3);
94
+ const hidden = values.slice(3);
110
95
 
111
96
  if (!visible.length) return null;
112
97
 
@@ -123,6 +108,13 @@ const CycleElements = ({ intl, values }) => {
123
108
  {value}
124
109
  </span>
125
110
  ))}
111
+ {hidden.length > 0 && (
112
+ <TagOverflowPopup
113
+ items={hidden}
114
+ className="navigator-tag cycle-element more"
115
+ ariaLabel={`${intl.formatMessage(messages.cycle)}: ${hidden.join(', ')}`}
116
+ />
117
+ )}
126
118
  </div>
127
119
  );
128
120
  };
@@ -141,7 +133,7 @@ const NavigatorCatalogueCardItem = (props) => {
141
133
  .join(', ');
142
134
  const toolProvider = result?._result?.tool_provider?.raw;
143
135
  const adaptationSupportCycleSteps = rawValueAsArray(
144
- result.adaptation_support_cycle_step,
136
+ result.cca_adaptation_support_cycle_step,
145
137
  )
146
138
  .map((value) => {
147
139
  const title = value?.title || value;
@@ -94,7 +94,7 @@ describe('NavigatorCatalogueCardItem', () => {
94
94
  'Datasets and indicators',
95
95
  ],
96
96
  },
97
- adaptation_support_cycle_step: {
97
+ cca_adaptation_support_cycle_step: {
98
98
  raw: [
99
99
  { title: 'Step 1: Preparing the ground' },
100
100
  { title: 'Step 2: Assessing risks' },
@@ -131,7 +131,10 @@ describe('NavigatorCatalogueCardItem', () => {
131
131
  expect(screen.getByText('Resilience')).toBeInTheDocument();
132
132
  expect(screen.getByText('Adaptation')).toBeInTheDocument();
133
133
  expect(screen.getByText('Step 1')).toBeInTheDocument();
134
- expect(screen.queryByText('Step 4')).not.toBeInTheDocument();
134
+ expect(
135
+ screen.getByRole('button', { name: 'Cycle: Step 4' }),
136
+ ).toHaveTextContent('+ 1');
137
+ expect(screen.getByText('Step 4')).toBeInTheDocument();
135
138
  expect(
136
139
  screen.getByTitle(
137
140
  'Maps and graphs, Reports and decision support, Datasets and indicators',
@@ -152,6 +155,22 @@ describe('NavigatorCatalogueCardItem', () => {
152
155
  });
153
156
  });
154
157
 
158
+ it('shows the cycle steps from the field used by the catalogue filter', () => {
159
+ renderCard({
160
+ title: 'Climate planning tool',
161
+ href: 'https://example.com/tool',
162
+ cca_adaptation_support_cycle_step: {
163
+ raw: ['Step 2: Assessing risks'],
164
+ },
165
+ adaptation_support_cycle_step: {
166
+ raw: [{ title: 'Step 1: Preparing the ground' }],
167
+ },
168
+ });
169
+
170
+ expect(screen.getByText('Step 2')).toBeInTheDocument();
171
+ expect(screen.queryByText('Step 1')).not.toBeInTheDocument();
172
+ });
173
+
155
174
  it('renders sparse results and disables comparison without a UID', () => {
156
175
  useCompareTools.mockReturnValue({
157
176
  isSelected: true,
@@ -6,10 +6,11 @@ import { defineMessages, useIntl } from 'react-intl';
6
6
  import { Button, Checkbox, Icon, Loader, Message } from 'semantic-ui-react';
7
7
  import URLManager from '@elastic/search-ui/lib/cjs/URLManager';
8
8
  import { useSearchContext } from '@eeacms/search/lib/hocs';
9
- import ToolThumbnail from '../../theme/ToolThumbnail/ToolThumbnail';
9
+ import ToolThumbnail from '@eeacms/volto-cca-policy/components/theme/ToolThumbnail/ToolThumbnail';
10
10
  import guideSteps from '../../../search/navigator_guide/guideSteps';
11
11
  import { navigatorGuideStepAtom } from '../../../state';
12
- import { mergeGuideOptions } from './utils';
12
+ import { mergeGuideOptions, sortAdaptationSteps } from './utils';
13
+ import { rawValueAsArray } from '../NavigatorCatalogue/utils';
13
14
  import useGuideFacetOptions from './useGuideFacetOptions';
14
15
  import { getNavigatorCataloguePageURL } from '../../Search/NavigatorCatalogue/utils';
15
16
 
@@ -95,7 +96,7 @@ const isStepSelected = (filters, field) =>
95
96
 
96
97
  const previewTagTypes = {
97
98
  adaptationSectors: 'sector',
98
- climateImpacts: 'hazard',
99
+ climateHazards: 'hazard',
99
100
  adaptationStage: 'adaptation-stage',
100
101
  coverage: 'coverage',
101
102
  };
@@ -130,31 +131,39 @@ const NavigatorGuideContentView = ({ appConfig }) => {
130
131
  const hasSelections = steps.some(({ field }) =>
131
132
  isStepSelected(filters, field),
132
133
  );
133
- const options = mergeGuideOptions(
134
+ const mergedOptions = mergeGuideOptions(
134
135
  allFacetOptions?.[step?.field],
135
136
  getFacetOptions(facets, step?.field),
136
137
  selectedValues,
137
138
  hasSelections,
138
139
  );
140
+ const options =
141
+ step?.id === 'adaptationStage'
142
+ ? sortAdaptationSteps(mergedOptions)
143
+ : mergedOptions;
139
144
  const isLastStep = activeStep === steps.length - 1;
140
145
  const selectedStepLabels = steps
141
146
  .filter(({ field }) => isStepSelected(filters, field))
142
147
  .map(({ label }) =>
143
148
  intl.formatMessage(label).toLocaleLowerCase(currentLang),
144
149
  );
145
- const selectedPreviewTags = steps.flatMap((item) => {
146
- const values =
147
- (filters || []).find((filter) => filter.field === item.field)?.values ||
148
- [];
150
+ const selectedPreviewTags = (result) =>
151
+ steps.flatMap((item) => {
152
+ const values =
153
+ (filters || []).find((filter) => filter.field === item.field)?.values ||
154
+ [];
149
155
 
150
- return values.map((value) => ({
151
- label: item.id === 'adaptationStage' ? value.split(':')[0] : value,
152
- type: previewTagTypes[item.id],
153
- }));
154
- });
155
- const visiblePreviewTags = selectedPreviewTags.slice(0, 3);
156
- const remainingPreviewTags =
157
- selectedPreviewTags.length - visiblePreviewTags.length;
156
+ const resultValues = rawValueAsArray(
157
+ result[item.field.replace('.keyword', '')],
158
+ ).map((value) => value?.title || value);
159
+
160
+ return values
161
+ .filter((value) => resultValues.includes(value))
162
+ .map((value) => ({
163
+ label: item.id === 'adaptationStage' ? value.split(':')[0] : value,
164
+ type: previewTagTypes[item.id],
165
+ }));
166
+ });
158
167
 
159
168
  React.useEffect(() => {
160
169
  if (storedActiveStep !== activeStep) {
@@ -204,88 +213,94 @@ const NavigatorGuideContentView = ({ appConfig }) => {
204
213
 
205
214
  <div className="navigator-guide-layout">
206
215
  <section className="navigator-guide-wizard">
207
- <div className="navigator-guide-progress">
208
- {steps.map((item, index) => (
209
- <React.Fragment key={item.id}>
210
- <Button
211
- className={`navigator-guide-progress-step${
212
- index === activeStep ? ' active' : ''
213
- }${index < activeStep ? ' completed' : ''}`}
214
- aria-current={index === activeStep ? 'step' : undefined}
215
- onClick={() => setActiveStep(index)}
216
- >
217
- <span>
218
- {isStepSelected(filters, item.field) ? (
219
- <Icon className="ri-check-line" />
220
- ) : (
221
- index + 1
216
+ <div className="navigator-guide-wizard-content">
217
+ <div className="navigator-guide-progress-wrapper">
218
+ <div className="navigator-guide-progress">
219
+ {steps.map((item, index) => (
220
+ <React.Fragment key={item.id}>
221
+ <Button
222
+ className={`navigator-guide-progress-step${
223
+ index === activeStep ? ' active' : ''
224
+ }${index < activeStep ? ' completed' : ''}`}
225
+ aria-current={index === activeStep ? 'step' : undefined}
226
+ onClick={() => setActiveStep(index)}
227
+ >
228
+ <span>
229
+ {isStepSelected(filters, item.field) ? (
230
+ <Icon className="ri-check-line" />
231
+ ) : (
232
+ index + 1
233
+ )}
234
+ </span>
235
+ {intl.formatMessage(item.label)}
236
+ </Button>
237
+ {index < steps.length - 1 && (
238
+ <span
239
+ className={`navigator-guide-progress-connector${
240
+ index < activeStep ? ' completed' : ''
241
+ }`}
242
+ aria-hidden="true"
243
+ />
222
244
  )}
223
- </span>
224
- {intl.formatMessage(item.label)}
225
- </Button>
226
- {index < steps.length - 1 && (
227
- <span
228
- className={`navigator-guide-progress-connector${
229
- index < activeStep ? ' completed' : ''
230
- }`}
231
- aria-hidden="true"
232
- />
233
- )}
234
- </React.Fragment>
235
- ))}
236
- </div>
237
- <div
238
- className="navigator-guide-progress-bar"
239
- role="progressbar"
240
- aria-valuemin="1"
241
- aria-valuemax={steps.length}
242
- aria-valuenow={activeStep + 1}
243
- >
244
- <div
245
- className="navigator-guide-progress-bar-fill"
246
- style={{ width: `${((activeStep + 1) / steps.length) * 100}%` }}
247
- />
248
- </div>
245
+ </React.Fragment>
246
+ ))}
247
+ </div>
248
+ <div
249
+ className="navigator-guide-progress-bar"
250
+ role="progressbar"
251
+ aria-valuemin="1"
252
+ aria-valuemax={steps.length}
253
+ aria-valuenow={activeStep + 1}
254
+ >
255
+ <div
256
+ className="navigator-guide-progress-bar-fill"
257
+ style={{
258
+ width: `${((activeStep + 1) / steps.length) * 100}%`,
259
+ }}
260
+ />
261
+ </div>
262
+ <div className="navigator-guide-step-meta">
263
+ <span className="navigator-guide-step-number">
264
+ {intl.formatMessage(messages.stepProgress, {
265
+ current: activeStep + 1,
266
+ total: steps.length,
267
+ })}
268
+ </span>
269
+ <span>{intl.formatMessage(messages.selectAllThatApply)}</span>
270
+ </div>
271
+ </div>
249
272
 
250
- <div className="navigator-guide-step-meta">
251
- <span className="navigator-guide-step-number">
252
- {intl.formatMessage(messages.stepProgress, {
253
- current: activeStep + 1,
254
- total: steps.length,
255
- })}
256
- </span>
257
- <span>{intl.formatMessage(messages.selectAllThatApply)}</span>
258
- </div>
259
- <h3>{intl.formatMessage(step.title)}</h3>
260
- {step.description && <p>{intl.formatMessage(step.description)}</p>}
273
+ <h3>{intl.formatMessage(step.title)}</h3>
274
+ {step.description && <p>{intl.formatMessage(step.description)}</p>}
261
275
 
262
- {isLoading ? (
263
- <div className="navigator-guide-options-loading">
264
- <Loader active inline />
265
- </div>
266
- ) : options.length > 0 ? (
267
- <div className="navigator-guide-options">
268
- {options.map((option) => (
269
- <label
270
- key={option.value}
271
- className={`navigator-guide-option${
272
- selectedValues.includes(option.value) ? ' selected' : ''
273
- }${option.disabled ? ' disabled' : ''}`}
274
- aria-disabled={option.disabled || undefined}
275
- >
276
- <Checkbox
277
- checked={selectedValues.includes(option.value)}
278
- disabled={option.disabled}
279
- onChange={() => toggleValue(option.value)}
280
- />
281
- <span>{option.value}</span>
282
- <small>{option.count}</small>
283
- </label>
284
- ))}
285
- </div>
286
- ) : (
287
- <Message>{intl.formatMessage(messages.noOptions)}</Message>
288
- )}
276
+ {isLoading ? (
277
+ <div className="navigator-guide-options-loading">
278
+ <Loader active inline />
279
+ </div>
280
+ ) : options.length > 0 ? (
281
+ <div className="navigator-guide-options">
282
+ {options.map((option) => (
283
+ <label
284
+ key={option.value}
285
+ className={`navigator-guide-option${
286
+ selectedValues.includes(option.value) ? ' selected' : ''
287
+ }${option.disabled ? ' disabled' : ''}`}
288
+ aria-disabled={option.disabled || undefined}
289
+ >
290
+ <Checkbox
291
+ checked={selectedValues.includes(option.value)}
292
+ disabled={option.disabled}
293
+ onChange={() => toggleValue(option.value)}
294
+ />
295
+ <span>{option.value}</span>
296
+ <small>{option.count}</small>
297
+ </label>
298
+ ))}
299
+ </div>
300
+ ) : (
301
+ <Message>{intl.formatMessage(messages.noOptions)}</Message>
302
+ )}
303
+ </div>
289
304
 
290
305
  <div className="navigator-guide-actions">
291
306
  <Button
@@ -346,53 +361,56 @@ const NavigatorGuideContentView = ({ appConfig }) => {
346
361
  <div className="navigator-guide-preview-results">
347
362
  {(results || [])
348
363
  .slice(0, appConfig.previewResultsLimit)
349
- .map((result) => (
350
- <div
351
- className="navigator-guide-preview-result"
352
- key={result._original?._id || result.href}
353
- >
354
- <ToolThumbnail
355
- result={result}
356
- fallbackIcon="ri-stack-line"
357
- />
358
- <div className="navigator-guide-preview-result-content">
359
- <small
360
- className="navigator-tool-provider"
361
- title={result?._result?.tool_provider?.raw}
362
- >
363
- {result?._result?.tool_provider?.raw}
364
- </small>
365
- <a
366
- href={result.href}
367
- target="_blank"
368
- rel="noopener noreferrer"
369
- className="navigator-guide-preview-result-title"
370
- title={result.title}
371
- >
372
- <h5>{result.title}</h5>
373
- </a>
374
- {selectedPreviewTags.length > 0 && (
375
- <div className="navigator-guide-preview-tags">
376
- {visiblePreviewTags.map(
377
- ({ label, type }, index) => (
364
+ .map((result) => {
365
+ const tags = selectedPreviewTags(result);
366
+ const visibleTags = tags.slice(0, 3);
367
+ const remainingTags = tags.length - visibleTags.length;
368
+ return (
369
+ <div
370
+ className="navigator-guide-preview-result"
371
+ key={result._original?._id || result.href}
372
+ >
373
+ <ToolThumbnail
374
+ result={result}
375
+ fallbackIcon="ri-stack-line"
376
+ />
377
+ <div className="navigator-guide-preview-result-content">
378
+ <small
379
+ className="navigator-tool-provider"
380
+ title={result?._result?.tool_provider?.raw}
381
+ >
382
+ {result?._result?.tool_provider?.raw}
383
+ </small>
384
+ <a
385
+ href={result.href}
386
+ target="_blank"
387
+ rel="noopener noreferrer"
388
+ className="navigator-guide-preview-result-title"
389
+ title={result.title}
390
+ >
391
+ <h5>{result.title}</h5>
392
+ </a>
393
+ {tags.length > 0 && (
394
+ <div className="navigator-guide-preview-tags">
395
+ {visibleTags.map(({ label, type }, index) => (
378
396
  <span
379
397
  className={`navigator-tag ${type}`}
380
398
  key={`${type}-${label}-${index}`}
381
399
  >
382
400
  {label}
383
401
  </span>
384
- ),
385
- )}
386
- {remainingPreviewTags > 0 && (
387
- <span className="navigator-guide-preview-tag-more">
388
- + {remainingPreviewTags}
389
- </span>
390
- )}
391
- </div>
392
- )}
402
+ ))}
403
+ {remainingTags > 0 && (
404
+ <span className="navigator-guide-preview-tag-more">
405
+ + {remainingTags}
406
+ </span>
407
+ )}
408
+ </div>
409
+ )}
410
+ </div>
393
411
  </div>
394
- </div>
395
- ))}
412
+ );
413
+ })}
396
414
  </div>
397
415
  <Button
398
416
  labelPosition="right"