@eeacms/volto-clms-theme 1.0.44 → 1.0.48

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 (54) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/Jenkinsfile +32 -24
  3. package/package.json +5 -1
  4. package/src/actions/geonetwork/import_geonetwork.js +21 -0
  5. package/src/actions/index.js +14 -0
  6. package/src/actions/userschema/userschema.js +17 -0
  7. package/src/components/Blocks/CclTextLinkCarouselBlock/CclTextLinkCarouselEdit.jsx +38 -0
  8. package/src/components/Blocks/CclTextLinkCarouselBlock/CclTextLinkCarouselView.jsx +41 -0
  9. package/src/components/Blocks/CclTextLinkCarouselBlock/TextLinkCarouselSchema.js +18 -0
  10. package/src/components/Blocks/CustomTemplates/VoltoTabsBlock/CclCarouselView.jsx +32 -11
  11. package/src/components/Blocks/CustomTemplates/VoltoTabsBlock/CclProductTabsView.jsx +1 -1
  12. package/src/components/Blocks/CustomTemplates/VoltoTabsBlock/CclVerticalTabsView.jsx +21 -7
  13. package/src/components/Blocks/CustomTemplates/VoltoTabsBlock/TabsWidget.jsx +78 -15
  14. package/src/components/Blocks/CustomTemplates/VoltoTabsBlock/custom.less +60 -1
  15. package/src/components/Blocks/CustomTemplates/VoltoTabsBlock/subTabSchema.js +19 -0
  16. package/src/components/Blocks/customBlocks.js +19 -0
  17. package/src/components/CLMSDatasetDetailView/BoundingBoxComponent.jsx +20 -0
  18. package/src/components/CLMSDatasetDetailView/CLMSDatasetDetailView.jsx +169 -15
  19. package/src/components/CLMSDatasetDetailView/ContactComponent.jsx +44 -0
  20. package/src/components/CLMSDatasetDetailView/DataSetInfoContent.jsx +14 -6
  21. package/src/components/CLMSDatasetDetailView/DistributionInfoComponent.jsx +20 -0
  22. package/src/components/CLMSDatasetDetailView/MetadataContent.jsx +182 -72
  23. package/src/components/CLMSDownloadCartView/CLMSDownloadCartView.jsx +5 -1
  24. package/src/components/CLMSEventView/CLMSEventView.jsx +15 -13
  25. package/src/components/CLMSNewsItemView/CLMSNewsItemView.jsx +13 -11
  26. package/src/components/CLMSProfileView/CLMSApiTokensView.jsx +55 -33
  27. package/src/components/CLMSProfileView/CLMSProfileView.jsx +28 -15
  28. package/src/components/CLMSProfileView/CLMSUserProfileView.jsx +37 -64
  29. package/src/components/CclCard/CclCard.jsx +8 -5
  30. package/src/components/CclCard/cards.less +1 -1
  31. package/src/components/CclInfoDescription/CclInfoDescription.jsx +9 -8
  32. package/src/components/CclLoginModal/CclLoginModal.jsx +1 -7
  33. package/src/components/CclLoginModal/ccl-login-modal.css +0 -4
  34. package/src/components/CclModal/CclModal.jsx +6 -1
  35. package/src/components/CclTab/CclTab.jsx +8 -11
  36. package/src/components/CclTab/CclTabs.jsx +23 -8
  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 +30 -21
  43. package/src/index.js +8 -3
  44. package/src/reducers/geonetwork/import_geonetwork_reducer.js +45 -0
  45. package/src/reducers/index.js +7 -3
  46. package/src/reducers/tokens/tokens.js +14 -10
  47. package/src/reducers/userschema/userschema.js +48 -0
  48. package/theme/clms/css/block-form.less +62 -0
  49. package/theme/clms/css/carousel.css +64 -11
  50. package/theme/clms/css/home.css +18 -4
  51. package/theme/clms/css/maps.css +4 -0
  52. package/theme/clms/css/maps.less +4 -0
  53. package/theme/clms/css/menu.css +4 -0
  54. package/theme/clms/css/styles.less +15 -3
