@eeacms/volto-clms-theme 1.0.68 → 1.0.69

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 (26) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/jest-addon.config.js +1 -1
  3. package/package.json +3 -2
  4. package/src/actions/import_wms_layers/import_wms_layers.js +20 -0
  5. package/src/actions/import_wms_layers/import_wms_layers.test.js +15 -0
  6. package/src/actions/index.js +5 -0
  7. package/src/components/Blocks/CustomTemplates/VoltoListingBlock/CclListingCards.jsx +1 -1
  8. package/src/components/Blocks/CustomTemplates/VoltoSearchBlock/DoubleRangeFacet.jsx +74 -0
  9. package/src/components/Blocks/CustomTemplates/VoltoSearchBlock/FilterList.jsx +57 -0
  10. package/src/components/Blocks/CustomTemplates/VoltoSearchBlock/RightModalFacets.jsx +1 -2
  11. package/src/components/Blocks/CustomTemplates/VoltoSearchBlock/index.js +10 -1
  12. package/src/components/Blocks/CustomTemplates/VoltoSearchBlock/range.css +5 -0
  13. package/src/components/Blocks/CustomTemplates/VoltoSearchBlock/rewriteOptions.js +49 -0
  14. package/src/components/Blocks/customBlocks.js +12 -0
  15. package/src/components/CLMSDatasetDetailView/CLMSDatasetDetailView.jsx +105 -1
  16. package/src/components/CLMSDatasetDetailView/CLMSDatasetDetailView.test.jsx +30 -61
  17. package/src/components/CclCard/CclCard.jsx +26 -8
  18. package/src/components/CclCard/CclCard.test.jsx +1 -0
  19. package/src/components/CclCard/cards.less +2 -2
  20. package/src/reducers/import_wms_layers/import_wms_layers.test.js +60 -0
  21. package/src/reducers/import_wms_layers/import_wms_layers_reducer.js +44 -0
  22. package/src/reducers/index.js +2 -0
  23. package/theme/clms/css/header.css +7 -0
  24. package/theme/clms/css/maps.css +9 -1
  25. package/theme/clms/css/maps.less +11 -1
  26. package/theme/clms/css/ownstyles.less +1 -1
