@eeacms/volto-cca-policy 0.2.69 → 0.2.70

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 (22) hide show
  1. package/CHANGELOG.md +28 -8
  2. package/package.json +1 -1
  3. package/src/components/Result/ClusterHorizontalCardItem.jsx +136 -0
  4. package/src/components/manage/Blocks/C3SIndicatorsGlossaryBlock/C3SIndicatorsGlossaryBlockView.test.jsx +34 -0
  5. package/src/components/manage/Blocks/C3SIndicatorsListingBlock/C3SIndicatorsListingBlockView.test.jsx +43 -0
  6. package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyExplorerEdit.test.jsx +89 -0
  7. package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyExplorerView.test.jsx +93 -0
  8. package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyMap.jsx +13 -79
  9. package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyMap.test.jsx +131 -0
  10. package/src/components/manage/Blocks/CaseStudyExplorer/FeatureDisplay.jsx +5 -1
  11. package/src/components/manage/Blocks/CaseStudyExplorer/FeatureDisplay.test.jsx +59 -0
  12. package/src/components/manage/Blocks/CaseStudyExplorer/FeatureInteraction.jsx +132 -53
  13. package/src/components/manage/Blocks/CaseStudyExplorer/styles.less +4 -0
  14. package/src/components/manage/Blocks/CaseStudyExplorer/useInteractiveStyles.jsx +189 -0
  15. package/src/components/manage/Blocks/MKHMap/InfoOverlay.jsx +20 -8
  16. package/src/components/manage/Blocks/MKHMap/View.jsx +1 -1
  17. package/src/components/theme/ImageGallery/styles.less +1 -1
  18. package/src/index.js +4 -1
  19. package/src/search/config.js +79 -26
  20. package/src/search/facets.js +12 -1
  21. package/src/search/views.js +15 -0
  22. package/src/components/manage/Blocks/CaseStudyExplorer/InfoOverlay.jsx +0 -80
@@ -4,13 +4,25 @@ import { openlayers as ol } from '@eeacms/volto-openlayers-map';
4
4
  import FeatureDisplay from './FeatureDisplay';
5
5
  import { usePrevious } from '@plone/volto/helpers/Utils/usePrevious';
6
6
 