@@ -1,23 +1,28 @@
1
- import React from 'react';
2
- import { v4 as uuid } from 'uuid';
1
+ import './fontawesome';
2
+
3
+ import { FormFieldWrapper, Icon } from '@plone/volto/components';
4
+ import { Grid, Header } from 'semantic-ui-react';
5
+ import { faExternalLinkAlt, faIcons } from '@fortawesome/free-solid-svg-icons';
3
6
  import { omit, without } from 'lodash';
4
- import move from 'lodash-move';
5
- import { Icon, FormFieldWrapper } from '@plone/volto/components';
7
+
6
8
  import { DragDropList } from '@plone/volto/components';
7
- import { emptyTab } from '@eeacms/volto-tabs-block/helpers';
9
+ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
10
+ import InlineForm from '@plone/volto/components/manage/Form/InlineForm';
11
+ import React from 'react';
12
+ import { SidebarPopup } from '@plone/volto/components';
8
13
  import { StyleWrapperEdit } from '@eeacms/volto-block-style/StyleWrapper';
14
+ import clearSVG from '@plone/volto/icons/clear.svg';
9
15
  import dragSVG from '@plone/volto/icons/drag.svg';
16
+ import { emptyTab } from '@eeacms/volto-tabs-block/helpers';
17
+ import { fontAwesomeSchema } from './fontAwesomeSchema';
18
+ import leftMenuSVG from '@plone/volto/icons/nav.svg';
19
+ import move from 'lodash-move';
20
+ import plusSVG from '@plone/volto/icons/circle-plus.svg';
21
+ import rightSVG from '@plone/volto/icons/right-key.svg';
22
+ import { subTabSchema } from './subTabSchema';
10
23
  import themeSVG from '@plone/volto/icons/theme.svg';
11
- import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
12
- import { faIcons, faExternalLinkAlt } from '@fortawesome/free-solid-svg-icons';
13
24
  import trashSVG from '@plone/volto/icons/delete.svg';
14
- import plusSVG from '@plone/volto/icons/circle-plus.svg';
15
- import { SidebarPopup } from '@plone/volto/components';
16
- import { fontAwesomeSchema } from './fontAwesomeSchema';
17
- import InlineForm from '@plone/volto/components/manage/Form/InlineForm';
18
- import clearSVG from '@plone/volto/icons/clear.svg';
19
- import './fontawesome';
20
- import { Header, Grid } from 'semantic-ui-react';
25
+ import { v4 as uuid } from 'uuid';
21
26
 
