@eeacms/volto-clms-theme 1.0.131 → 1.0.132

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 (24) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/package.json +4 -3
  3. package/src/components/Blocks/CustomTemplates/VoltoListingBlock/CclListingWorkOpportunities.jsx +7 -2
  4. package/src/components/Blocks/CustomTemplates/VoltoSearchBlock/DoubleRangeFacet.jsx +23 -4
  5. package/src/components/Blocks/CustomTemplates/VoltoSearchBlock/rewriteOptions.js +20 -24
  6. package/src/components/CLMSDatasetDetailView/CLMSDatasetDetailView.jsx +6 -2
  7. package/src/components/CLMSDatasetDetailView/DataSetInfoContent.jsx +3 -1
  8. package/src/components/CLMSDatasetDetailView/DownloadDataSetContent.jsx +0 -4
  9. package/src/components/CLMSDownloadCartView/CLMSCartContent.jsx +25 -28
  10. package/src/components/CLMSDownloadCartView/CLMSDownloadCartView.jsx +16 -20
  11. package/src/components/CLMSDownloadsView/CLMSDownloadTasks.jsx +1 -1
  12. package/src/components/CLMSProfileView/CLMSApiTokensView.jsx +19 -6
  13. package/src/components/CLMSProfileView/CLMSDeleteProfileView.jsx +2 -1
  14. package/src/components/CLMSProfileView/CLMSUserProfileView.jsx +19 -12
  15. package/src/components/CLMSWorkOpportunityView/WorkOpportunityView.jsx +6 -2
  16. package/src/components/CclCard/CclCard.jsx +3 -2
  17. package/src/components/CclDownloadTable/CclDownloadTable.jsx +51 -11
  18. package/src/components/CclInfoDescription/CclInfoDescription.jsx +4 -4
  19. package/src/components/Widgets/ImageWidget.jsx +9 -11
  20. package/src/components/Widgets/TaxonomyWidget.jsx +1 -1
  21. package/src/components/Widgets/taxonomyUtils.js +51 -33
  22. package/src/customizations/volto/components/manage/Widgets/EmailWidget.jsx +18 -9
  23. package/src/customizations/volto/components/manage/Widgets/TextareaWidget.jsx +3 -1
  24. package/theme/clms/css/styles.less +4 -0