7
- export default function InfoOverlay({ selectedFeature, layerId }) {
7
+ const isCluster = (features) => {
8
+ return features.length > 1 ? true : features[0].values_?.features?.length > 1;
9
+ };
10
+
11
+ export default function InfoOverlay({
12
+ selectedFeature,
13
+ onFeatureSelect,
14
+ layerId,
15
+ hasCusters = false,
16
+ }) {
8
17
  const { map } = useMapContext();
9
18
  const [tooltip, setTooltipRef] = React.useState();
10
19
  const [showTooltip, setShowTooltip] = React.useState();
11
20
 
12
21
  const prevLayerId = usePrevious(layerId);
13
22
 
23
+ const [isClient, setIsClient] = React.useState(false);
24
+ React.useEffect(() => setIsClient(true), []);
25
+
14
26
  React.useEffect(() => {
15
27
  if (prevLayerId && layerId !== prevLayerId) {
16
28
  setShowTooltip(false);
@@ -23,7 +35,7 @@ export default function InfoOverlay({ selectedFeature, layerId }) {
23
35
  const overlay = new ol.Overlay({
24
36
  element: document.getElementById('popup-overlay'),
25
37
  positioning: 'bottom-center',
26
- offset: [0, -10],
38
+ offset: [10, -10],
27
39
  stopEvent: false,
28
40
  });
29
41
  map.addOverlay(overlay);
@@ -33,11 +45,14 @@ export default function InfoOverlay({ selectedFeature, layerId }) {
33
45
  const { pixel, target } = evt;
34
46
  const features = target.getFeaturesAtPixel(pixel);
35
47
 
36
- if (features.length) {
48
+ if (features.length && (hasCusters ? !isCluster(features) : true)) {
37
49
  overlay.setPosition(coordinate);
38
50
  setShowTooltip(true);
39
51
  } else {
52
+ // handle a click in an overlay popup
53
+ if (evt.originalEvent.target.tagName === 'A') return;
40
54
  setShowTooltip(false);
55
+ onFeatureSelect(null);
41
56
  }
42
57
  }
43
58
 
@@ -47,10 +62,7 @@ export default function InfoOverlay({ selectedFeature, layerId }) {
47
62
  map.un('click', handler);
48
63
  map.removeOverlay(overlay);
49
64
  };
50
- }, [map, tooltip]); //
51
-
52
- const [isClient, setIsClient] = React.useState(false);
53
- React.useEffect(() => setIsClient(true), []);
65
+ }, [map, tooltip, onFeatureSelect, hasCusters]);
54
66
 
55
67
  return isClient ? (
56
68
  <div
@@ -62,7 +74,7 @@ export default function InfoOverlay({ selectedFeature, layerId }) {
62
74
  }}
63
75
  ref={setTooltipRef}
64
76
  >
65
- <FeatureDisplay feature={selectedFeature} />
77
+ {selectedFeature ? <FeatureDisplay feature={selectedFeature} /> : null}
66
78
  </div>
67
79
  ) : null;
68
80
  }
@@ -11,7 +11,7 @@ import { openlayers as ol } from '@eeacms/volto-openlayers-map';
11
11
 
12
12
  import * as layers from './layers';
13
13
  import FeatureInteraction from './FeatureInteraction';
14
- import InfoOverlay from '@eeacms/volto-cca-policy/components/manage/Blocks/CaseStudyExplorer/InfoOverlay';
14
+ import InfoOverlay from './InfoOverlay';
15
15
 
16
16
  import './styles.less';
17
17
 
@@ -9,7 +9,7 @@
9
9
  bottom: 0em;
10
10
  left: 0em;
11
11
  padding: 10px;
12
- background: rgba(0, 0, 0, 0.5); /* optional: semi-transparent background */
12
+ // background: rgba(0, 0, 0, 0.5); /* optional: semi-transparent background */
13
13
  color: white; /* text color */
14
14
  font-size: 14px; /* adjust font size as needed */
15
15
  text-align: left; /* optional: center the text */
package/src/index.js CHANGED
@@ -22,6 +22,7 @@ import GeocharsWidget from './components/theme/Widgets/GeocharsWidget';
22
22
  import GeolocationWidget from './components/theme/Widgets/GeolocationWidget';
23
23
  import MigrationButtons from './components/MigrationButtons';
24
24
  import HealthHorizontalCardItem from './components/Result/HealthHorizontalCardItem';
25
+ import ClusterHorizontalCardItem from './components/Result/ClusterHorizontalCardItem';
25
26
 
26
27
  import { langRedirection } from './store/middleware';
27
28
 
@@ -339,7 +340,9 @@ const applyConfig = (config) => {
339
340
  config.settings.searchlib.resolve.HealthHorizontalCardItem = {
340
341
  component: HealthHorizontalCardItem,
341
342
  };
342
-
343
+ config.settings.searchlib.resolve.ClusterHorizontalCardItem = {
344
+ component: ClusterHorizontalCardItem,
345
+ };
343
346
  // Custom widgets
344
347
  config.widgets.id.geochars = GeocharsWidget;
345
348
  config.widgets.id.geolocation = GeolocationWidget;
@@ -1,27 +1,65 @@
1
1
  import { mergeConfig } from '@eeacms/search';
2
- import { build_runtime_mappings } from '@eeacms/volto-globalsearch/utils';
3
2
  import { getClientProxyAddress } from './utils';
4
3
  import vocabs from './vocabulary';
5
4
 
6
5
  import facets from './facets';
6
+ import views from './views';
7
7
 
8
8
  const ccaConfig = {
9
9
  title: 'ClimateAdapt Main',
10
+ ...views,
10
11
  };
11
12
 
12
13
  export const clusters = {
13
14
  name: 'op_cluster',
14
- field: 'objectProvides',
15
+ // field: 'objectProvides',
15
16
  clusters: [
16
- // {
17
- // name: 'Type1',
18
- // icon: { name: 'bullhorn' },
19
- // values: ['Video', 'Guidance'],
20
- // defaultResultView: 'horizontalCard',
21
- // },
22
- ],
17
+ {
18
+ name: 'Climate-ADAPT',
19
+ icon: { name: 'file text' },
20
+ values: ['climate'],
21
+ },
22
+ {
23
+ name: 'Health Observatory',
24
+ icon: { name: 'compass' },
25
+ values: ['observatory'],
26
+ },
27
+ {
28
+ name: 'Mission Portal',
29
+ icon: { name: 'compass' },
30
+ values: ['mission'],
31
+ },
32
+ ].map((cluster) => ({
33
+ ...cluster,
34
+ defaultResultView: 'ClusterHorizontalCardItem',
35
+ })),
36
+ };
37
+
38
+ // console.log('clusters default', clusters, build_runtime_mappings(clusters));
39
+ // console.log(
40
+ // 'clusters mission',
41
+ // clusters_mission,
42
+ // build_runtime_mappings(clusters_mission),
43
+ // );
44
+
45
+ const cca_build_runtime_mappings = {};
46
+ cca_build_runtime_mappings['op_cluster'] = {
47
+ type: 'keyword',
48
+ script: {
49
+ source:
50
+ // "emit('_all_'); if (doc['cca_include_in_search_observatory'][0]) {emit('Health Observatory')} if (doc['cca_include_in_mission.keyword'][0].toString() == 'true') {emit('Mission Portal')} else {emit('Climate-ADAPT')}",
51
+ // "emit('_all_'); if (doc['cca_include_in_search_observatory'][0]) {emit('Health Observatory')} if (doc['cca_include_in_mission.keyword'][0].toString() == 'true' or (doc['id.keyword'].length==1 and doc['id.keyword'][0].toString().indexOf('https://climate-adapt.eea.europa.eu/en/mission')==0)) {emit('Mission Portal')} else {emit('Climate adapt')}",
52
+ // "def objectProvides = ['Adaptation option','Case study','Guidance','Video','Indicator','Information portal','Organisation','Publication reference','Research and knowledge project','Video','Tool'];def vals = doc['objectProvides'];for (defVal in objectProvides) {for (objVal in vals) {if (objVal.contains(defVal)) {emit('Climate-ADAPT')}}}emit('_all_');if (doc['cca_include_in_search_observatory'][0]) {emit('Health Observatory')} if (doc['cca_include_in_mission.keyword'][0].toString() == 'true') {emit('Mission Portal')} else {if (doc['id.keyword'].length==1) { if(doc['id.keyword'][0].toString().contains('climate-adapt.eea.europa.eu/en/mission')) {emit('Mission Portal')}}}",
53
+ "def objectProvides = ['Adaptation option','Case study','Guidance','Video','Indicator','Information portal','Organisation','Publication reference','Research and knowledge project','Video','Tool'];def vals = doc['objectProvides'];for (defVal in objectProvides) {for (objVal in vals) {if (objVal.contains(defVal)) {emit('Climate-ADAPT')}}}emit('_all_');if (doc['cca_include_in_search_observatory'][0]) {for (defVal in objectProvides) {for (objVal in vals) {if (objVal.contains(defVal)){emit('Health Observatory')}}}} if (doc['cca_include_in_mission.keyword'][0].toString() == 'true') {emit('Mission Portal')} else {if (doc['id.keyword'].length==1) { if(doc['id.keyword'][0].toString().contains('climate-adapt.eea.europa.eu/en/mission')) {emit('Mission Portal')}}}",
54
+ },
23
55
  };
24
56
 
57
+ // const mapping = {};
58
+ // mapping[settings.name] = {
59
+ // type: 'keyword',
60
+ // script: { source: source },
61
+ // };
62
+
25
63
  export default function installMainSearch(config) {
26
64
  const envConfig = ccaConfig;
27
65
 
@@ -30,41 +68,56 @@ export default function installMainSearch(config) {
30
68
  envConfig.app_name = pjson.name;
31
69
  envConfig.app_version = pjson.version;
32
70
 
71
+ // console.log('config.searchui.ccaSearch clusers', clusters);
72
+ // debugger;
33
73
  config.searchui.ccaSearch = {
34
74
  ...mergeConfig(envConfig, config.searchui.globalsearchbase),
35
75
  elastic_index: '_es/globalsearch',
36
76
  index_name: 'data_searchui',
37
77
  host: process.env.RAZZLE_ES_PROXY_ADDR || 'http://localhost:3000',
38
- runtime_mappings: build_runtime_mappings(clusters),
78
+ runtime_mappings: cca_build_runtime_mappings,
39
79
  ...vocabs,
40
80
  };
41
81
 
42
82
  const { ccaSearch } = config.searchui;
43
83
 
84
+ ccaSearch.contentSectionsParams = {
85
+ enable: true,
86
+ sectionFacetsField: 'op_cluster',
87
+ sections: clusters.clusters,
88
+ clusterMapping: Object.assign(
89
+ {},
90
+ ...clusters.clusters.map(({ name, values }) =>
91
+ Object.assign({}, ...values.map((v) => ({ [v]: name }))),
92
+ ),
93
+ ),
94
+ };
95
+
44
96
  ccaSearch.permanentFilters.push({
45
97
  term: {
46
98
  cluster_name: 'cca',
47
99
  },
48
100
  });
49
101
 
50
- ccaSearch.permanentFilters.push({
51
- terms: {
52
- objectProvides: [
53
- 'Adaptation option',
54
- 'Case study',
55
- 'Guidance',
56
- 'Video',
57
- 'Indicator',
58
- 'Information portal',
59
- 'Organisation',
60
- 'Publication reference',
61
- 'Research and knowledge project',
62
- 'Tool',
63
- ],
64
- },
65
- });
102
+ // ccaSearch.permanentFilters.push({
103
+ // terms: {
104
+ // objectProvides: [
105
+ // 'Adaptation option',
106
+ // 'Case study',
107
+ // 'Guidance',
108
+ // 'Video',
109
+ // 'Indicator',
110
+ // 'Information portal',
111
+ // 'Organisation',
112
+ // 'Publication reference',
113
+ // 'Research and knowledge project',
114
+ // 'Tool',
115
+ // ],
116
+ // },
117
+ // });
66
118
 
67
119
  ccaSearch.facets = facets;
120
+ // console.log('ccaSearch.facets', ccaSearch.facets);
68
121
 
69
122
  ccaSearch.initialView.tilesLandingPageParams.sections = [
70
123
  {
@@ -18,7 +18,17 @@ const adaptation_sectors = {
18
18
  showAllOptions: true,
19
19
  alwaysVisible: true,
20
20
  };
21
-
21
+ const op_cluster = {
22
+ field: 'op_cluster',
23
+ factory: 'MultiTermFacet',
24
+ isFilterable: true,
25
+ isMulti: true,
26
+ label: 'Section',
27
+ show: 10000,
28
+ showInFacetsList: false,
29
+ ignoreNLPWhenActive: true,
30
+ blacklist: ['Others', 'Publications'],
31
+ };
22
32
  // const clusters = {
23
33
  // field: 'op_cluster',
24
34
  // factory: 'MultiTermFacet',
@@ -113,6 +123,7 @@ const origin_websites = {
113
123
  const facets = [
114
124
  adaptation_sectors,
115
125
  // clusters,
126
+ op_cluster,
116
127
  objectProvides,
117
128
  issued_date,
118
129
  climate_impacts,
@@ -0,0 +1,15 @@
1
+ export default {
2
+ resultViews: [
3
+ {
4
+ id: 'ClusterHorizontalCardItem',
5
+ title: 'Cluster Climate catalogue items',
6
+ icon: 'bars',
7
+ render: null,
8
+ isDefault: true,
9
+ factories: {
10
+ view: 'HorizontalCard.Group',
11
+ item: 'ClusterHorizontalCardItem',
12
+ },
13
+ },
14
+ ],
15
+ };
@@ -1,80 +0,0 @@
1
- import React from 'react';
2
- import { useMapContext } from '@eeacms/volto-openlayers-map/api';
3
- import { openlayers as ol } from '@eeacms/volto-openlayers-map';
4
- import FeatureDisplay from './FeatureDisplay';
5
- import { usePrevious } from '@plone/volto/helpers/Utils/usePrevious';
6
-
7
- const isCluster = (features) => {
8
- return features.length > 1 ? true : features[0].values_?.features?.length > 1;
9
- };
10
-
11
- export default function InfoOverlay({
12
- selectedFeature,
13
- onFeatureSelect,
14
- layerId,
15
- hasCusters = false,
16
- }) {
17
- const { map } = useMapContext();
18
- const [tooltip, setTooltipRef] = React.useState();
19
- const [showTooltip, setShowTooltip] = React.useState();
20
-
21
- const prevLayerId = usePrevious(layerId);
22
-
23
- const [isClient, setIsClient] = React.useState(false);
24
- React.useEffect(() => setIsClient(true), []);
25
-
26
- React.useEffect(() => {
27
- if (prevLayerId && layerId !== prevLayerId) {
28
- setShowTooltip(false);
29
- }
30
- }, [layerId, prevLayerId]);
31
-
32
- React.useEffect(() => {
33
- if (!(map && tooltip)) return;
34
-
35
- const overlay = new ol.Overlay({
36
- element: document.getElementById('popup-overlay'),
37
- positioning: 'bottom-center',
38
- offset: [10, -10],
39
- stopEvent: false,
40
- });
41
- map.addOverlay(overlay);
42
-
43
- function handler(evt) {
44
- const coordinate = evt.coordinate;
45
- const { pixel, target } = evt;
46
- const features = target.getFeaturesAtPixel(pixel);
47
-
48
- if (features.length && (hasCusters ? !isCluster(features) : true)) {
49
- overlay.setPosition(coordinate);
50
- setShowTooltip(true);
51
- } else {
52
- // handle a click in an overlay popup
53
- if (evt.originalEvent.target.tagName === 'A') return;
54
- setShowTooltip(false);
55
- onFeatureSelect(null);
56
- }
57
- }
58
-
59
- map.on('click', handler);
60
-
61
- return () => {
62
- map.un('click', handler);
63
- map.removeOverlay(overlay);
64
- };
65
- }, [map, tooltip, onFeatureSelect, hasCusters]);
66
-
67
- return isClient ? (
68
- <div
69
- id="popup-overlay"
70
- style={{
71
- position: 'absolute',
72
- zIndex: 1,
73
- visibility: showTooltip ? 'visible' : 'hidden',
74
- }}
75
- ref={setTooltipRef}
76
- >
77
- {selectedFeature ? <FeatureDisplay feature={selectedFeature} /> : null}
78
- </div>
79
- ) : null;
80
- }