package/CHANGELOG.md CHANGED
@@ -4,8 +4,27 @@ 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.69](https://github.com/eea/volto-clms-theme/compare/1.0.68...1.0.69)
8
+
9
+ - new set of action and reducers to import WMS layers from a new endpoint [`#204`](https://github.com/eea/volto-clms-theme/pull/204)
10
+ - Bugs n improvements [`#205`](https://github.com/eea/volto-clms-theme/pull/205)
11
+ - add react-input-range to transformIgnorePatterns [`e3c704d`](https://github.com/eea/volto-clms-theme/commit/e3c704d4e0569d55b1c5cf50a3bf3191452aea38)
12
+ - global search variation [`3599a89`](https://github.com/eea/volto-clms-theme/commit/3599a897c1cdbdb39041144d0b6610bb1debbe5a)
13
+ - prettier [`bc6f853`](https://github.com/eea/volto-clms-theme/commit/bc6f85356460b5e03f3bbda134318adc5950d30f)
14
+ - fix tests [`09cd0b9`](https://github.com/eea/volto-clms-theme/commit/09cd0b99706492f2a24e79ed6f280fe6e023e084)
15
+ - Map styles [`ed902d4`](https://github.com/eea/volto-clms-theme/commit/ed902d49b46341ebdc1d12ceb6a1ca49129a4cd7)
16
+ - elvis [`09886c4`](https://github.com/eea/volto-clms-theme/commit/09886c40b1cab893cc94aaed3ded237aadf1171b)
17
+ - fix test [`50c0e5a`](https://github.com/eea/volto-clms-theme/commit/50c0e5a4231833596ae738ef6a4d76f63eaf5c22)
18
+ - fix test [`1d2669f`](https://github.com/eea/volto-clms-theme/commit/1d2669ffb71c33ae692b4023a85ce4c6a76c0cec)
19
+ - double range facet for temporal extent filter [`118e622`](https://github.com/eea/volto-clms-theme/commit/118e622eca2486893e5993bfd89f1024a922a184)
20
+ - Header responsive [`872534f`](https://github.com/eea/volto-clms-theme/commit/872534fd9bf616447b60c4a87fe62e544cafdc1b)
21
+ - News/Event line color [`e144da8`](https://github.com/eea/volto-clms-theme/commit/e144da8845dece2098312af1fdcfa4901bbaeabe)
22
+
7
23
  #### [1.0.68](https://github.com/eea/volto-clms-theme/compare/1.0.67...1.0.68)
8
24
 
25
+ > 14 February 2022
26
+
27
+ - Develop [`#203`](https://github.com/eea/volto-clms-theme/pull/203)
9
28
  - fix underpanel [`d665279`](https://github.com/eea/volto-clms-theme/commit/d665279a8b2fefc450353af0121325c375d32cb5)
10
29
  - Selected files information, option to clear selection and indeterminate checkbox at header [`b72f476`](https://github.com/eea/volto-clms-theme/commit/b72f476a2bd382fd2cce4ed8abc9134fb05ceb32)
11
30
 
@@ -28,7 +28,7 @@ module.exports = {
28
28
  '^.+\\.(svg)$': './node_modules/@plone/volto/jest-svgsystem-transform.js',
29
29
  },
30
30
  transformIgnorePatterns: [
31
- 'node_modules/(?!(@eeacms/volto-clms-utils/|@plone/volto/|slick-carousel))',
31
+ 'node_modules/(?!(@eeacms/volto-clms-utils/|@plone/volto/|slick-carousel|react-input-range))',
32
32
  ],
33
33
  coverageThreshold: {
34
34
  global: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-clms-theme",
3
- "version": "1.0.68",
3
+ "version": "1.0.69",
4
4
  "description": "volto-clms-theme: Volto theme for CLMS site",
5
5
  "main": "src/index.js",
6
6
  "author": "CodeSyntax for the European Environment Agency",
@@ -49,7 +49,8 @@
49
49
  "react-svg": "14.0.4",
50
50
  "slick-carousel": "1.8.1",
51
51
  "volto-dropdownmenu": "2.2.7",
52
- "volto-form-block": "2.2.2"
52
+ "volto-form-block": "2.2.2",
53
+ "react-input-range": "^1.3.0"
53
54
  },
54
55
  "devDependencies": {
55
56
  "@cypress/code-coverage": "^3.9.5",
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Post meeting register actions.
3
+ * @module actions/postImportGeonetwork
4
+ */
5
+ export const POST_IMPORT_WMS_LAYERS = 'POST_IMPORT_WMS_LAYERS';
6
+
7
+ /**
8
+ * Post import geonetwork.
9
+ * @function postImportGeonetwork
10
+ * @returns {Object} Get extra items action.
11
+ */
12
+ export function postImportWMSLayers(url, id, type) {
13
+ return {
14
+ type: POST_IMPORT_WMS_LAYERS,
15
+ request: {
16
+ op: 'post',
17
+ path: `${url}/@import-wms-layers`,
18
+ },
19
+ };
20
+ }
@@ -0,0 +1,15 @@
1
+ import { postImportWMSLayers } from './import_wms_layers';
2
+ import { POST_IMPORT_WMS_LAYERS } from './import_wms_layers';
3
+
4
+ describe('Import geonetwork action', () => {
5
+ describe('postImportWMSLayers', () => {
6
+ it('should create an action to post geonetwork', () => {
7
+ const url = 'http://localhost';
8
+ const action = postImportWMSLayers(url);
9
+
10
+ expect(action.type).toEqual(POST_IMPORT_WMS_LAYERS);
11
+ expect(action.request.op).toEqual('post');
12
+ expect(action.request.path).toEqual(`${url}/@import-wms-layers`);
13
+ });
14
+ });
15
+ });
@@ -82,3 +82,8 @@ export {
82
82
  unsubscribeTo,
83
83
  confirmUnsubscribeTo,
84
84
  } from './subscription/post_subscription';
85
+
86
+ export {
87
+ POST_IMPORT_WMS_LAYERS,
88
+ postImportWMSLayers,
89
+ } from './import_wms_layers/import_wms_layers';
@@ -25,7 +25,7 @@ const CclListingCards = (props) => {
25
25
  let containerClass = '';
26
26
  if (['news', 'event'].includes(variation)) {
27
27
  containerClass = 'ccl-container';
28
- } else if (!['line', 'doc'].includes(variation)) {
28
+ } else if (!['line', 'doc', 'globalSearch'].includes(variation)) {
29
29
  containerClass = 'card-container';
30
30
  }
31
31
  return (
@@ -0,0 +1,74 @@
1
+ import { Segment } from 'semantic-ui-react';
2
+ import React, { useState } from 'react';
3
+ import InputRange from 'react-input-range';
4
+ import 'react-input-range/lib/css/index.css';
5
+ import './range.css';
6
+
7
+ const DoubleRangeFacet = (props) => {
8
+ const { facet, choices, onChange, value } = props;
9
+ const facetValue = value;
10
+ var [open, setOpen] = React.useState(false);
11
+
12
+ const convertToRange = (values) => {
13
+ return {
14
+ min: Math.min.apply(
15
+ Math,
16
+ values.map(function (o) {
17
+ return o.value;
18
+ }),
19
+ ),
20
+ max: Math.max.apply(
21
+ Math,
22
+ values.map(function (o) {
23
+ return o.value;
24
+ }),
25
+ ),
26
+ };
27
+ };
28
+
29
+ const startingValues = convertToRange(choices);
30
+
31
+ const [rangeValues, setRangeValues] = useState(startingValues);
32
+
33
+ const onChangeRange = (rValue, onChange) => {
34
+ setRangeValues(rValue);
35
+ onChange(
36
+ facet.field.value,
37
+ [...Array(rValue.max - rValue.min + 1).keys()].map((i) =>
38
+ (i + rValue.min).toString(),
39
+ ),
40
+ );
41
+ };
42
+
43
+ return (
44
+ <fieldset className="ccl-fieldset">
45
+ <div
46
+ className="ccl-expandable__button"
47
+ aria-expanded={open}
48
+ onClick={() => setOpen(!open)}
49
+ onKeyDown={() => setOpen(!open)}
50
+ tabIndex={0}
51
+ role={'button'}
52
+ >
53
+ <legend className="ccl-form-legend">
54
+ {facet.title} {startingValues.min} - {startingValues.max}
55
+ </legend>
56
+ </div>
57
+ <div>
58
+ <Segment basic padded>
59
+ <InputRange
60
+ minValue={startingValues.min}
61
+ maxValue={startingValues.max}
62
+ value={
63
+ facetValue.length > 0 ? convertToRange(facetValue) : rangeValues
64
+ }
65
+ onChange={(value) => onChangeRange(value, onChange)}
66
+ />
67
+ </Segment>
68
+ <br />
69
+ </div>
70
+ </fieldset>
71
+ );
72
+ };
73
+
74
+ export default DoubleRangeFacet;
@@ -0,0 +1,57 @@
1
+ import React from 'react';
2
+ import { Button, Icon } from 'semantic-ui-react';
3
+ import { defineMessages, useIntl } from 'react-intl';
4
+
5
+ const messages = defineMessages({
6
+ currentFilters: {
7
+ id: 'Current filters applied',
8
+ defaultMessage: 'Current filters applied',
9
+ },
10
+ clearFilters: {
11
+ id: 'Clear filters',
12
+ defaultMessage: 'Clear filters',
13
+ },
14
+ });
15
+
16
+ const FilterList = (props) => {
17
+ const { facets, setFacets, isEditMode } = props;
18
+ const showFilterList = !Object.values(facets).every((facet) => !facet.length);
19
+
20
+ const currentFilters = Object.fromEntries(
21
+ Object.entries(facets).filter((v) => v[1] && v[0] !== 'SearchableText'),
22
+ );
23
+
24
+ const totalFilters = [].concat.apply([], Object.values(currentFilters))
25
+ .length;
26
+
27
+ const intl = useIntl();
28
+
29
+ return showFilterList && Object.keys(currentFilters).length ? (
30
+ <div className="accordion ui filter-listing">
31
+ <div
32
+ className="filter-list-header"
33
+ style={{ cursor: 'auto' }}
34
+ active={false}
35
+ >
36
+ <div className="filter-list-title">
37
+ {intl.formatMessage(messages.currentFilters)}: {totalFilters}
38
+ </div>
39
+ <Button
40
+ icon
41
+ basic
42
+ compact
43
+ size="small"
44
+ onClick={(e) => {
45
+ e.stopPropagation();
46
+ !isEditMode && setFacets({});
47
+ }}
48
+ >
49
+ <Icon name="trash" />
50
+ {intl.formatMessage(messages.clearFilters)}
51
+ </Button>
52
+ </div>
53
+ </div>
54
+ ) : null;
55
+ };
56
+
57
+ export default FilterList;
@@ -1,13 +1,13 @@
1
1
  import { Button, Grid, Segment } from 'semantic-ui-react';
2
2
  import {
3
3
  Facets,
4
- FilterList,
5
4
  SearchDetails,
6
5
  SearchInput,
7
6
  SortOn,
8
7
  } from '@plone/volto/components/manage/Blocks/Search/components';
9
8
  import { defineMessages, useIntl } from 'react-intl';
10
9
 
10
+ import FilterList from './FilterList';
11
11
  import CclFiltersModal from '@eeacms/volto-clms-theme/components/CclFiltersModal/CclFiltersModal';
12
12
  import { Icon } from '@plone/volto/components';
13
13
  import React from 'react';
@@ -59,7 +59,6 @@ const RightModalFacets = (props) => {
59
59
  const { showSearchButton } = data;
60
60
  const isLive = !showSearchButton;
61
61
  const intl = useIntl();
62
-
63
62
  return (
64
63
  <Grid className="searchBlock-facets right-column-facets" stackable>
65
64
  {data?.headline && (
@@ -1,5 +1,14 @@
1
+ import DoubleRangeFacet from './DoubleRangeFacet';
1
2
  import AccordionFacet from './AccordionFacet';
2
3
  import RightModalFacets from './RightModalFacets';
3
4
  import WithType from './WithType';
5
+ import rewriteOptions, { portal_types_labels } from './rewriteOptions';
4
6
 
5
- export { RightModalFacets, AccordionFacet, WithType };
7
+ export {
8
+ RightModalFacets,
9
+ AccordionFacet,
10
+ WithType,
11
+ DoubleRangeFacet,
12
+ rewriteOptions,
13
+ portal_types_labels,
14
+ };
@@ -0,0 +1,5 @@
1
+ .input-range__track--active,
2
+ .input-range__slider {
3
+ border: #a0b128;
4
+ background: #a0b128;
5
+ }
@@ -0,0 +1,49 @@
1
+ export const portal_types_labels = {
2
+ DataSet: 'Dataset',
3
+ Product: 'Product',
4
+ 'News Item': 'News',
5
+ 'eea.meeting': 'Event',
6
+ UseCase: 'Use case',
7
+ WorkOpportunity: 'Work opportunity',
8
+ Tender: 'Tender',
9
+ TechnicalLibrary: 'Product documentation',
10
+ };
11
+
12
+ const rewriteOptions = (name, choices) => {
13
+ var result = choices;
14
+ if (name === 'review_state') {
15
+ result = choices.map((opt) => ({
16
+ ...opt,
17
+ label: opt.label.replace(/\[.+\]/, '').trim(),
18
+ }));
19
+ }
20
+ const portal_types = [
21
+ 'DataSet',
22
+ 'Product',
23
+ 'News Item',
24
+ 'eea.meeting',
25
+ 'UseCase',
26
+ 'WorkOpportunity',
27
+ 'Tender',
28
+ 'TechnicalLibrary',
29
+ ];
30
+
31
+ if (name === 'portal_type') {
32
+ result = choices
33
+ .filter((opt) => portal_types.includes(opt.value))
34
+ .map((opt) => {
35
+ return { ...opt, label: portal_types_labels[opt.value] };
36
+ })
37
+ .sort((a, b) => {
38
+ if (a.label < b.label) {
39
+ return -1;
40
+ } else if (a.label > b.label) {
41
+ return 1;
42
+ }
43
+ return 0;
44
+ });
45
+ }
46
+ return result;
47
+ };
48
+
49
+ export default rewriteOptions;
@@ -2,6 +2,8 @@ import {
2
2
  AccordionFacet,
3
3
  RightModalFacets,
4
4
  WithType,
5
+ DoubleRangeFacet,
6
+ rewriteOptions,
5
7
  } from '@eeacms/volto-clms-theme/components/Blocks/CustomTemplates/VoltoSearchBlock';
6
8
  import {
7
9
  CclCarouselView,
@@ -118,6 +120,7 @@ const availableVariations = [
118
120
  'CloseTenders',
119
121
  true,
120
122
  ),
123
+ listingVariation('CclGlobalSearch', false, 'Global search', 'globalSearch'),
121
124
  ];
122
125
 
123
126
  const customBlocks = (config) => ({
@@ -310,6 +313,9 @@ const customBlocks = (config) => ({
310
313
  ...config.blocks.blocksConfig.search.extensions,
311
314
  facetWidgets: {
312
315
  ...config.blocks.blocksConfig.search.extensions.facetWidgets,
316
+ rewriteOptions: (name, choices) => {
317
+ return rewriteOptions(name, choices);
318
+ },
313
319
  types: [
314
320
  {
315
321
  id: 'accordionCheckboxFacet',
@@ -323,6 +329,12 @@ const customBlocks = (config) => ({
323
329
  view: WithType(AccordionFacet, 'label'),
324
330
  isDefault: false,
325
331
  },
332
+ {
333
+ id: 'doubleRangeFacet',
334
+ title: 'Double Range',
335
+ view: DoubleRangeFacet,
336
+ isDefault: false,
337
+ },
326
338
  ...config.blocks.blocksConfig.search.extensions.facetWidgets.types,
327
339
  ],
328
340
  },
@@ -20,6 +20,7 @@ import { connect } from 'react-redux';
20
20
  import { getUser } from '@plone/volto/actions';
21
21
  import jwtDecode from 'jwt-decode';
22
22
  import { postImportGeonetwork } from '../../actions';
23
+ import { postImportWMSLayers } from '../../actions';
23
24
  import { useLocation } from 'react-router-dom';
24
25
 
25
26
  /**
@@ -35,6 +36,7 @@ const CLMSDatasetDetailView = ({ content, token }) => {
35
36
  const geonetwork_importation = useSelector(
36
37
  (state) => state.geonetwork_importation,
37
38
  );
39
+ const wms_layers_importation = useSelector((state) => state.importWMSLayers);
38
40
  const user = useSelector((state) => state.users?.user);
39
41
  React.useEffect(() => {
40
42
  dispatch(getUser(token));
@@ -43,6 +45,11 @@ const CLMSDatasetDetailView = ({ content, token }) => {
43
45
  function handleImport(id, type) {
44
46
  dispatch(postImportGeonetwork(location.pathname, id, type));
45
47
  }
48
+
49
+ function handleWMSImport() {
50
+ dispatch(postImportWMSLayers(location.pathname));
51
+ }
52
+
46
53
  const [open, setOpen] = React.useState({});
47
54
  const locale = useSelector((state) => state.intl.locale);
48
55
 
@@ -50,7 +57,7 @@ const CLMSDatasetDetailView = ({ content, token }) => {
50
57
  <div className="ccl-container ">
51
58
  <h1 className="page-title">{content.title}</h1>
52
59
  {content.geonetwork_identifiers?.items?.length > 0 &&
53
- user.roles &&
60
+ user?.roles &&
54
61
  user.roles.includes('Manager') && (
55
62
  <Segment.Group compact horizontal>
56
63
  {content.geonetwork_identifiers?.items.map((item) => {
@@ -178,6 +185,103 @@ const CLMSDatasetDetailView = ({ content, token }) => {
178
185
  })}
179
186
  </Segment.Group>
180
187
  )}
188
+
189
+ {user?.roles && user.roles.includes('Manager') && (
190
+ <Segment.Group compact horizontal>
191
+ <Segment
192
+ padded={'very'}
193
+ color={'olive'}
194
+ key={'wms-layers-import'}
195
+ loading={wms_layers_importation?.loading}
196
+ circular
197
+ >
198
+ <Modal
199
+ onClose={() => {
200
+ setOpen({ ...open, 'wms-layers-import': false });
201
+ }}
202
+ onOpen={() => {
203
+ setOpen({ ...open, 'wms-layers-import': true });
204
+ }}
205
+ open={open['wms-layers-import']}
206
+ trigger={
207
+ <CclButton>
208
+ <FormattedMessage
209
+ id="Import WMS Layers"
210
+ defaultMessage="Import WMS Layers"
211
+ />
212
+ </CclButton>
213
+ }
214
+ className={'modal-clms'}
215
+ >
216
+ <div className={'modal-clms-background'}>
217
+ <div className={'modal-clms-container'}>
218
+ <div className={'modal-close modal-clms-close'}>
219
+ <span
220
+ className="ccl-icon-close"
221
+ aria-label="Close"
222
+ onClick={() => {
223
+ setOpen({ ...open, 'wms-layers-import': false });
224
+ }}
225
+ onKeyDown={() => {
226
+ setOpen({ ...open, 'wms-layers-import': false });
227
+ }}
228
+ tabIndex="0"
229
+ role="button"
230
+ ></span>
231
+ </div>
232
+ <div className="modal-login-text">
233
+ <h1>
234
+ <FormattedMessage
235
+ id="Import WMS Layers"
236
+ defaultMessage="Import WMS Layers"
237
+ />
238
+ </h1>
239
+ This action will import the WMS Layers from the view service
240
+ defined in the dataset or from GeoNetwork if the view
241
+ service is not defined and a linked geonetwork record has a
242
+ valid WMS service link
243
+ <br />
244
+ <br />
245
+ </div>
246
+ <CclButton
247
+ onClick={() => {
248
+ handleWMSImport();
249
+ setOpen({ ...open, 'wms-layers-import': false });
250
+ }}
251
+ mode="filled"
252
+ >
253
+ <FormattedMessage
254
+ id="Import data"
255
+ defaultMessage="Import data"
256
+ />
257
+ </CclButton>
258
+ </div>
259
+ </div>
260
+ </Modal>
261
+ {wms_layers_importation?.imported_wms_layers?.status && (
262
+ <p>
263
+ {wms_layers_importation?.loaded &&
264
+ wms_layers_importation?.error === null && (
265
+ <strong>
266
+ {' '}
267
+ {wms_layers_importation?.imported_wms_layers?.message}
268
+ </strong>
269
+ )}
270
+ </p>
271
+ )}
272
+ {wms_layers_importation?.imported_wms_layers?.status ===
273
+ 'error' && (
274
+ <p>
275
+ <strong>
276
+ {' '}
277
+ {wms_layers_importation?.imported_wms_layers?.message}
278
+ </strong>
279
+ </p>
280
+ )}
281
+ </Segment>
282
+ </Segment.Group>
283
+ )}
284
+
181
285
  <CclTabs routing={true}>
182
286
  <div tabTitle="General Info">{DataSetInfoContent(content)}</div>
183
287
  {content?.downloadable_dataset &&
@@ -7,6 +7,33 @@ import { Provider } from 'react-redux';
7
7
  import configureStore from 'redux-mock-store';
8
8
 
9
9
  const mockStore = configureStore();
10
+ let store = mockStore({
11
+ intl: {
12
+ locale: 'en',
13
+ messages: {},
14
+ },
15
+ search: {
16
+ subrequest: {
17
+ '123': { items: [] },
18
+ },
19
+ },
20
+ users: {
21
+ user: { roles: ['Manager'] },
22
+ },
23
+ importWMSLayers: {
24
+ imported_wms_layers: {
25
+ status: 'success',
26
+ message: 'message',
27
+ },
28
+ error: false,
29
+ loaded: true,
30
+ loading: false,
31
+ },
32
+ userSession: {
33
+ token:
34
+ 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImV4cCI6MTY0NDM4MzA0NCwiZnVsbG5hbWUiOm51bGx9.cB_q3Q0Jhu8h2m_SDmmknodpDxDLfb4o-qY6Y2plE04',
35
+ },
36
+ });
10
37
 
11
38
  describe('CLMSDatasetDetailView', () => {
12
39
  it('Check metadata view', () => {
@@ -47,27 +74,7 @@ describe('CLMSDatasetDetailView', () => {
47
74
  },
48
75
  ],
49
76
  };
50
- const store = mockStore({
51
- content: {
52
- ...content,
53
- },
54
- intl: {
55
- locale: 'en',
56
- messages: {},
57
- },
58
- search: {
59
- subrequest: {
60
- '123': { items: [] },
61
- },
62
- },
63
- users: {
64
- user: { roles: ['Manager'] },
65
- },
66
- userSession: {
67
- token:
68
- 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImV4cCI6MTY0NDM4MzA0NCwiZnVsbG5hbWUiOm51bGx9.cB_q3Q0Jhu8h2m_SDmmknodpDxDLfb4o-qY6Y2plE04',
69
- },
70
- });
77
+ store.content = content;
71
78
 
72
79
  const DatasetDetailView = renderer
73
80
  .create(
@@ -107,27 +114,7 @@ describe('CLMSDatasetDetailView', () => {
107
114
  downloadable_dataset: true,
108
115
  downloadable_files: [],
109
116
  };
110
- const store = mockStore({
111
- content: {
112
- ...content,
113
- },
114
- intl: {
115
- locale: 'en',
116
- messages: {},
117
- },
118
- search: {
119
- subrequest: {
120
- '123': { items: [] },
121
- },
122
- },
123
- users: {
124
- user: { roles: ['Manager'] },
125
- },
126
- userSession: {
127
- token:
128
- 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImV4cCI6MTY0NDM4MzA0NCwiZnVsbG5hbWUiOm51bGx9.cB_q3Q0Jhu8h2m_SDmmknodpDxDLfb4o-qY6Y2plE04',
129
- },
130
- });
117
+ store.content = content;
131
118
 
132
119
  const DatasetDetailView = renderer
133
120
  .create(
@@ -159,25 +146,7 @@ describe('CLMSDatasetDetailView', () => {
159
146
  },
160
147
  ],
161
148
  };
162
- const store = mockStore({
163
- content: {
164
- ...content,
165
- },
166
- intl: {
167
- locale: 'en',
168
- messages: {},
169
- },
170
- search: {
171
- subrequest: {
172
- '123': { items: [] },
173
- },
174
- },
175
- user: { roles: ['Manager'] },
176
- userSession: {
177
- token:
178
- 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImV4cCI6MTY0NDM4MzA0NCwiZnVsbG5hbWUiOm51bGx9.cB_q3Q0Jhu8h2m_SDmmknodpDxDLfb4o-qY6Y2plE04',
179
- },
180
- });
149
+ store.content = content;
181
150
  const DatasetDetailView = renderer
182
151
  .create(
183
152
  <Provider store={store}>
@@ -7,6 +7,8 @@ import { Link } from 'react-router-dom';
7
7
  import PropTypes from 'prop-types';
8
8
  import React from 'react';
9
9
  import { When } from '@plone/volto/components/theme/View/EventDatesInfo';
10
+ import { Label } from 'semantic-ui-react';
11
+ import { portal_types_labels } from '../Blocks/CustomTemplates/VoltoSearchBlock';
10
12
 
11
13
  function bytesToSize(bytes) {
12
14
  var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
@@ -16,17 +18,33 @@ function bytesToSize(bytes) {
16
18
  }
17
19
  function CclCard(props) {
18
20
  const { type, children, card } = props;
19
- let url = card ? card['@id'] || card.hrerf || '/' : '/';
21
+ let url = '/';
22
+ let content_type = '';
23
+ if (card) {
24
+ url = card['@id'] || card.hrerf || '/';
25
+ content_type = portal_types_labels[card['@type']] || card['@type'];
26
+ }
27
+ const conditional_types = [
28
+ 'doc',
29
+ 'news',
30
+ 'event',
31
+ 'block',
32
+ 'threeColumns',
33
+ 'globalSearch',
34
+ ];
20
35
  return (
21
- <div className={'card-' + (type || 'line')}>
22
- {type === 'doc' ||
23
- type === 'news' ||
24
- type === 'event' ||
25
- type === 'block' ||
26
- type === 'threeColumns' ? (
36
+ <div
37
+ className={'card-' + (type === 'globalSearch' ? 'doc' : type || 'line')}
38
+ >
39
+ {conditional_types.includes(type) ? (
27
40
  <>
28
- {type === 'doc' && (
41
+ {(type === 'doc' || type === 'globalSearch') && (
29
42
  <>
43
+ {type === 'globalSearch' && (
44
+ <Label ribbon="right" color="olive">
45
+ {content_type}
46
+ </Label>
47
+ )}
30
48
  <div className="card-doc-title">
31
49
  <Link to={url}>{card?.title || 'Card default title'}</Link>
32
50
  </div>
@@ -11,6 +11,7 @@ describe('CclCard', () => {
11
11
  const card = {
12
12
  title: 'title example',
13
13
  description: 'description example',
14
+ '@type': 'News Item',
14
15
  start:
15
16
  'Wed May 19 2021 12:49:04 GMT+0200 (hora de verano de Europa central)',
16
17
  end: 'Wed May 26 2024 12:49:04 GMT+0200 (hora de verano de Europa central)',
@@ -181,7 +181,7 @@
181
181
 
182
182
  .card-news:not(:last-of-type) {
183
183
  padding-bottom: 1rem;
184
- border-bottom: solid 1px #ebebeb;
184
+ border-bottom: solid 1px #a0b12833;
185
185
  margin-bottom: 1rem;
186
186
  }
187
187
 
@@ -244,7 +244,7 @@
244
244
 
245
245
  .card-event:not(:last-of-type) {
246
246
  padding-bottom: 1rem;
247
- border-bottom: solid 1px #ebebeb;
247
+ border-bottom: solid 1px #a0b12833;
248
248
  margin-bottom: 1rem;
249
249
  }
250
250
 
@@ -0,0 +1,60 @@
1
+ import { importWMSLayersReducer } from './import_wms_layers_reducer';
2
+ import { POST_IMPORT_WMS_LAYERS } from '../../actions';
3
+
4
+ //jest test for importWMSLayersReducer
5
+ describe('importWMSLayersReducer', () => {
6
+ it('should return the initial state', () => {
7
+ expect(importWMSLayersReducer(undefined)).toEqual({
8
+ error: null,
9
+ loaded: false,
10
+ loading: false,
11
+ imported_wms_layers: {},
12
+ });
13
+ });
14
+ //jest test for importWMSLayersReducer -success
15
+ it('should handle POST_IMPORT_WMS_LAYERS_SUCCESS', () => {
16
+ const action = {
17
+ type: `${POST_IMPORT_WMS_LAYERS}_SUCCESS`,
18
+ result: { imported_wms_layers: { id: '1' } },
19
+ };
20
+ expect(importWMSLayersReducer({}, action)).toEqual({
21
+ error: null,
22
+ loaded: true,
23
+ loading: false,
24
+ imported_wms_layers: action.result,
25
+ });
26
+ });
27
+ //jest test for importWMSLayersReducer -fail
28
+ it('should handle POST_IMPORT_WMS_LAYERS_FAIL', () => {
29
+ expect(
30
+ importWMSLayersReducer(
31
+ {},
32
+ {
33
+ type: `${POST_IMPORT_WMS_LAYERS}_FAIL`,
34
+ error: 'error',
35
+ },
36
+ ),
37
+ ).toEqual({
38
+ error: 'error',
39
+ loaded: false,
40
+ loading: false,
41
+ imported_wms_layers: {},
42
+ });
43
+ });
44
+ //jest test for importWMSLayersReducer -pending
45
+ it('should handle POST_IMPORT_WMS_LAYERS_PENDING', () => {
46
+ expect(
47
+ importWMSLayersReducer(
48
+ {},
49
+ {
50
+ type: `${POST_IMPORT_WMS_LAYERS}_PENDING`,
51
+ },
52
+ ),
53
+ ).toEqual({
54
+ error: null,
55
+ loaded: false,
56
+ loading: true,
57
+ imported_wms_layers: {},
58
+ });
59
+ });
60
+ });
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @module reducers/import_wms_layers
3
+ */
4
+
5
+ import { POST_IMPORT_WMS_LAYERS } from '../../actions';
6
+
7
+ const initialState = {
8
+ error: null,
9
+ loaded: false,
10
+ loading: false,
11
+ imported_wms_layers: {},
12
+ };
13
+
14
+ export const importWMSLayersReducer = (state = initialState, action = {}) => {
15
+ switch (action?.type) {
16
+ case `${POST_IMPORT_WMS_LAYERS}_PENDING`:
17
+ return {
18
+ ...state,
19
+ error: null,
20
+ loaded: false,
21
+ loading: true,
22
+ imported_wms_layers: {},
23
+ };
24
+ case `${POST_IMPORT_WMS_LAYERS}_FAIL`:
25
+ return {
26
+ ...state,
27
+ error: action.error,
28
+ loaded: false,
29
+ loading: false,
30
+ imported_wms_layers: {},
31
+ };
32
+
33
+ case `${POST_IMPORT_WMS_LAYERS}_SUCCESS`:
34
+ return {
35
+ ...state,
36
+ error: null,
37
+ loaded: true,
38
+ loading: false,
39
+ imported_wms_layers: action.result,
40
+ };
41
+ default:
42
+ return state;
43
+ }
44
+ };
@@ -15,6 +15,7 @@ import { registryReducer } from './registry/registry';
15
15
  import { subscribeToReducer } from './subscription/subscription_reducer';
16
16
  import tokens from './tokens/tokens';
17
17
  import { userschemaReducer } from './userschema/userschema';
18
+ import { importWMSLayersReducer } from './import_wms_layers/import_wms_layers_reducer';
18
19
 
19
20
  /**
20
21
  * Root reducer.
@@ -39,6 +40,7 @@ const reducers = {
39
40
  // subscribe_to_newsletter: newsletterReducer,
40
41
  newsletter_subscribers: newsletterSubscribersReducer,
41
42
  subscription: subscribeToReducer,
43
+ importWMSLayers: importWMSLayersReducer,
42
44
  };
43
45
 
44
46
  export default reducers;
@@ -634,12 +634,19 @@
634
634
  margin: 0;
635
635
  font-size: 1rem;
636
636
  line-height: 2.2rem;
637
+ white-space: nowrap;
637
638
  }
638
639
 
639
640
  .ccl-header .ccl-header-tools .ccl-header-menu-tools li > span {
640
641
  color: white;
641
642
  cursor: pointer;
642
643
  }
644
+ @media (min-width: 820px) and (max-width: 992px) {
645
+ .ccl-header .ccl-header-tools .ccl-header-menu-tools li {
646
+ font-size: 0.875rem;
647
+ }
648
+ }
649
+
643
650
  @media (max-width: 820px) {
644
651
  .ccl-header .ccl-header-nav .ccl-collapsible-toolmenu > li > span {
645
652
  display: block;
@@ -389,7 +389,7 @@
389
389
  .land .map-menu-dataset>div:first-of-type {
390
390
  display: flex;
391
391
  width: 100%;
392
- justify-content: space-between;
392
+ justify-content: flex-start;
393
393
  }
394
394
 
395
395
  .land .map-menu-layers-container {
@@ -531,6 +531,14 @@
531
531
  box-shadow: none !important;
532
532
  }
533
533
 
534
+ .info-table tr:nth-child(even) {
535
+ background-color: #a0b1280f;
536
+ }
537
+
538
+ .info-table tr:nth-child(odd) {
539
+ background-color: #a0b12833;
540
+ }
541
+
534
542
  .land .map-login-block {
535
543
  display: none;
536
544
  margin: 1rem;
@@ -404,7 +404,7 @@
404
404
  .map-menu-dataset > div:first-of-type {
405
405
  display: flex;
406
406
  width: 100%;
407
- justify-content: space-between;
407
+ justify-content: flex-start;
408
408
  }
409
409
 
410
410
  .map-menu-layers-container {
@@ -548,6 +548,15 @@
548
548
  box-shadow: none !important;
549
549
  }
550
550
 
551
+ /* Info widget */
552
+ .info-table tr:nth-child(even) {
553
+ background-color: #a0b1280f;
554
+ }
555
+
556
+ .info-table tr:nth-child(odd) {
557
+ background-color: #a0b12833;
558
+ }
559
+
551
560
  /* Login */
552
561
  .map-login-block {
553
562
  display: none;
@@ -562,6 +571,7 @@
562
571
  margin: 1rem;
563
572
  }
564
573
 
574
+ /* Time slider */
565
575
  .esri-time-slider__time-extent-group > * {
566
576
  color: #273b4b;
567
577
  }
@@ -1000,7 +1000,7 @@ main .search-form button {
1000
1000
  .home-news-container:not(:last-of-type),
1001
1001
  .home-events-container:not(:last-of-type) {
1002
1002
  padding-bottom: 1rem;
1003
- border-bottom: solid 1px #ebebeb;
1003
+ border-bottom: solid 1px #a0b12833;
1004
1004
  margin-bottom: 1rem;
1005
1005
  }
1006
1006