package/CHANGELOG.md CHANGED
@@ -4,6 +4,47 @@ 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.132](https://github.com/eea/volto-clms-theme/compare/1.0.131...1.0.132) - 3 October 2022
8
+
9
+ #### :rocket: New Features
10
+
11
+ - feat: upgrade volto-form-block version [Mikel Larreategi - [`622012b`](https://github.com/eea/volto-clms-theme/commit/622012b48bba449950b25e2efb1fb838aa15faaa)]
12
+ - feat: restore the ability to change the title of the Area of interest column in the prepackaged files download [Mikel Larreategi - [`4154428`](https://github.com/eea/volto-clms-theme/commit/415442889655773c6fdc2249f6a12fcf744150f3)]
13
+ - feat: Lowering the duration of the access to downloads CLMS-1206 [ionlizarazu - [`9e8475f`](https://github.com/eea/volto-clms-theme/commit/9e8475f544257764d36486543aeaccc45793f9f2)]
14
+ - feat: add step field to doubleRangeFacet to customize the step of the range selector [ionlizarazu - [`9118590`](https://github.com/eea/volto-clms-theme/commit/9118590ea69d64001fdcf445feab9ad1eeedb27a)]
15
+
16
+ #### :bug: Bug Fixes
17
+
18
+ - fix: delete user cart before deleting the profile [Mikel Larreategi - [`138c530`](https://github.com/eea/volto-clms-theme/commit/138c530f48757bd6d1746dc20227062cde178d1d)]
19
+ - fix: portal_type ordering in facets [ionlizarazu - [`ec1a42c`](https://github.com/eea/volto-clms-theme/commit/ec1a42c653db1857eca947d62653dd837a0acb83)]
20
+ - fix: wrong functionality of the cart rendering after adding some packages to it [ionlizarazu - [`65746d9`](https://github.com/eea/volto-clms-theme/commit/65746d949b499cace652c0f57d7fa22bbb94c851)]
21
+ - fix:small changes [ionlizarazu - [`5377522`](https://github.com/eea/volto-clms-theme/commit/5377522ebecb7b15954b2f10ac16662ffb582770)]
22
+ - fix: change added to cart toast [ionlizarazu - [`79ab75d`](https://github.com/eea/volto-clms-theme/commit/79ab75de1376c546a5d966670689d0f0dce2600a)]
23
+ - fix: Listing document card edit icon [ionlizarazu - [`de5e15e`](https://github.com/eea/volto-clms-theme/commit/de5e15eb11518b796719d56302198900d99d2667)]
24
+ - fix:move the taxonomy ordering functionality to the structure_taxonomy_terms function [ionlizarazu - [`de90d5a`](https://github.com/eea/volto-clms-theme/commit/de90d5ab60c66781da39d040a93ca735e0bc2e3b)]
25
+ - fix: use UniversalLink in WorkOpportunity and Tenders [Mikel Larreategi - [`9b11306`](https://github.com/eea/volto-clms-theme/commit/9b11306affd25ac3ec6fb25dbf455df0f521c87c)]
26
+ - fix: allow more image formats, and do not try to show TIFFs, because they can't be shown [Mikel Larreategi - [`2ef8546`](https://github.com/eea/volto-clms-theme/commit/2ef8546dad19669e2dc5751b35075cfd1a73a2ba)]
27
+ - fix: change title in Dataset citation [Mikel Larreategi - [`8c07443`](https://github.com/eea/volto-clms-theme/commit/8c0744384dd62c78fbfa91deae9e716dcf5bfd50)]
28
+ - fix: sort technical documentation on dataset view according to the documentation_sorting index like we do in the product related technical documentation. CLMS-1416 [Mikel Larreategi - [`a315100`](https://github.com/eea/volto-clms-theme/commit/a315100f9785db65bdbb2d42ff4a77b6aa85c17f)]
29
+ - fix: when log out redirect to portal [Unai - [`d1c7937`](https://github.com/eea/volto-clms-theme/commit/d1c79376e15e542eb381f5e2156466d45882eb11)]
30
+ - fix: CLMS-1369 [Unai - [`9c246f4`](https://github.com/eea/volto-clms-theme/commit/9c246f4e8f8fc3a3162bf0c47718fcbf7c6ee358)]
31
+ - fix: prepackage filter placeholder [ionlizarazu - [`3f4e26b`](https://github.com/eea/volto-clms-theme/commit/3f4e26b0afd40d2799d2038bc4534eb8f294ff57)]
32
+ - fix: CLMS-1159 [Unai - [`966d93a`](https://github.com/eea/volto-clms-theme/commit/966d93a5c8c33971554e480cb2ed8fa55c6608d0)]
33
+ - fix: search in item area instead of resolution. Select all button [ionlizarazu - [`9d02ff8`](https://github.com/eea/volto-clms-theme/commit/9d02ff81f60d1ca836abc5ddcda213b9fa7d291a)]
34
+
35
+ #### :nail_care: Enhancements
36
+
37
+ - refactor: CLMS-941 [Unai - [`87fe047`](https://github.com/eea/volto-clms-theme/commit/87fe0471d5ec52964641eb127d6bc5020fd21c93)]
38
+
39
+ #### :house: Internal changes
40
+
41
+ - chore: add some missing button destination to go to correct URLs [Mikel Larreategi - [`733b88d`](https://github.com/eea/volto-clms-theme/commit/733b88d5df62817b86cbd464f4b93d8edd4a9a85)]
42
+ - chore: use UniversalLink in profile view [Mikel Larreategi - [`f506ab6`](https://github.com/eea/volto-clms-theme/commit/f506ab6089ad1b3da3fe9b12e6b2a7b9a2169023)]
43
+
44
+ #### :hammer_and_wrench: Others
45
+
46
+ - merge sprint-35 [Mikel Larreategi - [`8bd4d75`](https://github.com/eea/volto-clms-theme/commit/8bd4d758de17ac73d8f0fc7b91fedd68cc39d4dd)]
47
+ - email widget checks if email is valid when clicking on its input [Unai - [`a4c9bd6`](https://github.com/eea/volto-clms-theme/commit/a4c9bd601b44143e5e79e0c67c92f30b08aeab56)]
7
48
  ### [1.0.131](https://github.com/eea/volto-clms-theme/compare/1.0.130...1.0.131) - 28 September 2022
8
49
 
9
50
  #### :bug: Bug Fixes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-clms-theme",
3
- "version": "1.0.131",
3
+ "version": "1.0.132",
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",
@@ -55,7 +55,7 @@
55
55
  "react-svg": "14.0.4",
56
56
  "slick-carousel": "1.8.1",
57
57
  "volto-dropdownmenu": "2.2.7",
58
- "volto-form-block": "2.5.0",
58
+ "volto-form-block": "2.7.1",
59
59
  "react-input-range": "^1.3.0",
60
60
  "lightgallery": "^2.4.0",
61
61
  "validator": "13.7.0"
@@ -76,7 +76,8 @@
76
76
  "prettier-eslint": "^12.0.0",
77
77
  "stylelint": "^13.12.0",
78
78
  "stylelint-config-idiomatic-order": "8.1.0",
79
- "stylelint-prettier": "1.1.2"
79
+ "stylelint-prettier": "1.1.2",
80
+ "md5": "^2.3.0"
80
81
  },
81
82
  "prettier": {
82
83
  "trailingComma": "all",
@@ -1,10 +1,13 @@
1
1
  import React from 'react';
2
- import PropTypes from 'prop-types';
3
2
  import { defineMessages, useIntl } from 'react-intl';
4
3
  import { useSelector } from 'react-redux';
5
4
  import { Link } from 'react-router-dom';
5
+
6
+ import { UniversalLink } from '@plone/volto/components';
6
7
  import { workOpportunitiesCclDateTimeFormat } from '@eeacms/volto-clms-theme/components/CclUtils';
7
8
 
9
+ import PropTypes from 'prop-types';
10
+
8
11
  const messages = defineMessages({
9
12
  ProcurementNo: {
10
13
  id: 'ProcurementNo',
@@ -43,7 +46,9 @@ const CclWorkOpportunity = (props) => {
43
46
  : intl.formatMessage(messages.ProcurementNo)}
44
47
  </span>
45
48
  {item.url ? (
46
- <a href={item.url || ''}>{item.procurement_no}</a>
49
+ <UniversalLink href={item.url || ''}>
50
+ {item.procurement_no}
51
+ </UniversalLink>
47
52
  ) : (
48
53
  item.procurement_no
49
54
  )}
@@ -6,11 +6,29 @@ import React, { useState } from 'react';
6
6
  import InputRange from 'react-input-range';
7
7
  import { Segment } from 'semantic-ui-react';
8
8
  import {
9
- selectFacetSchemaEnhancer,
10
9
  selectFacetStateToValue,
11
10
  selectFacetValueToQuery,
12
11
  } from '@plone/volto/components/manage/Blocks/Search/components/base';
13
12
 
13
+ const doubleRangeFacetSchemaEnhancer = ({ schema, formData }) => {
14
+ // adds (enables) the 'multiple' field after the 'type' dropdown
15
+ let { fields } = schema.fieldsets[0];
16
+ const pos = fields.indexOf('type') + 1;
17
+ fields = [
18
+ ...fields.slice(0, pos),
19
+ 'step',
20
+ 'multiple',
21
+ ...fields.slice(pos, fields.length),
22
+ ];
23
+
24
+ schema.properties = {
25
+ ...schema.properties,
26
+ step: { title: 'Step', type: 'number', default: 1 },
27
+ };
28
+ schema.fieldsets[0].fields = fields;
29
+ return schema;
30
+ };
31
+
14
32
  const DoubleRangeFacet = (props) => {
15
33
  const { facet, choices, onChange, value } = props;
16
34
  const facetValue = value;
@@ -21,13 +39,13 @@ const DoubleRangeFacet = (props) => {
21
39
  min: Math.min.apply(
22
40
  Math,
23
41
  values.map(function (o) {
24
- return o.value;
42
+ return o.value.replace(/[a-zA-Z]/, '');
25
43
  }),
26
44
  ),
27
45
  max: Math.max.apply(
28
46
  Math,
29
47
  values.map(function (o) {
30
- return o.value;
48
+ return o.value.replace(/[a-zA-Z]/, '');
31
49
  }),
32
50
  ),
33
51
  };
@@ -64,6 +82,7 @@ const DoubleRangeFacet = (props) => {
64
82
  <InputRange
65
83
  minValue={startingValues.min}
66
84
  maxValue={startingValues.max}
85
+ step={facet.step || 1}
67
86
  value={
68
87
  facetValue.length > 0 ? convertToRange(facetValue) : rangeValues
69
88
  }
@@ -76,7 +95,7 @@ const DoubleRangeFacet = (props) => {
76
95
  );
77
96
  };
78
97
 
79
- DoubleRangeFacet.schemaEnhancer = selectFacetSchemaEnhancer;
98
+ DoubleRangeFacet.schemaEnhancer = doubleRangeFacetSchemaEnhancer;
80
99
  DoubleRangeFacet.stateToValue = selectFacetStateToValue;
81
100
  DoubleRangeFacet.valueToQuery = selectFacetValueToQuery;
82
101
  export default DoubleRangeFacet;
@@ -41,16 +41,17 @@ const rewriteOptions = (name, choices) => {
41
41
  }));
42
42
  }
43
43
  const portal_types = [
44
- 'DataSet',
45
44
  'Product',
45
+ 'DataSet',
46
+ 'TechnicalLibrary',
47
+ 'UseCase',
46
48
  'News Item',
47
49
  'eea.meeting',
48
- 'UseCase',
49
- 'WorkOpportunity',
50
50
  'Tender',
51
- 'TechnicalLibrary',
51
+ 'WorkOpportunity',
52
52
  'Document',
53
53
  ];
54
+
54
55
  if (name === 'portal_type') {
55
56
  result = choices
56
57
  .filter((opt) => portal_types.includes(opt.value))
@@ -58,12 +59,7 @@ const rewriteOptions = (name, choices) => {
58
59
  return { ...opt, label: portal_types_labels[opt.value] };
59
60
  })
60
61
  .sort((a, b) => {
61
- if (a.label < b.label) {
62
- return -1;
63
- } else if (a.label > b.label) {
64
- return 1;
65
- }
66
- return 0;
62
+ return portal_types.indexOf(a.value) - portal_types.indexOf(b.value);
67
63
  });
68
64
  }
69
65
  if (name === 'classificationTopicCategory') {
@@ -80,20 +76,20 @@ const rewriteOptions = (name, choices) => {
80
76
  return 0;
81
77
  });
82
78
  }
83
- if (name === 'taxonomy_technical_library_categorization') {
84
- result = choices
85
- .sort((a, b) => {
86
- if (a.label < b.label) {
87
- return -1;
88
- } else if (a.label > b.label) {
89
- return 1;
90
- }
91
- return 0;
92
- })
93
- .map((opt) => {
94
- return { ...opt, label: opt.label.replace(/^[0-9][0-9]#/, '') };
95
- });
96
- }
79
+ // if (name === 'taxonomy_technical_library_categorization') {
80
+ // result = choices
81
+ // .sort((a, b) => {
82
+ // if (a.label < b.label) {
83
+ // return -1;
84
+ // } else if (a.label > b.label) {
85
+ // return 1;
86
+ // }
87
+ // return 0;
88
+ // })
89
+ // .map((opt) => {
90
+ // return { ...opt, label: opt.label.replace(/^[0-9][0-9]#/, '') };
91
+ // });
92
+ // }
97
93
  if (name === 'component_title') {
98
94
  result = choices
99
95
  .sort((a, b) => {
@@ -44,7 +44,9 @@ const CLMSDatasetDetailView = ({ content, token }) => {
44
44
  const wms_fields_importation = useSelector((state) => state.importWMSFields);
45
45
  const user = useSelector((state) => state.users?.user);
46
46
  React.useEffect(() => {
47
- dispatch(getUser(token));
47
+ if (token) {
48
+ dispatch(getUser(token));
49
+ }
48
50
  }, [dispatch, token]);
49
51
 
50
52
  function handleImport(id, type) {
@@ -388,7 +390,9 @@ const CLMSDatasetDetailView = ({ content, token }) => {
388
390
 
389
391
  {content?.downloadable_dataset &&
390
392
  content?.downloadable_files?.items?.length > 0 && (
391
- <div tabTitle="Download">{DownloadDataSetContent(content)}</div>
393
+ <div tabTitle="Download">
394
+ {DownloadDataSetContent(content, token)}
395
+ </div>
392
396
  )}
393
397
  {content?.downloadable_dataset &&
394
398
  content?.downloadable_files?.items?.length === 0 && (
@@ -30,6 +30,8 @@ const DataSetInfoContent = (props) => {
30
30
  portal_type: 'TechnicalLibrary',
31
31
  path: '/',
32
32
  associated_datasets: UID,
33
+ sort_on: 'documentation_sorting',
34
+ sort_order: 'ascending',
33
35
  },
34
36
  id,
35
37
  ),
@@ -78,7 +80,7 @@ const DataSetInfoContent = (props) => {
78
80
  citation?.data !== '<p><br/></p>' &&
79
81
  citation?.data !== '<p></p>' && (
80
82
  <CclCitation
81
- title="Citation status"
83
+ title="Dataset citation"
82
84
  marginBottom={true}
83
85
  children={<StringToHTML string={citation?.data} />}
84
86
  ></CclCitation>
@@ -1,6 +1,5 @@
1
1
  import React, { useEffect } from 'react';
2
2
  import CclDownloadTable from '@eeacms/volto-clms-theme/components/CclDownloadTable/CclDownloadTable';
3
- import { getUser } from '@plone/volto/actions';
4
3
  import { useDispatch, useSelector } from 'react-redux';
5
4
  import CclButton from '@eeacms/volto-clms-theme/components/CclButton/CclButton';
6
5
  import config from '@plone/volto/registry';
@@ -29,9 +28,6 @@ const DownloadDataSetContent = (data, token) => {
29
28
  }
30
29
  }, [registryRecords, registry_key, location.pathname]);
31
30
  const user = useSelector((state) => state.users?.user);
32
- React.useEffect(() => {
33
- dispatch(getUser(token));
34
- }, [dispatch, token]);
35
31
 
36
32
  function modalStatus(status) {
37
33
  if (status === true) {
@@ -13,12 +13,7 @@ import {
13
13
  formatNaming,
14
14
  originalFormatNaming,
15
15
  } from './cartUtils';
16
- import {
17
- getDownloadtool,
18
- getFormatConversionTable,
19
- getProjections,
20
- postDownloadtool,
21
- } from '../../actions';
16
+ import { getDownloadtool, postDownloadtool } from '../../actions';
22
17
  import { useDispatch, useSelector } from 'react-redux';
23
18
 
24
19
  import CclButton from '@eeacms/volto-clms-theme/components/CclButton/CclButton';
@@ -34,18 +29,20 @@ const CLMSCartContent = (props) => {
34
29
  const dispatch = useDispatch();
35
30
  const { removeCartItem, removeCartItems } = useCartState();
36
31
 
32
+ // state connections
33
+ const cart = useSelector((state) => state.cart_items.items);
34
+ const post_download_in_progress = useSelector(
35
+ (state) => state.downloadtool.post_download_in_progress,
36
+ );
37
+
37
38
  // component states
38
39
  const [openedModal, setOpenedModal] = useState(false);
39
40
  const [cartSelection, setCartSelection] = useState([]);
40
41
  const [loadingTable, setLoadingTable] = useState(false);
41
42
  const [cartItems, setCartItems] = useState([]);
42
-
43
- // state connections
44
- const cart = useSelector((state) => state.cart_items.items);
45
- const post_download_in_progress = useSelector(
46
- (state) => state.downloadtool.post_download_in_progress,
43
+ const datasets_items = useSelector(
44
+ (state) => state.datasetsByUid.datasets.items,
47
45
  );
48
- const datasets = useSelector((state) => state.datasetsByUid.datasets.items);
49
46
  const formatConversionTable = useSelector(
50
47
  (state) => state.downloadtool.format_conversion_table_in_progress,
51
48
  );
@@ -55,12 +52,7 @@ const CLMSCartContent = (props) => {
55
52
  const nutsnames = useSelector((state) => state.nutsnames.nutsnames);
56
53
 
57
54
  useEffect(() => {
58
- dispatch(getProjections());
59
- dispatch(getFormatConversionTable());
60
- }, [dispatch]);
61
-
62
- useEffect(() => {
63
- setCartItemInProgress(post_download_in_progress['unique_ids']);
55
+ setCartItemInProgress(post_download_in_progress.unique_ids || '');
64
56
  // eslint-disable-next-line react-hooks/exhaustive-deps
65
57
  }, [post_download_in_progress]);
66
58
 
@@ -70,10 +62,14 @@ const CLMSCartContent = (props) => {
70
62
  array_ids.includes(item.unique_id),
71
63
  );
72
64
  setCartItems(cleanDuplicatesEntries(newCart));
73
- if (datasets?.length > 0 && cart.length > 0 && !newCart.length) {
65
+ if (
66
+ datasets_items?.length > 0 &&
67
+ cart.length > 0 &&
68
+ cart.length !== newCart.length
69
+ ) {
74
70
  concatRequestedCartItem();
75
71
  }
76
- }, [cart, datasets]);
72
+ }, [cart, datasets_items]);
77
73
 
78
74
  useEffect(() => {
79
75
  if (Object.keys(nutsnames).length > 0 && cart.length > 0) {
@@ -82,21 +78,22 @@ const CLMSCartContent = (props) => {
82
78
  }, [nutsnames]);
83
79
 
84
80
  function concatRequestedCartItem() {
81
+ let newCartItems = [...cartItems];
85
82
  localSessionCart.forEach((localItem) => {
86
- const requestedItem = datasets
87
- ? datasets.find((req) => req.UID === localItem.UID)
83
+ const requestedItem = datasets_items
84
+ ? datasets_items.find((req) => req.UID === localItem.UID)
88
85
  : false;
89
86
  if (requestedItem) {
90
87
  const file_data = requestedItem?.downloadable_files?.items.find(
91
88
  (item) => item['@id'] === localItem.file_id,
92
89
  );
93
90
  if (file_data) {
94
- cartItems.push(
91
+ newCartItems.push(
95
92
  getCartObjectFromPrepackaged(file_data, requestedItem),
96
93
  );
97
- setCartItems(cleanDuplicatesEntries(cartItems));
94
+ setCartItems(cleanDuplicatesEntries(newCartItems));
98
95
  } else {
99
- cartItems.push(
96
+ newCartItems.push(
100
97
  getCartObjectFromMapviewer(
101
98
  localItem,
102
99
  requestedItem,
@@ -104,7 +101,7 @@ const CLMSCartContent = (props) => {
104
101
  nutsnames,
105
102
  ),
106
103
  );
107
- setCartItems(cleanDuplicatesEntries(cartItems));
104
+ setCartItems(cleanDuplicatesEntries(newCartItems));
108
105
  }
109
106
  }
110
107
  });
@@ -265,8 +262,8 @@ const CLMSCartContent = (props) => {
265
262
  (obj) => obj.unique_id === item.unique_id,
266
263
  );
267
264
  cartItems[objIndex].type = data.value;
268
- const dataset = datasets
269
- ? datasets.find((req) => req.UID === item.dataset_uid)
265
+ const dataset = datasets_items
266
+ ? datasets_items.find((req) => req.UID === item.dataset_uid)
270
267
  : false;
271
268
  const format_item = dataset.dataset_download_information.items.find(
272
269
  (item) => item['@id'] === data.value,
@@ -5,29 +5,26 @@
5
5
 
6
6
  import { Forbidden, Unauthorized } from '@plone/volto/components';
7
7
  import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
8
- import React, { useEffect, useState } from 'react';
8
+ import React, { useEffect } from 'react';
9
9
  import {
10
10
  getDatasetsByUid,
11
11
  getExtraBreadcrumbItems,
12
12
  getNutsNames,
13
13
  } from '../../actions';
14
- import useCartState, {
15
- CART_SESSION_KEY,
16
- } from '@eeacms/volto-clms-utils/cart/useCartState';
14
+ import useCartState from '@eeacms/volto-clms-utils/cart/useCartState';
17
15
  import { useDispatch, useSelector } from 'react-redux';
18
16
 
19
17
  import CLMSCartContent from './CLMSCartContent';
20
18
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
21
19
  import { Helmet } from '@plone/volto/helpers';
22
20
  import { Link } from 'react-router-dom';
21
+ import { getFormatConversionTable, getProjections } from '../../actions';
23
22
 
24
23
  const CLMSDownloadCartView = (props) => {
25
24
  const dispatch = useDispatch();
26
- const user_id = useSelector((state) => state.users.user.id);
27
25
  const locale = useSelector((state) => state.intl?.locale);
28
- const [localSessionCart, setLocalSessionCart] = useState([]);
26
+ const cart = useSelector((state) => state.cart_items.items);
29
27
  const { isLoggedIn } = useCartState();
30
-
31
28
  const { formatMessage } = useIntl();
32
29
  const messages = defineMessages({
33
30
  Cart: {
@@ -36,6 +33,11 @@ const CLMSDownloadCartView = (props) => {
36
33
  },
37
34
  });
38
35
 
36
+ useEffect(() => {
37
+ dispatch(getProjections());
38
+ dispatch(getFormatConversionTable());
39
+ }, [dispatch]);
40
+
39
41
  useEffect(() => {
40
42
  dispatch(
41
43
  getExtraBreadcrumbItems([
@@ -50,23 +52,17 @@ const CLMSDownloadCartView = (props) => {
50
52
  return () => {
51
53
  dispatch(getExtraBreadcrumbItems([]));
52
54
  };
53
- }, [dispatch, formatMessage, messages.Cart, props.location.pathname]);
54
-
55
- useEffect(() => {
56
- const CART_SESSION_USER_KEY = CART_SESSION_KEY.concat(`_${user_id}`);
57
- setLocalSessionCart(
58
- JSON.parse(localStorage.getItem(CART_SESSION_USER_KEY)) || [],
59
- );
60
- }, [user_id]);
55
+ // eslint-disable-next-line react-hooks/exhaustive-deps
56
+ }, [props.location.pathname]);
61
57
 
62
58
  useEffect(() => {
63
59
  let localsessionUidsList = [];
64
- if (localSessionCart?.length !== 0) {
60
+ if (cart?.length !== 0) {
65
61
  localsessionUidsList = [
66
- ...new Set(localSessionCart.map((item) => item.UID || item.id)),
62
+ ...new Set(cart.map((item) => item.UID || item.id)),
67
63
  ];
68
64
  }
69
- let localsessionNutsIDList = [...new Set(getNutsIDList(localSessionCart))];
65
+ let localsessionNutsIDList = [...new Set(getNutsIDList(cart))];
70
66
  let uidsList = [...new Set(localsessionUidsList)];
71
67
  if (uidsList.length > 0) {
72
68
  dispatch(getDatasetsByUid(uidsList));
@@ -75,7 +71,7 @@ const CLMSDownloadCartView = (props) => {
75
71
  dispatch(getNutsNames(localsessionNutsIDList));
76
72
  }
77
73
  // eslint-disable-next-line react-hooks/exhaustive-deps
78
- }, [localSessionCart, dispatch]);
74
+ }, [cart, dispatch]);
79
75
 
80
76
  function getNutsIDList(cart_data) {
81
77
  const nuts_ids = [];
@@ -134,7 +130,7 @@ const CLMSDownloadCartView = (props) => {
134
130
  </ul>
135
131
  </div>
136
132
  </div>
137
- <CLMSCartContent localSessionCart={localSessionCart} />
133
+ <CLMSCartContent localSessionCart={cart} />
138
134
  </div>
139
135
  </>
140
136
  )}
@@ -74,7 +74,7 @@ const CLMSDownloadTasks = (props) => {
74
74
  (today.getTime() - (FinalizationDate.getTime() || 0)) /
75
75
  (1000 * 3600 * 24),
76
76
  );
77
- return daysDiff - 10 < -1;
77
+ return daysDiff - 3 < -1;
78
78
  };
79
79
 
80
80
  const MapTasks = (mapProps) => {
@@ -271,7 +271,7 @@ class CLMSApiTokensView extends Component {
271
271
  <CclModal
272
272
  onClick={() => this.onClose}
273
273
  trigger={
274
- <CclButton mode={'filled'}>
274
+ <CclButton mode={'filled'} to="profile#API-tokens">
275
275
  {this.props.intl.formatMessage(messages.deleteButton)}
276
276
  </CclButton>
277
277
  }
@@ -284,6 +284,7 @@ class CLMSApiTokensView extends Component {
284
284
  </p>
285
285
  <CclButton
286
286
  mode={'filled'}
287
+ to="profile#API-tokens"
287
288
  onClick={() => {
288
289
  this.deleteToken(item.key_id);
289
290
  }}
@@ -294,10 +295,14 @@ class CLMSApiTokensView extends Component {
294
295
  </div>
295
296
  </>
296
297
  ))}
297
- <br></br>
298
- <br></br>
298
+ <br />
299
+ <br />
299
300
  {this.state.createNewToken === false && (
300
- <CclButton mode={'filled'} onClick={this.handleClick}>
301
+ <CclButton
302
+ mode={'filled'}
303
+ onClick={this.handleClick}
304
+ to="profile#API-tokens"
305
+ >
301
306
  {this.props.intl.formatMessage(messages.createTitle)}
302
307
  </CclButton>
303
308
  )}
@@ -305,7 +310,7 @@ class CLMSApiTokensView extends Component {
305
310
  <CclModal
306
311
  onClick={() => this.onClose}
307
312
  trigger={
308
- <CclButton mode={'filled'}>
313
+ <CclButton mode={'filled'} to="profile#API-tokens">
309
314
  {this.props.intl.formatMessage(messages.createTitle)}
310
315
  </CclButton>
311
316
  }
@@ -343,6 +348,7 @@ class CLMSApiTokensView extends Component {
343
348
  placeholder=""
344
349
  aria-label="Name of the new token"
345
350
  />
351
+ <br />
346
352
  <input
347
353
  className="ccl-button ccl-button-green"
348
354
  type="button"
@@ -393,8 +399,10 @@ class CLMSApiTokensView extends Component {
393
399
  class="ccl-text-input"
394
400
  value={JSON.stringify(item)}
395
401
  />
402
+ <br />
396
403
  <CclButton
397
404
  mode={'filled'}
405
+ to="profile#API-tokens"
398
406
  onClick={() => {
399
407
  navigator.clipboard.writeText(
400
408
  JSON.stringify(item),
@@ -405,13 +413,18 @@ class CLMSApiTokensView extends Component {
405
413
  messages.copyButton,
406
414
  )}
407
415
  </CclButton>
416
+ <br />
408
417
  </>
409
418
  )) ||
410
419
  ''}
411
420
  </>
412
421
  ))}
413
422
  </form>
414
- <CclButton mode={'filled'} onClick={this.onClose}>
423
+ <CclButton
424
+ mode={'filled'}
425
+ onClick={this.onClose}
426
+ to="profile#API-tokens"
427
+ >
415
428
  {this.props.intl.formatMessage(
416
429
  messages.goBackButton,
417
430
  )}
@@ -1,6 +1,5 @@
1
1
  import React from 'react';
2
2
  import { injectIntl } from 'react-intl';
3
- import { FormattedMessage } from 'react-intl';
4
3
  import { useDispatch, useSelector } from 'react-redux';
5
4
  import { useHistory } from 'react-router-dom';
6
5
  import { Container } from 'semantic-ui-react';
@@ -11,6 +10,7 @@ import CclButton from '@eeacms/volto-clms-theme/components/CclButton/CclButton';
11
10
  import useCartState from '@eeacms/volto-clms-utils/cart/useCartState';
12
11
 
13
12
  import { delProfile } from '../../actions';
13
+ import { FormattedMessage } from 'react-intl';
14
14
 
15
15
  /**
16
16
  * CLMSProfileView container.
@@ -100,6 +100,7 @@ export const CLMSDeleteProfileView = (props) => {
100
100
  setOpen({ ...open, 'delete-profile': false });
101
101
  }}
102
102
  mode="filled"
103
+ to="profile#Delete-profile"
103
104
  >
104
105
  <FormattedMessage
105
106
  id="Yes, I want to delete my account"
@@ -1,21 +1,25 @@
1
- /**
2
- * CLMSProfileView container.
3
- * @module components/CLMSProfileView/CLMSProfileView
4
- */
5
-
6
1
  import React, { Component } from 'react';
7
- import PropTypes from 'prop-types';
8
- import { connect } from 'react-redux';
9
- import { compose } from 'redux';
10
2
  import { defineMessages, injectIntl } from 'react-intl';
11
- import jwtDecode from 'jwt-decode';
12
- import { Form, Toast } from '@plone/volto/components';
3
+ import { connect } from 'react-redux';
13
4
  import { toast } from 'react-toastify';
5
+ import { compose } from 'redux';
6
+ import { Container } from 'semantic-ui-react';
7
+
14
8
  import { getUser, updateUser } from '@plone/volto/actions';
9
+ import { UniversalLink } from '@plone/volto/components';
10
+ import { Form, Toast } from '@plone/volto/components';
15
11
  import { getBaseUrl } from '@plone/volto/helpers';
16
- import { Container } from 'semantic-ui-react';
12
+
17
13
  import { getUserSchema } from '../../actions';
18
14
 
15
+ import jwtDecode from 'jwt-decode';
16
+ import PropTypes from 'prop-types';
17
+
18
+ /**
19
+ * CLMSProfileView container.
20
+ * @module components/CLMSProfileView/CLMSProfileView
21
+ */
22
+
19
23
  const messages = defineMessages({
20
24
  UserProfile: {
21
25
  id: 'UserProfile',
@@ -159,7 +163,10 @@ class CLMSUserProfileView extends Component {
159
163
  using EU Login to enter this site. <br />
160
164
  If you want to change your fullname and e-mail address, please
161
165
  do so in your{' '}
162
- <a href="https://ecas.ec.europa.eu/cas/">EU Login account</a>.
166
+ <UniversalLink href={'https://ecas.ec.europa.eu/cas/'}>
167
+ EU Login account
168
+ </UniversalLink>
169
+ .
163
170
  </p>
164
171
  <div>
165
172
  {this.props?.userschema?.loaded && (
@@ -1,8 +1,10 @@
1
1
  import React from 'react';
2
2
  import { defineMessages, useIntl } from 'react-intl';
3
- import { workOpportunitiesCclDateTimeFormat } from '@eeacms/volto-clms-theme/components/CclUtils';
4
3
  import { useSelector } from 'react-redux';
5
4
 
5
+ import { UniversalLink } from '@plone/volto/components';
6
+ import { workOpportunitiesCclDateTimeFormat } from '@eeacms/volto-clms-theme/components/CclUtils';
7
+
6
8
  const messages = defineMessages({
7
9
  ProcurementNo: {
8
10
  id: 'ProcurementNo',
@@ -41,7 +43,9 @@ const CLMSWorkOpportunityView = (props) => {
41
43
  : intl.formatMessage(messages.ProcurementNo)}
42
44
  </span>
43
45
  {content.url ? (
44
- <a href={content.url || ''}>{content.procurement_no}</a>
46
+ <UniversalLink href={content.url || ''}>
47
+ {content.procurement_no}
48
+ </UniversalLink>
45
49
  ) : (
46
50
  content.procurement_no
47
51
  )}
@@ -9,6 +9,7 @@ import { Label } from 'semantic-ui-react';
9
9
  import { portal_types_labels } from '../Blocks/CustomTemplates/VoltoSearchBlock';
10
10
  import penSVG from '@plone/volto/icons/pen.svg';
11
11
  import { Icon } from 'semantic-ui-react';
12
+ import { Icon as VoltoIcon } from '@plone/volto/components';
12
13
 
13
14
  import PlaceHolder from '@eeacms/volto-clms-theme/../theme/clms/img/ccl-thumbnail-placeholder.jpg';
14
15
  import { cclDateFormat } from '@eeacms/volto-clms-theme/components/CclUtils';
@@ -58,9 +59,9 @@ const DocCard = ({ card, url, showEditor, children }) => {
58
59
  )}
59
60
  {card?.Type === 'TechnicalLibrary' && showEditor && (
60
61
  <Link to={`${url}/edit`}>
61
- <Icon
62
+ <VoltoIcon
62
63
  name={penSVG}
63
- size="15px"
64
+ size="12px"
64
65
  className="circled"
65
66
  title={'Edit'}
66
67
  />
@@ -10,7 +10,7 @@ import {
10
10
  import React, { useState } from 'react';
11
11
 
12
12
  import CclButton from '@eeacms/volto-clms-theme/components/CclButton/CclButton';
13
- import { Icon } from '@plone/volto/components';
13
+ import { Icon, Toast } from '@plone/volto/components';
14
14
  import PropTypes from 'prop-types';
15
15
  import clearSVG from '@plone/volto/icons/clear.svg';
16
16
  import paginationLeftSVG from '@plone/volto/icons/left-key.svg';
@@ -18,11 +18,13 @@ import paginationRightSVG from '@plone/volto/icons/right-key.svg';
18
18
  import useCartState from '@eeacms/volto-clms-utils/cart/useCartState';
19
19
  import { useSelector } from 'react-redux';
20
20
  import { StringToHTML } from '@eeacms/volto-clms-theme/components/CclUtils';
21
+ import { toast } from 'react-toastify';
22
+ import { defineMessages, useIntl } from 'react-intl';
21
23
 
22
24
  function CclDownloadTable(props) {
23
25
  const locale = useSelector((state) => state.intl?.locale);
24
26
  const { dataset } = props;
25
- const { addCartItem, Toast, isLoggedIn } = useCartState();
27
+ const { addCartItem, isLoggedIn } = useCartState();
26
28
  const [cartSelection, setCartSelection] = useState([]);
27
29
  const [currentPageItems, setCurrentPageItems] = useState([]);
28
30
  const [currentPage, setCurrentPage] = useState(1);
@@ -32,6 +34,7 @@ function CclDownloadTable(props) {
32
34
  const [totalPages, setTotalPages] = useState(
33
35
  Math.ceil(dataset?.downloadable_files?.items.length / 10),
34
36
  );
37
+ const intl = useIntl();
35
38
  // complete the selected file with dataset UID, title and a concat of dataset.UID and block id to get unique id for the whole web
36
39
  const prePackagedCollection = dataset?.downloadable_files?.items.map(
37
40
  (element) => {
@@ -44,13 +47,24 @@ function CclDownloadTable(props) {
44
47
  },
45
48
  );
46
49
 
50
+ const messages = defineMessages({
51
+ added_to_cart: {
52
+ id: 'Added to cart',
53
+ defaultMessage: 'Added to cart',
54
+ },
55
+ success: {
56
+ id: 'Success',
57
+ defaultMessage: 'Success',
58
+ },
59
+ });
60
+
47
61
  React.useEffect(() => {
48
62
  setCurrentPageItems(prePackagedCollection.slice(0, 10));
49
63
  // eslint-disable-next-line react-hooks/exhaustive-deps
50
64
  }, []);
51
65
 
52
66
  React.useEffect(() => {
53
- calcHeaderCheckboxStatus();
67
+ calcHeaderCheckboxStatus(currentPageItems);
54
68
  // eslint-disable-next-line react-hooks/exhaustive-deps
55
69
  }, [cartSelection, currentPage]);
56
70
 
@@ -78,17 +92,22 @@ function CclDownloadTable(props) {
78
92
  setFilteredItems(prePackagedCollection);
79
93
  setTotalPages(Math.ceil(prePackagedCollection.length / 10));
80
94
  }
81
- calcHeaderCheckboxStatus();
95
+ calcHeaderCheckboxStatus(currentPageItems);
82
96
 
83
97
  // eslint-disable-next-line react-hooks/exhaustive-deps
84
98
  }, [filterText]);
85
99
 
86
- const calcHeaderCheckboxStatus = () => {
87
- const currentPageSelection = currentPageItems.filter((item) =>
100
+ const calcHeaderCheckboxStatus = (currentPI) => {
101
+ const currentPageSelection = currentPI.filter((item) =>
88
102
  cartSelection.includes(item.unique_id),
89
103
  );
90
104
  if (currentPageSelection.length === 10) {
91
105
  setpageCheckboxStatus(2);
106
+ } else if (
107
+ currentPI.length !== 0 &&
108
+ currentPageSelection.length === currentPI.length
109
+ ) {
110
+ setpageCheckboxStatus(2);
92
111
  } else if (cartSelection.length > 0) {
93
112
  setpageCheckboxStatus(1);
94
113
  } else {
@@ -142,7 +161,11 @@ function CclDownloadTable(props) {
142
161
  setCartSelection(newCartSelection);
143
162
  };
144
163
 
145
- const addToCard = () => {
164
+ const selectAllPagesCart = () => {
165
+ setCartSelection(prePackagedCollection.map((item) => item.unique_id));
166
+ };
167
+
168
+ const addToCard = async () => {
146
169
  let selectedCartItems = prePackagedCollection
147
170
  .filter((item) => cartSelection.includes(item.unique_id) && item)
148
171
  // Get only UID and unique_id from selectedCartItems array of objects
@@ -153,7 +176,15 @@ function CclDownloadTable(props) {
153
176
  file: item.file,
154
177
  unique_id: item.unique_id,
155
178
  }));
156
- addCartItem(selectedCartItems);
179
+ await addCartItem(selectedCartItems).then(() => {
180
+ toast.success(
181
+ <Toast
182
+ success
183
+ title={intl.formatMessage(messages.success)}
184
+ content={intl.formatMessage(messages.added_to_cart)}
185
+ />,
186
+ );
187
+ });
157
188
  };
158
189
 
159
190
  const clearSelection = () => {
@@ -201,7 +232,6 @@ function CclDownloadTable(props) {
201
232
  validcolums &&
202
233
  columns && (
203
234
  <div className="dataset-download-table">
204
- <Toast message="Added to cart" time={5000}></Toast>
205
235
  <h2>Download pre-packaged data collections</h2>
206
236
  <p>
207
237
  Please note that you can only download the latest version of our
@@ -237,7 +267,15 @@ function CclDownloadTable(props) {
237
267
  <>
238
268
  {' - '}
239
269
  <Button basic color="olive" onClick={clearSelection}>
240
- Clear selection <Icon name={clearSVG} size={20}></Icon>
270
+ Clear selection <Icon name={clearSVG} size={'20px'}></Icon>
271
+ </Button>
272
+ </>
273
+ )}
274
+ {cartSelection.length !== prePackagedCollection.length && (
275
+ <>
276
+ <br />
277
+ <Button basic color="olive" onClick={selectAllPagesCart}>
278
+ Select all
241
279
  </Button>
242
280
  </>
243
281
  )}
@@ -255,7 +293,9 @@ function CclDownloadTable(props) {
255
293
  )}
256
294
  {columns.includes('title') && <th>Title</th>}
257
295
  {columns.includes('file') && <th>File name</th>}
258
- {columns.includes('area') && <th>Area of interest</th>}
296
+ {columns.includes('area') && (
297
+ <th>{dataset.download_table_area_of_interest_title}</th>
298
+ )}
259
299
  {columns.includes('year') && <th>Year</th>}
260
300
  {columns.includes('version') && <th>Version</th>}
261
301
  {columns.includes('resolution') && <th>Resolution</th>}
@@ -9,18 +9,18 @@ import { faInfoCircle } from '@fortawesome/free-solid-svg-icons';
9
9
  * @param {string} title Header of Citation.
10
10
  * @param {string} tooltip Tooltip info text.
11
11
  * @param {string} description Description.
12
- * @example <CclInfoDescription
12
+ * @example <CclInfoDescription
13
13
  title="Validation status"
14
14
  description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis luctus
15
15
  mauris ante, a iaculis leo placerat quis.">
16
16
  </CclInfoDescription>
17
- *
17
+ *
18
18
  */
19
19
  function CclInfoDescription({ title, description, tooltip }) {
20
20
  return (
21
21
  <div className="dataset-info-field">
22
22
  <div className="dataset-field-title">
23
- <h3>{title}</h3>
23
+ {title && <h3>{title}</h3>}
24
24
  {tooltip && (
25
25
  <span className="info-icon" tooltip={tooltip} direction="up">
26
26
  <FontAwesomeIcon icon={faInfoCircle} />
@@ -33,7 +33,7 @@ function CclInfoDescription({ title, description, tooltip }) {
33
33
  }
34
34
 
35
35
  CclInfoDescription.propTypes = {
36
- title: PropTypes.string.isRequired,
36
+ title: PropTypes.string,
37
37
  description: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
38
38
  };
39
39
  export default CclInfoDescription;
@@ -24,6 +24,9 @@ const imageMimetypes = [
24
24
  'image/jpg',
25
25
  'image/gif',
26
26
  'image/svg+xml',
27
+ 'image/tif',
28
+ 'image/tiff',
29
+ 'image/bmp',
27
30
  ];
28
31
  const Dropzone = loadable(() => import('react-dropzone'));
29
32
 
@@ -94,15 +97,6 @@ const FileWidget = (props) => {
94
97
  ? `data:${value['content-type']};${value.encoding},${value.data}`
95
98
  : null;
96
99
 
97
- const allowedFileTypes = [
98
- 'image/png',
99
- 'image/jpeg',
100
- 'image/webp',
101
- 'image/jpg',
102
- 'image/gif',
103
- 'image/svg+xml',
104
- ];
105
-
106
100
  /**
107
101
  * Drop handler
108
102
  * @method onDrop
@@ -113,7 +107,7 @@ const FileWidget = (props) => {
113
107
  const file = files[0];
114
108
  readAsDataURL(file).then((data) => {
115
109
  const fields = data.match(/^data:(.*);(.*),(.*)$/);
116
- if (!allowedFileTypes.includes(fields[1])) {
110
+ if (!imageMimetypes.includes(fields[1])) {
117
111
  toast.error(
118
112
  <Toast
119
113
  autoClose={5000}
@@ -135,7 +129,11 @@ const FileWidget = (props) => {
135
129
  let reader = new FileReader();
136
130
  reader.onload = function () {
137
131
  const fields = reader.result.match(/^data:(.*);(.*),(.*)$/);
138
- if (imageMimetypes.includes(fields[1])) {
132
+ if (fields[1] === 'image/tif' || fields[1] === 'image/tiff') {
133
+ setFileType(true);
134
+ let imagePreview = document.getElementById(`field-${id}-image`);
135
+ imagePreview.src = '';
136
+ } else if (imageMimetypes.includes(fields[1])) {
139
137
  setFileType(true);
140
138
  let imagePreview = document.getElementById(`field-${id}-image`);
141
139
  imagePreview.src = reader.result;
@@ -180,7 +180,7 @@ const CheckboxListParent = ({ option, key, onChange, value, id }) => {
180
180
  }}
181
181
  label={
182
182
  <label htmlFor={`field-${option.value}`}>
183
- {option.label.replace(/^[0-9][0-9]#/, '')}
183
+ {option.label}
184
184
  </label>
185
185
  }
186
186
  checked={
@@ -17,39 +17,41 @@
17
17
 
18
18
  export const structure_taxonomy_terms = (choices) => {
19
19
  let options = [];
20
- choices.forEach((choice) => {
21
- var splitted_option = choice.label.split(' » ');
22
- var modified_option = {
23
- value: choice.value,
24
- label:
25
- splitted_option.length > 1
26
- ? splitted_option.slice(-1).pop()
27
- : choice.label,
28
- original: choice.label,
29
- childrens: [],
30
- };
31
- splitted_option.length === 1 && options.push(modified_option);
32
- });
33
- choices.forEach((choice) => {
34
- var splitted_option = choice.label.split(' » ');
35
- var modified_option = {
36
- value: choice.value,
37
- label:
38
- splitted_option.length > 1
39
- ? splitted_option.slice(-1).pop()
40
- : choice.label,
41
- original: choice.label,
42
- childrens: [],
43
- };
44
- if (splitted_option.length > 1) {
45
- var parent_option = splitted_option.slice(0, -1).pop();
46
- options.forEach((opt) => {
47
- if (opt.label === parent_option) {
48
- opt.childrens.push(modified_option);
49
- }
50
- });
51
- }
52
- });
20
+ if (choices.length > 0) {
21
+ choices.forEach((choice) => {
22
+ var splitted_option = choice.label.split(' » ');
23
+ var modified_option = {
24
+ value: choice.value,
25
+ label:
26
+ splitted_option.length > 1
27
+ ? splitted_option.slice(-1).pop()
28
+ : choice.label,
29
+ original: choice.label,
30
+ childrens: [],
31
+ };
32
+ splitted_option.length === 1 && options.push(modified_option);
33
+ });
34
+ choices.forEach((choice) => {
35
+ var splitted_option = choice.label.split(' » ');
36
+ var modified_option = {
37
+ value: choice.value,
38
+ label:
39
+ splitted_option.length > 1
40
+ ? splitted_option.slice(-1).pop()
41
+ : choice.label,
42
+ original: choice.label,
43
+ childrens: [],
44
+ };
45
+ if (splitted_option.length > 1) {
46
+ var parent_option = splitted_option.slice(0, -1).pop();
47
+ options.forEach((opt) => {
48
+ if (opt.label === parent_option) {
49
+ opt.childrens.push(modified_option);
50
+ }
51
+ });
52
+ }
53
+ });
54
+ }
53
55
 
54
56
  // options = options.map((item) => {
55
57
  // item['children'] = sort_array_items_by_key(item['childrens'], 'label');
@@ -58,5 +60,21 @@ export const structure_taxonomy_terms = (choices) => {
58
60
 
59
61
  // return sort_array_items_by_key(options, 'label');
60
62
  //return options.reverse();
63
+
64
+ if (options.length > 0) {
65
+ options = options
66
+ .sort((a, b) => {
67
+ if (a.label < b.label) {
68
+ return -1;
69
+ } else if (a.label > b.label) {
70
+ return 1;
71
+ }
72
+ return 0;
73
+ })
74
+ .map((option) => {
75
+ return { ...option, label: option.label.replace(/^[0-9][0-9]#/, '') };
76
+ });
77
+ }
78
+
61
79
  return options;
62
80
  };
@@ -7,6 +7,7 @@ import { FormFieldWrapper } from '@plone/volto/components';
7
7
  import PropTypes from 'prop-types';
8
8
  import React from 'react';
9
9
  import { defineMessages, useIntl } from 'react-intl';
10
+ import validator from 'validator';
10
11
 
11
12
  /** EmailWidget, a widget for email addresses
12
13
  *
@@ -38,28 +39,36 @@ const EmailWidget = (props) => {
38
39
  id: 'The entered email address is not valid',
39
40
  defaultMessage: 'The entered email address is not valid',
40
41
  },
42
+ valid_email: {
43
+ id: 'Valid email address',
44
+ defaultMessage: 'Valid email address',
45
+ },
41
46
  });
42
47
 
43
48
  const email =
44
49
  typeof window !== 'undefined' && document.getElementById(inputId) !== null
45
50
  ? document.getElementById(inputId).value
46
51
  : '';
52
+
53
+ const input =
54
+ typeof window !== 'undefined' && document.getElementById(inputId) !== null
55
+ ? document.getElementById(inputId)
56
+ : '';
47
57
  // email.addEventListener('input', function (e) {
48
58
  React.useEffect(() => {
49
59
  if (email !== '') {
50
- if (email.validity !== undefined) {
51
- if (email.validity.typeMismatch) {
52
- email.setCustomValidity(intl.formatMessage(messages.invalid_email));
53
- email.reportValidity();
54
- } else {
55
- email.setCustomValidity('');
56
- }
60
+ if (validator.isEmail(email) === false) {
61
+ input.setCustomValidity(intl.formatMessage(messages.invalid_email));
62
+ input.reportValidity();
63
+ } else if (validator.isEmail(email)) {
64
+ input.setCustomValidity(intl.formatMessage(messages.valid_email));
65
+ input.reportValidity();
57
66
  }
58
67
  } else {
59
68
  return;
60
69
  }
61
70
  // eslint-disable-next-line react-hooks/exhaustive-deps
62
- }, [email.value]);
71
+ }, [email]);
63
72
  // });
64
73
 
65
74
  return (
@@ -68,7 +77,7 @@ const EmailWidget = (props) => {
68
77
  <input
69
78
  id={inputId}
70
79
  name={id}
71
- type="email"
80
+ // type="text"
72
81
  value={value || ''}
73
82
  disabled={isDisabled}
74
83
  placeholder={placeholder}
@@ -30,7 +30,9 @@ const TextareaWidget = (props) => {
30
30
  if (maxLength & value?.length) {
31
31
  let remlength = maxLength - value.length;
32
32
  if (remlength < 0) {
33
- setlengthError(`You have exceed word limit by ${Math.abs(remlength)}`);
33
+ setlengthError(
34
+ `You have exceed character limit by ${Math.abs(remlength)}`,
35
+ );
34
36
  } else {
35
37
  setlengthError('');
36
38
  }
@@ -1243,6 +1243,10 @@ div#page-document h1.documentFirstHeading {
1243
1243
  margin-bottom: 0;
1244
1244
  }
1245
1245
 
1246
+ .slate-editor ul > ul {
1247
+ margin-left: 35px;
1248
+ }
1249
+
1246
1250
  // CLMS-1344
1247
1251
  #sidebar-metadata .react-select__option {
1248
1252
  white-space: nowrap;