@eeacms/volto-clms-theme 1.0.41 → 1.0.45

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 (60) hide show
  1. package/CHANGELOG.md +117 -0
  2. package/Jenkinsfile +17 -19
  3. package/package.json +5 -3
  4. package/src/actions/geonetwork/import_geonetwork.js +21 -0
  5. package/src/actions/index.js +16 -0
  6. package/src/actions/registry/registry.js +21 -0
  7. package/src/actions/userschema/userschema.js +17 -0
  8. package/src/components/Blocks/CclHomeBgImageBlock/CclGreenBgView.jsx +32 -8
  9. package/src/components/Blocks/CclHomeBgImageBlock/CclHomeBgImageBlockEdit.jsx +5 -1
  10. package/src/components/Blocks/CclHomeBgImageBlock/CclHomeBgImageSchema.js +36 -7
  11. package/src/components/Blocks/CclRelatedListingBlock/CclRelatedListingEdit.jsx +95 -0
  12. package/src/components/Blocks/CclRelatedListingBlock/CclRelatedListingView.jsx +67 -0
  13. package/src/components/Blocks/CclRelatedListingBlock/schema.js +34 -0
  14. package/src/components/Blocks/CclTextLinkCarouselBlock/CclTextLinkCarouselEdit.jsx +38 -0
  15. package/src/components/Blocks/CclTextLinkCarouselBlock/CclTextLinkCarouselView.jsx +41 -0
  16. package/src/components/Blocks/CclTextLinkCarouselBlock/TextLinkCarouselSchema.js +18 -0
  17. package/src/components/Blocks/CustomTemplates/VoltoListingBlock/CclListingWorkOpportunities.jsx +5 -15
  18. package/src/components/Blocks/CustomTemplates/VoltoTabsBlock/CclCarouselView.jsx +39 -13
  19. package/src/components/Blocks/CustomTemplates/VoltoTabsBlock/CclProductTabsView.jsx +6 -1
  20. package/src/components/Blocks/CustomTemplates/VoltoTabsBlock/CclVerticalFaqTabsView.jsx +19 -60
  21. package/src/components/Blocks/CustomTemplates/VoltoTabsBlock/FixTemplates.jsx +19 -0
  22. package/src/components/Blocks/CustomTemplates/VoltoTabsBlock/custom.less +55 -1
  23. package/src/components/Blocks/CustomTemplates/VoltoTabsBlock/index.js +2 -0
  24. package/src/components/Blocks/customBlocks.js +97 -26
  25. package/src/components/CLMSDatasetDetailView/CLMSDatasetDetailView.jsx +175 -15
  26. package/src/components/CLMSDatasetDetailView/DataSetInfoContent.jsx +20 -13
  27. package/src/components/CLMSDatasetDetailView/MetadataContent.jsx +26 -7
  28. package/src/components/CLMSDownloadCartView/CLMSDownloadCartView.jsx +5 -1
  29. package/src/components/CLMSProfileView/CLMSApiTokensView.jsx +55 -33
  30. package/src/components/CLMSProfileView/CLMSProfileView.jsx +28 -15
  31. package/src/components/CLMSProfileView/CLMSUserProfileView.jsx +37 -64
  32. package/src/components/CclCard/CclCard.jsx +1 -7
  33. package/src/components/CclCard/cards.less +1 -1
  34. package/src/components/CclLoginModal/CclLoginModal.jsx +83 -0
  35. package/src/components/CclLoginModal/ccl-login-modal.css +3 -0
  36. package/src/components/CclModal/CclModal.jsx +20 -5
  37. package/src/components/Widgets/ContactWidget.jsx +91 -0
  38. package/src/components/Widgets/DistributionInfoWidget.jsx +40 -0
  39. package/src/components/Widgets/GeonetworkIdentifiersWidget.jsx +48 -0
  40. package/src/components/Widgets/TextLinkWidget.jsx +41 -0
  41. package/src/constants/ActionTypes.js +1 -0
  42. package/src/customizations/volto/components/theme/Header/Header.jsx +31 -31
  43. package/src/customizations/volto/components/theme/SearchWidget/SearchWidget.jsx +11 -3
  44. package/src/index.js +13 -8
  45. package/src/reducers/geonetwork/import_geonetwork_reducer.js +45 -0
  46. package/src/reducers/index.js +9 -3
  47. package/src/reducers/registry/registry.js +46 -0
  48. package/src/reducers/tokens/tokens.js +14 -10
  49. package/src/reducers/userschema/userschema.js +48 -0
  50. package/theme/clms/css/breadcrumbs.css +1 -0
  51. package/theme/clms/css/carousel.css +109 -11
  52. package/theme/clms/css/forms.css +6 -1
  53. package/theme/clms/css/home.css +29 -4
  54. package/theme/clms/css/maps.css +4 -0
  55. package/theme/clms/css/maps.less +4 -0
  56. package/theme/clms/css/styles.less +12 -3
  57. package/src/components/Blocks/CclTechnicalLibrariesList/CclTechnicalLibrariesListEdit.jsx +0 -63
  58. package/src/components/Blocks/CclTechnicalLibrariesList/CclTechnicalLibrariesListView.jsx +0 -43
  59. package/src/components/Blocks/CclTechnicalLibrariesList/TechnicalLibrariesListSchema.js +0 -17
  60. package/src/components/CLMSServiceDeskView/CLMSServiceDeskView.jsx +0 -113