22
27
  export function moveColumn(formData, source, destination) {
23
28
  return {
@@ -36,6 +41,7 @@ const TabsWidget = (props) => {
36
41
  const [blockStyleVisible, setBlockStyleVisible] = React.useState(false);
37
42
  const [activeTabId, setActiveTabId] = React.useState(0);
38
43
  const [activeFontAwesomePopup, setActiveFontAwesomePopup] = React.useState(0);
44
+ const [activeSubTabPopup, setActiveSubTabPopup] = React.useState(0);
39
45
 
40
46
  const { value = {}, id, onChange } = props;
41
47
  const { blocks = {} } = value;
@@ -83,7 +89,18 @@ const TabsWidget = (props) => {
83
89
  <Icon name={dragSVG} size="18px" />
84
90
  </div>
85
91
  <div className="tab-area">
86
- <div className="label">
92
+ <div
93
+ className="label"
94
+ style={{
95
+ textOverflow: 'ellipsis',
96
+ whiteSpace: 'nowrap',
97
+ overflow: 'hidden',
98
+ maxWidth: '65%',
99
+ }}
100
+ >
101
+ {child.subTab?.subtab === true && (
102
+ <Icon name={rightSVG} size="18px" />
103
+ )}
87
104
  {child.title || `Tab ${index + 1}`}
88
105
  </div>
89
106
  <button
@@ -190,6 +207,52 @@ const TabsWidget = (props) => {
190
207
  />
191
208
  </SidebarPopup>
192
209
 
210
+ <button
211
+ onClick={() => {
212
+ setActiveTabId(childId);
213
+ setActiveSubTabPopup(true);
214
+ }}
215
+ title="Sub Tab"
216
+ >
217
+ <Icon size={'24px'} name={leftMenuSVG} />
218
+ </button>
219
+ <SidebarPopup open={activeSubTabPopup}>
220
+ <InlineForm
221
+ schema={subTabSchema()}
222
+ title={
223
+ <>
224
+ {subTabSchema().title}
225
+ <button
226
+ onClick={() => {
227
+ setActiveSubTabPopup(false);
228
+ }}
229
+ style={{ float: 'right' }}
230
+ >
231
+ <Icon name={clearSVG} size="24px" />
232
+ </button>
233
+ </>
234
+ }
235
+ formData={{
236
+ ...activeTabData?.subTab,
237
+ }}
238
+ onChangeField={(idTab, formValue) => {
239
+ onChange(id, {
240
+ ...value,
241
+ blocks: {
242
+ ...value.blocks,
243
+ [activeTabId]: {
244
+ ...(activeTabData || {}),
245
+ subTab: {
246
+ ...activeTabData?.subTab,
247
+ [idTab]: formValue,
248
+ },
249
+ },
250
+ },
251
+ });
252
+ }}
253
+ />
254
+ </SidebarPopup>
255
+
193
256
  {value.blocks_layout?.items?.length > 1 ? (
194
257
  <button
195
258
  onClick={() => {
@@ -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,56 @@ 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
+ }
79
+
80
+ div.tabs-block.edit a.item.active p.menu-item-text {
81
+ border-style: none none solid none;
82
+ font-weight: bold;
83
+ }
@@ -0,0 +1,19 @@
1
+ export const subTabSchema = () => ({
2
+ title: 'Vertical tab block',
3
+ fieldsets: [
4
+ {
5
+ id: 'default',
6
+ title: 'Default',
7
+ fields: ['subtab'],
8
+ },
9
+ ],
10
+ properties: {
11
+ subtab: {
12
+ title: 'Is subtab',
13
+ description: 'Define if this tab is a subTab',
14
+ type: 'boolean',
15
+ default: false,
16
+ },
17
+ },
18
+ required: [],
19
+ });
@@ -68,6 +68,9 @@ import CclRelatedListingView from '@eeacms/volto-clms-theme/components/Blocks/Cc
68
68
  import CclRelatedListingEdit from '@eeacms/volto-clms-theme/components/Blocks/CclRelatedListingBlock/CclRelatedListingEdit';
69
69
  import RelatedListingSchema from '@eeacms/volto-clms-theme/components/Blocks/CclRelatedListingBlock/schema';
70
70
 
71
+ import TextLinkCarouselView from '@eeacms/volto-clms-theme/components/Blocks/CclTextLinkCarouselBlock/CclTextLinkCarouselView';
72
+ import TextLinkCarouselEdit from '@eeacms/volto-clms-theme/components/Blocks/CclTextLinkCarouselBlock/CclTextLinkCarouselEdit';
73
+
71
74
  import upSVG from '@plone/volto/icons/up-key.svg';
72
75
  import downSVG from '@plone/volto/icons/down-key.svg';
73
76
 
@@ -436,6 +439,22 @@ const customBlocks = (config) => ({
436
439
  },
437
440
  ],
438
441
  },
442
+ textLinkCarousel: {
443
+ id: 'textLinkCarousel', // The name (id) of the block
444
+ title: 'Text and Link Carousel', // The display name of the block
445
+ icon: homeBand, // The icon used in the block chooser
446
+ group: 'ccl_blocks', // The group (blocks can be grouped, displayed in the chooser)
447
+ view: TextLinkCarouselView, // The view mode component
448
+ edit: TextLinkCarouselEdit, // The edit mode component
449
+ restricted: false, // If the block is restricted, it won't show in the chooser
450
+ mostUsed: false, // A meta group `most used`, appearing at the top of the chooser
451
+ blockHasOwnFocusManagement: false, // Set this to true if the block manages its own focus
452
+ sidebarTab: 1, // The sidebar tab you want to be selected when selecting the block
453
+ security: {
454
+ addPermission: [], // Future proof (not implemented yet) add user permission role(s)
455
+ view: [], // Future proof (not implemented yet) view user role(s)
456
+ },
457
+ },
439
458
  });
440
459
 
441
460
  export default customBlocks;
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+
3
+ const BoundingBoxComponent = (props) => {
4
+ const { north, south, east, west } = props.bbox;
5
+
6
+ return (
7
+ <div className="bounding-box-container">
8
+ <h3>Bounding Box</h3>
9
+ <div className="bounding-box-item">
10
+ {east && <div className="bounding-box-item">East: {east}</div>}
11
+ {west && <div className="bounding-box-item">West: {west}</div>}
12
+ {north && <div className="bounding-box-item">North: {north}</div>}
13
+ {south && <div className="bounding-box-item">South: {south}</div>}
14
+ </div>
15
+ <br />
16
+ </div>
17
+ );
18
+ };
19
+
20
+ export default BoundingBoxComponent;
@@ -3,21 +3,27 @@
3
3
  * @module components/theme/View/CLMSDatasetDetailView
4
4
  */
5
5
 
6
- import React from 'react';
7
- import PropTypes from 'prop-types';
8
- // import { FormattedMessage } from 'react-intl';
9
- import CclButton from '@eeacms/volto-clms-theme/components/CclButton/CclButton';
10
- import CclTabs from '@eeacms/volto-clms-theme/components/CclTab/CclTabs';
11
6
  import {
12
7
  DataSetInfoContent,
13
8
  DownloadDataSetContent,
14
9
  MetadataContent,
15
10
  } from '@eeacms/volto-clms-theme/components/CLMSDatasetDetailView';
16
- import { useLocation } from 'react-router-dom';
11
+ import { Modal, Segment } from 'semantic-ui-react';
12
+ import { useDispatch, useSelector } from 'react-redux';
13
+
14
+ import CclButton from '@eeacms/volto-clms-theme/components/CclButton/CclButton';
15
+ import CclTabs from '@eeacms/volto-clms-theme/components/CclTab/CclTabs';
16
+ import { FormattedMessage } from 'react-intl';
17
+ import PropTypes from 'prop-types';
18
+ import React from 'react';
17
19
  import { compose } from 'redux';
18
20
  import { connect } from 'react-redux';
19
- import jwtDecode from 'jwt-decode';
21
+ import { getUser } from '@plone/volto/actions';
20
22
  import { injectIntl } from 'react-intl';
23
+ import jwtDecode from 'jwt-decode';
24
+ import { postImportGeonetwork } from '../../actions';
25
+ import { useLocation } from 'react-router-dom';
26
+
21
27
  // import {
22
28
  // mockDatabaseInfo,
23
29
  // mockMetadata,
@@ -35,20 +41,163 @@ import { injectIntl } from 'react-intl';
35
41
 
36
42
  const CLMSDatasetDetailView = ({ content, token }) => {
37
43
  const location = useLocation();
44
+ const dispatch = useDispatch();
45
+ const geonetwork_importation = useSelector(
46
+ (state) => state.geonetwork_importation,
47
+ );
48
+ // const userSession = useSelector((state) => state.userSession);
49
+ // const user_token = userSession.token ? jwtDecode(userSession.token).sub : '';
50
+ const user = useSelector((state) => state.users?.user);
51
+ React.useEffect(() => {
52
+ dispatch(getUser(token));
53
+ }, [dispatch, token]);
54
+
55
+ function handleImport(id, type) {
56
+ dispatch(postImportGeonetwork(location.pathname, id, type));
57
+ }
58
+ const [open, setOpen] = React.useState({});
59
+ const locale = useSelector((state) => state.intl.locale);
38
60
 
39
61
  return (
40
62
  <div className="ccl-container ">
41
63
  <h1 className="page-title">{content.title}</h1>
64
+ {content.geonetwork_identifiers?.items?.length > 0 &&
65
+ user.roles &&
66
+ user.roles.includes('Manager') && (
67
+ <Segment.Group compact horizontal>
68
+ {content.geonetwork_identifiers?.items.map((item) => {
69
+ return (
70
+ <Segment
71
+ padded={'very'}
72
+ color={'olive'}
73
+ key={item.id}
74
+ loading={geonetwork_importation.loading}
75
+ circular
76
+ >
77
+ <strong>
78
+ {item.title} (from {item.type}):{' '}
79
+ </strong>
80
+ <br />
81
+ <br />
82
+ <Modal
83
+ onClose={() => {
84
+ setOpen({ ...open, [item.id]: false });
85
+ }}
86
+ onOpen={() => {
87
+ setOpen({ ...open, [item.id]: true });
88
+ }}
89
+ open={open[item.id]}
90
+ trigger={
91
+ <CclButton>
92
+ <FormattedMessage
93
+ id="Import data"
94
+ defaultMessage="Import data"
95
+ />
96
+ </CclButton>
97
+ }
98
+ className={'modal-clms'}
99
+ >
100
+ <div className={'modal-clms-background'}>
101
+ <div className={'modal-clms-container'}>
102
+ <div className={'modal-close modal-clms-close'}>
103
+ <span
104
+ className="ccl-icon-close"
105
+ aria-label="Close"
106
+ onClick={() => {
107
+ setOpen({ ...open, [item.id]: false });
108
+ }}
109
+ onKeyDown={() => {
110
+ setOpen({ ...open, [item.id]: false });
111
+ }}
112
+ tabIndex="0"
113
+ role="button"
114
+ ></span>
115
+ </div>
116
+ <div className="modal-login-text">
117
+ <h1>
118
+ <FormattedMessage
119
+ id="Import from GeoNetwork"
120
+ defaultMessage="Import from GeoNetwork"
121
+ />
122
+ </h1>
123
+ This action will import the data from{' '}
124
+ <strong>{item.title}</strong> (from {item.type}) into
125
+ this dataset.
126
+ <br />
127
+ <br />
128
+ <a
129
+ target="_blank"
130
+ rel="noreferrer"
131
+ href={
132
+ item.type === 'EEA'
133
+ ? 'https://sdi.eea.europa.eu/catalogue/srv/eng/catalog.search#/metadata/' +
134
+ item.id
135
+ : 'https://land.copernicus.vgt.vito.be/geonetwork/srv/eng/catalog.search#/metadata/' +
136
+ item.id
137
+ }
138
+ >
139
+ {item.type === 'EEA' && (
140
+ <FormattedMessage
141
+ id="EEA Geonetwork element"
142
+ defaultMessage="EEA Geonetwork element"
143
+ />
144
+ )}
145
+ {item.type === 'VITO' && (
146
+ <FormattedMessage
147
+ id="VITO Geonetwork element"
148
+ defaultMessage="VITO Geonetwork element"
149
+ />
150
+ )}
151
+ </a>
152
+ </div>
153
+ <CclButton
154
+ onClick={() => {
155
+ handleImport(item.id, item.type);
156
+ setOpen({ ...open, [item.id]: false });
157
+ }}
158
+ mode="filled"
159
+ >
160
+ <FormattedMessage
161
+ id="Import data"
162
+ defaultMessage="Import data"
163
+ />
164
+ </CclButton>
165
+ </div>
166
+ </div>
167
+ </Modal>
168
+ {geonetwork_importation.imported_data
169
+ ?.requested_geonetwork_id === item.id && (
170
+ <p>
171
+ {geonetwork_importation.loaded &&
172
+ geonetwork_importation.error === null && (
173
+ <strong>
174
+ {' '}
175
+ The data has been successfully imported
176
+ </strong>
177
+ )}
178
+ </p>
179
+ )}
180
+ {geonetwork_importation.imported_data?.status === 'error' && (
181
+ <p>
182
+ <strong>
183
+ {' '}
184
+ {geonetwork_importation.imported_data?.message}
185
+ </strong>
186
+ </p>
187
+ )}
188
+ </Segment>
189
+ );
190
+ })}
191
+ </Segment.Group>
192
+ )}
42
193
  <CclTabs>
43
194
  <div tabTitle="General Info">{DataSetInfoContent(content)}</div>
44
195
  <div tabTitle="Metadata">{MetadataContent(content)}</div>
45
- {(content.mapviewer_viewservice?.length === 0 ||
46
- content.mapviewer_viewservice === null) &&
47
- (content.downloadable_files?.items?.length === 0 ||
48
- content.downloadable_files === null) ? (
49
- <div tabTitle=""></div>
50
- ) : (
196
+
197
+ {content?.downloadable_dataset ? (
51
198
  <div tabTitle="Download">{DownloadDataSetContent(content)}</div>
199
+ ) : (
200
+ <div tabTitle=""></div>
52
201
  )}
53
202
 
54
203
  <div underPanel={true}>
@@ -63,8 +212,13 @@ const CLMSDatasetDetailView = ({ content, token }) => {
63
212
  )}
64
213
  {content?.mapviewer_viewservice?.length > 0 && (
65
214
  <div className="menu-detail-button">
66
- <CclButton url={location.pathname + '/map-viewer'}>
67
- View in the map viewer
215
+ <CclButton
216
+ url={'/' + locale + '/map-viewer?dataset=' + content.UID}
217
+ >
218
+ <FormattedMessage
219
+ id="View in the map viewer"
220
+ defaultMessage="View in the map viewer"
221
+ />
68
222
  </CclButton>
69
223
  </div>
70
224
  )}
@@ -0,0 +1,44 @@
1
+ import React from 'react';
2
+
3
+ const ContactComponent = (props) => {
4
+ const {
5
+ organisationName,
6
+ deliveryPoint,
7
+ city,
8
+ administrativeArea,
9
+ postalCode,
10
+ country,
11
+ electronicMailAddress,
12
+ url,
13
+ urlTitle,
14
+ roleCode,
15
+ } = props.contact;
16
+
17
+ return (
18
+ <div className="contact-container">
19
+ <h3>Contact</h3>
20
+ <div className="contact-item">
21
+ {city && <div className="contact-item">{city}</div>}
22
+ {organisationName && (
23
+ <div className="contact-item">{organisationName}</div>
24
+ )}
25
+ {deliveryPoint && <div className="contact-item">{deliveryPoint}</div>}
26
+ {city && <div className="contact-item">{city}</div>}
27
+ {administrativeArea && (
28
+ <div className="contact-item">{administrativeArea}</div>
29
+ )}
30
+ {postalCode && <div className="contact-item">{postalCode}</div>}
31
+ {country && <div className="contact-item">{country}</div>}
32
+ {electronicMailAddress && (
33
+ <div className="contact-item">{electronicMailAddress}</div>
34
+ )}
35
+ {url && <div className="contact-item">{url}</div>}
36
+ {urlTitle && <div className="contact-item">{urlTitle}</div>}
37
+ {roleCode && <div className="contact-item">Role: {roleCode}</div>}
38
+ </div>
39
+ <br />
40
+ </div>
41
+ );
42
+ };
43
+
44
+ export default ContactComponent;
@@ -51,12 +51,13 @@ const DataSetInfoContent = (props) => {
51
51
 
52
52
  return (
53
53
  <div>
54
- <CclCitation title="Validation status" marginBottom={true}>
55
- <p>
56
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis luctus
57
- mauris ante, a iaculis leo placerat quis.
58
- </p>
59
- </CclCitation>
54
+ {props?.validation?.data && (
55
+ <CclCitation
56
+ title="Validation status"
57
+ marginBottom={true}
58
+ children={<StringToHTML string={props.validation.data} />}
59
+ ></CclCitation>
60
+ )}
60
61
  <CclInfoContainer>
61
62
  <h2>General Info</h2>
62
63
 
@@ -129,6 +130,13 @@ const DataSetInfoContent = (props) => {
129
130
  </div>
130
131
  </div>
131
132
  )}
133
+
134
+ <CclCitation title="Dataset citation" marginBottom={true}>
135
+ <p>
136
+ © European Union, Copernicus Land Monitoring Service , European
137
+ Environment Agency (EEA)
138
+ </p>
139
+ </CclCitation>
132
140
  </div>
133
141
  );
134
142
  };
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+
3
+ const DistributionInfoComponent = (props) => {
4
+ const { resourceLocator, services } = props.resource;
5
+
6
+ return (
7
+ <div className="distribution-info-container">
8
+ <h3>Resource</h3>
9
+ <div className="distribution-info-item">
10
+ {resourceLocator && (
11
+ <div className="distribution-info-item">{resourceLocator}</div>
12
+ )}
13
+ {services && <div className="distribution-info-item">{services}</div>}
14
+ </div>
15
+ <br />
16
+ </div>
17
+ );
18
+ };
19
+
20
+ export default DistributionInfoComponent;