@@ -0,0 +1,34 @@
1
+ import config from '@plone/volto/registry';
2
+
3
+ const Schema = (types_schema) => {
4
+ const variationsConfig =
5
+ config.blocks.blocksConfig['relatedListing'].variations;
6
+ const variations = Object.keys(variationsConfig).map((variation) => [
7
+ variationsConfig[variation].id,
8
+ variationsConfig[variation].title,
9
+ ]);
10
+ return {
11
+ title: 'Related Items List block',
12
+ fieldsets: [
13
+ {
14
+ id: 'default',
15
+ title: 'Default',
16
+ fields: ['content_type', 'variation'],
17
+ },
18
+ ],
19
+ properties: {
20
+ content_type: {
21
+ title: 'Content Type',
22
+ choices: [...types_schema],
23
+ },
24
+ variation: {
25
+ title: 'Variation',
26
+ type: 'array',
27
+ choices: [...variations],
28
+ },
29
+ },
30
+ required: [],
31
+ };
32
+ };
33
+
34
+ export default Schema;
@@ -0,0 +1,38 @@
1
+ import React /* , { useState } */ from 'react';
2
+
3
+ // import { TextLinkCarouselView } from './TextLinkCarouselView';
4
+ import { SidebarPortal } from '@plone/volto/components';
5
+ import InlineForm from '@plone/volto/components/manage/Form/InlineForm';
6
+ import { TextLinkCarouselSchema } from './TextLinkCarouselSchema';
7
+
8
+ // import { compose } from 'redux';
9
+ // import withObjectBrowser from '@plone/volto/components/manage/Sidebar/ObjectBrowser';
10
+ // import { injectIntl } from 'react-intl';
11
+
12
+ const TextLinkCarouselEdit = (props) => {
13
+ const { block, data, onChangeBlock, selected } = props;
14
+
15
+ return (
16
+ <>
17
+ {data?.textLink?.items.map((item, index) => (
18
+ <div className="text-link-carousel-block" key={index}>
19
+ {item.text}
20
+ </div>
21
+ ))}
22
+ <SidebarPortal selected={selected}>
23
+ <InlineForm
24
+ schema={TextLinkCarouselSchema()}
25
+ title="Home text link carousel"
26
+ onChangeField={(id, value) => {
27
+ onChangeBlock(block, {
28
+ ...data,
29
+ [id]: value,
30
+ });
31
+ }}
32
+ formData={data}
33
+ />
34
+ </SidebarPortal>
35
+ </>
36
+ );
37
+ };
38
+ export default /* compose(withObjectBrowser, injectIntl) */ TextLinkCarouselEdit;
@@ -0,0 +1,41 @@
1
+ import React from 'react';
2
+ import loadable from '@loadable/component';
3
+ const Slider = loadable(() => import('react-slick'));
4
+
5
+ const TextLinkCarouselView = (props) => {
6
+ const { data } = props;
7
+ const slider = React.useRef(null);
8
+
9
+ const { tabsList = [], setActiveTab = () => {} } = props;
10
+ const settings = {
11
+ dots: false,
12
+ infinite: true,
13
+ speed: 500,
14
+ fade: false,
15
+ cssEase: 'linear',
16
+ arrows: false,
17
+ autoplay: true,
18
+ autoplaySpeed: 2000,
19
+ beforeChange: (oldIndex, index) => {
20
+ setActiveTab(tabsList[index]);
21
+ },
22
+ };
23
+
24
+ return (
25
+ <>
26
+ <div class="ccl-container">
27
+ <Slider {...settings} ref={slider} className="text-carousel">
28
+ {data?.textLink?.items.map((item, index) => (
29
+ <div className="text-link-carousel-block" key={index}>
30
+ <div className="text-link-carousel-block-content">
31
+ <a href={'' + item?.link?.[0]?.['@id']}>{item.text}</a>
32
+ </div>
33
+ </div>
34
+ ))}
35
+ </Slider>
36
+ </div>
37
+ </>
38
+ );
39
+ };
40
+
41
+ export default TextLinkCarouselView;
@@ -0,0 +1,18 @@
1
+ export const TextLinkCarouselSchema = () => ({
2
+ title: 'Home text link carousel',
3
+ fieldsets: [
4
+ {
5
+ id: 'default',
6
+ title: 'Default',
7
+ fields: ['textLink'],
8
+ },
9
+ ],
10
+ properties: {
11
+ textLink: {
12
+ title: 'Text and Link',
13
+ widget: 'text_link_widget',
14
+ type: 'string',
15
+ },
16
+ },
17
+ required: [],
18
+ });
@@ -36,19 +36,7 @@ const CclWorkOpportunity = (props) => {
36
36
  );
37
37
  };
38
38
 
39
- function formatDate(date) {
40
- var d = new Date(date),
41
- month = '' + (d.getMonth() + 1),
42
- day = '' + d.getDate(),
43
- year = d.getFullYear();
44
-
45
- if (month.length < 2) month = '0' + month;
46
- if (day.length < 2) day = '0' + day;
47
-
48
- return [year, month, day].join('-');
49
- }
50
-
51
- var Today = formatDate(Date.now());
39
+ var Today = new Date();
52
40
 
53
41
  const CclListingWorkOpportunities = (props) => {
54
42
  const { items, variation } = props;
@@ -61,7 +49,8 @@ const CclListingWorkOpportunities = (props) => {
61
49
  {items
62
50
  .filter(
63
51
  (item) =>
64
- item.submission_deadline < Today && status === 'CloseTenders',
52
+ new Date(item.submission_deadline) < Today &&
53
+ status === 'CloseTenders',
65
54
  )
66
55
  .map((item, index) => (
67
56
  <CclWorkOpportunity
@@ -73,7 +62,8 @@ const CclListingWorkOpportunities = (props) => {
73
62
  {items
74
63
  .filter(
75
64
  (item) =>
76
- item.submission_deadline > Today && status === 'OpenTenders',
65
+ new Date(item.submission_deadline) > Today &&
66
+ status === 'OpenTenders',
77
67
  )
78
68
  .map((item, index) => (
79
69
  <CclWorkOpportunity
@@ -3,12 +3,10 @@ import { connect } from 'react-redux';
3
3
  import { compose } from 'redux';
4
4
  import { withRouter } from 'react-router';
5
5
  import loadable from '@loadable/component';
6
- import { Icon, RenderBlocks } from '@plone/volto/components';
6
+ import { RenderBlocks } from '@plone/volto/components';
7
7
  import { withScrollToTarget } from '@eeacms/volto-tabs-block/hocs';
8
8
  import './custom.less';
9
- import rightArrowSVG from '@eeacms/volto-tabs-block/icons/right-arrow.svg';
10
- import leftArrowSVG from '@eeacms/volto-tabs-block/icons/left-arrow.svg';
11
- // import cx from 'classnames';
9
+ import cx from 'classnames';
12
10
  import 'slick-carousel/slick/slick.css';
13
11
  import 'slick-carousel/slick/slick-theme.css';
14
12
  import '@eeacms/volto-tabs-block/less/carousel.less';
@@ -29,17 +27,43 @@ const View = (props) => {
29
27
  const activeTabIndex = tabsList.indexOf(activeTab);
30
28
 
31
29
  const settings = {
32
- dots: true,
30
+ dots: false,
33
31
  infinite: true,
34
32
  speed: 2000,
35
33
  fade: true,
36
34
  cssEase: 'linear',
37
- autoplay: true,
35
+ autoplay: false,
38
36
  autoplaySpeed: 5000,
39
37
  beforeChange: (oldIndex, index) => {
40
38
  setActiveTab(tabsList[index]);
41
39
  },
42
40
  };
41
+
42
+ const Dots = (props) => {
43
+ const { activeTab = null, tabsList = [], slider = {} } = props;
44
+ return tabsList.length > 1 ? (
45
+ <ul className={cx('slick-dots', props.uiContainer)} role={'tablist'}>
46
+ {tabsList.map((tab, index) => (
47
+ <li
48
+ key={`dot-${tab}`}
49
+ className={cx({ 'slick-active': activeTab === tab })}
50
+ role={'presentation'}
51
+ >
52
+ <button
53
+ onClick={() => {
54
+ if (slider.current) {
55
+ slider.current.slickGoTo(index);
56
+ }
57
+ }}
58
+ />
59
+ </li>
60
+ ))}
61
+ </ul>
62
+ ) : (
63
+ ''
64
+ );
65
+ };
66
+
43
67
  const ArrowsGroup = (props) => {
44
68
  // const { activeTab = null, tabsList = [], slider = {} } = props;
45
69
  // const currentSlide = tabsList.indexOf(activeTab);
@@ -55,9 +79,7 @@ const View = (props) => {
55
79
  slider.current.slickPrev();
56
80
  }
57
81
  }}
58
- >
59
- <Icon name={leftArrowSVG} size="50px" />
60
- </button>
82
+ ></button>
61
83
 
62
84
  <button
63
85
  aria-label="Next slide"
@@ -67,9 +89,7 @@ const View = (props) => {
67
89
  slider.current.slickNext();
68
90
  }
69
91
  }}
70
- >
71
- <Icon name={rightArrowSVG} size="50px" />
72
- </button>
92
+ ></button>
73
93
  </div>
74
94
  );
75
95
  };
@@ -103,6 +123,7 @@ const View = (props) => {
103
123
  /* eslint-disable-next-line */
104
124
  }, [hashlink.counter]);
105
125
 
126
+ const [showInfo, setShowInfo] = React.useState(false);
106
127
  const panes = tabsList.map((tab, index) => {
107
128
  return {
108
129
  id: tab,
@@ -111,7 +132,11 @@ const View = (props) => {
111
132
  key={`slide-${tab}`}
112
133
  {...props}
113
134
  metadata={metadata}
114
- content={tabs[tab]}
135
+ content={{
136
+ ...tabs[tab],
137
+ setShowInfo: setShowInfo,
138
+ showInfo: showInfo,
139
+ }}
115
140
  />
116
141
  ),
117
142
  };
@@ -123,6 +148,7 @@ const View = (props) => {
123
148
  {panes.length ? panes.map((pane) => pane.renderItem) : ''}
124
149
  </Slider>
125
150
  <ArrowsGroup activeTab={activeTab} tabsList={tabsList} slider={slider} />
151
+ <Dots activeTab={activeTab} tabsList={tabsList} slider={slider} />
126
152
  </>
127
153
  );
128
154
  };
@@ -1,8 +1,10 @@
1
1
  import React from 'react';
2
2
  import CclVerticalTabsView from './CclVerticalTabsView';
3
3
  import { FormattedMessage } from 'react-intl';
4
+ import { useSelector } from 'react-redux';
4
5
 
5
6
  const CclProductTabsView = (props) => {
7
+ const locale = useSelector((state) => state.intl.locale);
6
8
  const ExtraComponent = () => (
7
9
  <div className="left-menu-detail">
8
10
  <div className="menu-detail-image">
@@ -20,7 +22,10 @@ const CclProductTabsView = (props) => {
20
22
  )}
21
23
  </div>
22
24
  <div className="menu-detail-button">
23
- <a href="/" className="ccl-button ccl-button--default">
25
+ <a
26
+ href={'/' + locale + '/map-viewer?product=' + props.metadata['UID']}
27
+ className="ccl-button ccl-button--default"
28
+ >
24
29
  <FormattedMessage
25
30
  id="View in the map viewer"
26
31
  defaultMessage="View in the map viewer"
@@ -7,52 +7,10 @@ import { withScrollToTarget } from '@eeacms/volto-tabs-block/hocs';
7
7
  import './fontawesome';
8
8
  import cx from 'classnames';
9
9
  import './custom.less';
10
+ import { Route, NavLink } from 'react-router-dom';
10
11
 
11
12
  const CclVerticalFaqTabsView = (props) => {
12
- const [hashlinkOnMount, setHashlinkOnMount] = React.useState(false);
13
- const {
14
- metadata = {},
15
- data = {},
16
- tabsList = [],
17
- activeTabIndex = 0,
18
- hashlink = {},
19
- setActiveTab = () => {},
20
- } = props;
21
-
22
- React.useEffect(() => {
23
- const urlHash = props.location.hash.substring(1) || '';
24
- if (
25
- hashlink.counter > 0 ||
26
- (hashlink.counter === 0 && urlHash && !hashlinkOnMount)
27
- ) {
28
- const id = hashlink.hash || urlHash || '';
29
- const index = tabsList.indexOf(id);
30
- const parentId = data.id || props.id;
31
- const parent = document.getElementById(parentId);
32
- const headerWrapper = document.querySelector('.header-wrapper');
33
- const offsetHeight = headerWrapper?.offsetHeight || 0;
34
- if (id !== parentId && index > -1 && parent) {
35
- if (activeTabIndex !== index) {
36
- setActiveTab(id);
37
- }
38
- props.scrollToTarget(parent, offsetHeight);
39
- } else if (id === parentId && parent) {
40
- props.scrollToTarget(parent, offsetHeight);
41
- }
42
- }
43
- if (!hashlinkOnMount) {
44
- setHashlinkOnMount(true);
45
- }
46
- }, [
47
- activeTabIndex,
48
- data.id,
49
- hashlink.counter,
50
- hashlink.hash,
51
- hashlinkOnMount,
52
- props,
53
- setActiveTab,
54
- tabsList,
55
- ]);
13
+ const { metadata = {}, tabsList = [] } = props;
56
14
 
57
15
  const PanelsComponent = () => {
58
16
  const { activeTab = null, tabs = {} } = props;
@@ -60,18 +18,20 @@ const CclVerticalFaqTabsView = (props) => {
60
18
  <div className="right-content cont-w-75">
61
19
  {tabsList.map((tab, index) => {
62
20
  return (
63
- <div
64
- key={index}
65
- className={cx('panel', tab === activeTab && 'panel-selected')}
66
- role="tabpanel"
67
- aria-hidden="false"
68
- >
69
- <RenderBlocks
70
- {...props}
71
- metadata={metadata}
72
- content={tabs[tab]}
73
- />
74
- </div>
21
+ <Route to={'#' + activeTab}>
22
+ <div
23
+ key={index}
24
+ className={cx('panel', tab === activeTab && 'panel-selected')}
25
+ role="tabpanel"
26
+ aria-hidden="false"
27
+ >
28
+ <RenderBlocks
29
+ {...props}
30
+ metadata={metadata}
31
+ content={tabs[tab]}
32
+ />
33
+ </div>
34
+ </Route>
75
35
  );
76
36
  })}
77
37
  </div>
@@ -96,11 +56,10 @@ const CclVerticalFaqTabsView = (props) => {
96
56
  id={tabIndex}
97
57
  className={cx('card', tab === activeTab && 'active')}
98
58
  >
99
- <a
100
- href={'#' + tabIndex}
59
+ <NavLink
60
+ to={'#tab' + tabIndex}
101
61
  className="collapsed"
102
62
  onClick={(e) => {
103
- e.preventDefault();
104
63
  if (activeTab !== tab) {
105
64
  setActiveTab(tab);
106
65
  }
@@ -112,7 +71,7 @@ const CclVerticalFaqTabsView = (props) => {
112
71
  }}
113
72
  >
114
73
  {title || defaultTitle}
115
- </a>
74
+ </NavLink>
116
75
  </div>
117
76
  );
118
77
  })}
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import config from '@plone/volto/registry';
3
+ import { TABS_BLOCK } from '@eeacms/volto-tabs-block/constants';
4
+
5
+ const FixTemplates = (TabView) =>
6
+ function Component(props) {
7
+ const deprecated_templates =
8
+ config.blocks.blocksConfig[TABS_BLOCK].deprecated_templates;
9
+ const { data = {} } = props;
10
+ const deprecated = deprecated_templates.includes(data.template);
11
+ const new_props = {
12
+ ...props,
13
+ data: { ...data, template: deprecated ? 'default' : data.template },
14
+ };
15
+
16
+ return <TabView {...new_props} />;
17
+ };
18
+
19
+ export default FixTemplates;
@@ -9,12 +9,18 @@ div.tabs-block.CCLCarousel {
9
9
  left: 50% !important;
10
10
  width: 100vw !important;
11
11
  max-width: initial !important;
12
- // margin-top: -2rem;
13
12
  margin-right: -50vw !important;
14
13
  margin-left: -50vw !important;
15
14
  }
16
15
  }
17
16
 
17
+ .slick-slider.text-carousel {
18
+ div & {
19
+ z-index: 1;
20
+ width: 60%;
21
+ }
22
+ }
23
+
18
24
  .tabs-block .slick-slider {
19
25
  z-index: 1;
20
26
  }
@@ -22,3 +28,51 @@ div.tabs-block.CCLCarousel {
22
28
  .slick-arrows {
23
29
  margin-top: -2rem !important;
24
30
  }
31
+
32
+ .text-link-carousel-block {
33
+ height: 2rem;
34
+ padding: 0;
35
+ }
36
+
37
+ .text-link-carousel-block-content {
38
+ display: flex;
39
+ height: 2rem;
40
+ flex-direction: column;
41
+ justify-content: center;
42
+ }
43
+
44
+ .text-link-carousel-block .text-link-carousel-block-content > a,
45
+ .text-link-carousel-block .text-link-carousel-block-content > a:hover {
46
+ color: #fff;
47
+ }
48
+
49
+ p.styled-slate {
50
+ margin-bottom: 0;
51
+ }
52
+
53
+ @media (max-width: 1200px) {
54
+ .text-link-carousel-block {
55
+ height: fit-content !important;
56
+ margin: 0.5rem;
57
+ margin-top: -2rem;
58
+ }
59
+
60
+ .text-carousel {
61
+ margin: 0.5rem;
62
+ margin-top: -2rem;
63
+ }
64
+
65
+ .text-link-carousel-block-content {
66
+ height: fit-content !important;
67
+ }
68
+ }
69
+
70
+ @media (max-width: 420px) {
71
+ .text-link-carousel-block {
72
+ margin-top: -4rem;
73
+ }
74
+
75
+ .text-carousel {
76
+ margin-top: -4rem;
77
+ }
78
+ }
@@ -4,6 +4,7 @@ import CclVerticalFaqTabsView from './CclVerticalFaqTabsView';
4
4
  import CclCarouselView from './CclCarouselView';
5
5
  import RoutingHOC from './RoutingHOC';
6
6
  import CclProductTabsView from './CclProductTabsView';
7
+ import FixTemplates from './FixTemplates';
7
8
 
8
9
  export {
9
10
  CclTabsView,
@@ -12,4 +13,5 @@ export {
12
13
  CclCarouselView,
13
14
  RoutingHOC,
14
15
  CclProductTabsView,
16
+ FixTemplates,
15
17
  };