@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
@@ -67,7 +67,7 @@ const messages = defineMessages({
67
67
  },
68
68
  createdToken: {
69
69
  id: 'Created token name',
70
- defaultMessage: 'Token',
70
+ defaultMessage: 'The token has been created successfuly',
71
71
  },
72
72
  copyButton: {
73
73
  id: 'Copy created token button',
@@ -144,11 +144,12 @@ class CLMSApiTokensView extends Component {
144
144
  ip_range: PropTypes.string,
145
145
  issued: PropTypes.string,
146
146
  key_id: PropTypes.string,
147
- last_used: PropTypes.string,
148
- title: PropTypes.string,
147
+ public_key: PropTypes.string,
148
+ private_key: PropTypes.string,
149
149
  }),
150
150
  ),
151
151
  };
152
+
152
153
  constructor(props) {
153
154
  super(props);
154
155
  this.handleChange = this.handleChange.bind(this);
@@ -184,12 +185,9 @@ class CLMSApiTokensView extends Component {
184
185
  onClose() {
185
186
  this.componentDidMount();
186
187
  this.setState({
187
- value: '',
188
- createdToken: false,
189
- modal: false,
190
- tokenTitle: '',
191
- textToCopy: '',
192
188
  createNewToken: false,
189
+ public_key: undefined,
190
+ private_key: undefined,
193
191
  });
194
192
  }
195
193
 
@@ -203,10 +201,10 @@ class CLMSApiTokensView extends Component {
203
201
 
204
202
  handleClick() {
205
203
  this.setState({
206
- createdToken: true,
207
204
  modal: false,
208
- button: false,
209
205
  createNewToken: true,
206
+ public_key: undefined,
207
+ private_key: undefined,
210
208
  });
211
209
  }
212
210
 
@@ -225,14 +223,14 @@ class CLMSApiTokensView extends Component {
225
223
  this.props.getUser(this.props.userId);
226
224
  this.props.getTokens();
227
225
  this.setState({
228
- value: '',
229
- tokenTitle: '',
226
+ value: undefined,
227
+ tokenTitle: undefined,
230
228
  button: false,
231
- createNewToken: true,
229
+ // createNewToken: true,
232
230
  modal: false,
233
231
  createdToken: false,
234
- textToCopy: '',
235
- key_id: '',
232
+ textToCopy: undefined,
233
+ key_id: undefined,
236
234
  });
237
235
  }
238
236
 
@@ -263,21 +261,36 @@ class CLMSApiTokensView extends Component {
263
261
  {this.props.intl.formatMessage(messages.ApiTokens)}
264
262
  </h1>
265
263
  <div>
266
- <h3>{this.props.intl.formatMessage(messages.title)}</h3>
264
+ <h2>{this.props.intl.formatMessage(messages.title)}</h2>
267
265
  <p>{this.props.intl.formatMessage(messages.description)}</p>
268
266
  {this.props.createdTokens?.map((item) => (
269
267
  <>
270
268
  <div>
271
269
  <p>{item.title}</p>
272
270
  <p>{item.key_id}</p>
273
- <CclButton
274
- mode={'filled'}
275
- onClick={() => {
276
- this.deleteToken(item.key_id);
277
- }}
271
+ <CclModal
272
+ onClick={() => this.onClose}
273
+ trigger={
274
+ <CclButton mode={'filled'}>
275
+ {this.props.intl.formatMessage(messages.deleteButton)}
276
+ </CclButton>
277
+ }
278
+ size="small"
278
279
  >
279
- {this.props.intl.formatMessage(messages.deleteButton)}
280
- </CclButton>
280
+ <h4>This token will be deleted forever</h4>
281
+ <p>
282
+ You will not be able to use this token again. Only
283
+ delete your tokens when you are absolutely sure of it
284
+ </p>
285
+ <CclButton
286
+ mode={'filled'}
287
+ onClick={() => {
288
+ this.deleteToken(item.key_id);
289
+ }}
290
+ >
291
+ {'I confirm that I want to delete this token'}
292
+ </CclButton>
293
+ </CclModal>
281
294
  </div>
282
295
  </>
283
296
  ))}
@@ -351,31 +364,40 @@ class CLMSApiTokensView extends Component {
351
364
  <>
352
365
  {(this.state.createdToken === true && (
353
366
  <div>
354
- <p>
367
+ <h3>
355
368
  {this.props.intl.formatMessage(
356
369
  messages.createdToken,
357
370
  )}
358
- </p>
371
+ </h3>
359
372
  <form className="ccl-form search-form">
360
373
  {this.props.newTokens?.map((item) => (
361
374
  <>
362
- {(item.public_key !== undefined && (
375
+ {(item?.private_key && (
363
376
  <>
364
- <input
365
- value={item.public_key}
377
+ <p>{'Download your service key.'}</p>
378
+ <p>
379
+ {
380
+ "This is the only time your private key will be displayed - it will not be stored on the server, and can't be recovered should you fail to save it."
381
+ }
382
+ </p>
383
+ <p>
384
+ {
385
+ 'You should copy & paste this key into a .json file, and store this file in a location accessible only to your service application. This key grants anyone in possession of it full access to this account. You should therefore make sure to protect it with the least file system permissions possible.'
386
+ }
387
+ </p>
388
+
389
+ <textarea
366
390
  disabled="disabled"
367
- type="text"
368
- className="ccl-text-input"
369
391
  id="created_token"
370
392
  name="createdToken"
371
- placeholder=""
372
- aria-label="Created token"
393
+ class="ccl-text-input"
394
+ value={JSON.stringify(item)}
373
395
  />
374
396
  <CclButton
375
397
  mode={'filled'}
376
398
  onClick={() => {
377
399
  navigator.clipboard.writeText(
378
- item.public_key,
400
+ JSON.stringify(item),
379
401
  );
380
402
  }}
381
403
  >
@@ -3,18 +3,20 @@
3
3
  * @module components/CLMSProfileView/CLMSProfileView
4
4
  */
5
5
 
6
+ import {
7
+ CLMSApiTokensView,
8
+ CLMSUserProfileView,
9
+ } from '@eeacms/volto-clms-theme/components/CLMSProfileView';
6
10
  import React, { Component } from 'react';
11
+ import { getUser, updateUser } from '@plone/volto/actions';
12
+
13
+ import CclTabs from '@eeacms/volto-clms-theme/components/CclTab/CclTabs';
7
14
  import PropTypes from 'prop-types';
8
- import { connect } from 'react-redux';
9
15
  import { compose } from 'redux';
10
- import jwtDecode from 'jwt-decode';
11
- import { getUser, updateUser } from '@plone/volto/actions';
16
+ import { connect } from 'react-redux';
12
17
  import { getBaseUrl } from '@plone/volto/helpers';
13
- import CclTabs from '@eeacms/volto-clms-theme/components/CclTab/CclTabs';
14
- import {
15
- CLMSUserProfileView,
16
- CLMSApiTokensView,
17
- } from '@eeacms/volto-clms-theme/components/CLMSProfileView';
18
+ import { getExtraBreadcrumbItems } from '../../actions';
19
+ import jwtDecode from 'jwt-decode';
18
20
 
19
21
  /**
20
22
  * CLMSProfileView class.
@@ -32,13 +34,18 @@ class CLMSProfileView extends Component {
32
34
  children: PropTypes.instanceOf(Array),
33
35
  user: PropTypes.shape({
34
36
  '@id': PropTypes.string,
35
- description: PropTypes.string,
37
+ are_you_registering_on_behalf_on_an_organisation_: PropTypes.bool,
38
+ country: PropTypes.string,
36
39
  email: PropTypes.string,
37
40
  fullname: PropTypes.string,
41
+ how_do_you_intend_to_use_the_products: PropTypes.arrayOf(
42
+ PropTypes.string,
43
+ ),
38
44
  id: PropTypes.string,
39
- location: PropTypes.string,
40
- nickname: PropTypes.string,
41
- portrait: PropTypes.string,
45
+ organisation_institutional_domain: PropTypes.arrayOf(PropTypes.string),
46
+ organisation_name: PropTypes.string,
47
+ organisation_url: PropTypes.string,
48
+ professional_thematic_domain: PropTypes.arrayOf(PropTypes.string),
42
49
  roles: PropTypes.array,
43
50
  username: PropTypes.string,
44
51
  return_url: PropTypes.string,
@@ -56,8 +63,14 @@ class CLMSProfileView extends Component {
56
63
  */
57
64
  render() {
58
65
  const loggedIn = !!this.props.userId;
66
+ this.props.getExtraBreadcrumbItems([
67
+ {
68
+ title: 'Profile',
69
+ pathname: this.props.location.pathname,
70
+ },
71
+ ]);
59
72
  return (
60
- <>
73
+ <div className="ccl-container ">
61
74
  {loggedIn && (
62
75
  <>
63
76
  <CclTabs>
@@ -70,7 +83,7 @@ class CLMSProfileView extends Component {
70
83
  </CclTabs>
71
84
  </>
72
85
  )}
73
- </>
86
+ </div>
74
87
  );
75
88
  }
76
89
  }
@@ -83,6 +96,6 @@ export default compose(
83
96
  ? jwtDecode(state.userSession.token).sub
84
97
  : '',
85
98
  }),
86
- { getUser, updateUser, getBaseUrl },
99
+ { getUser, updateUser, getBaseUrl, getExtraBreadcrumbItems },
87
100
  ),
88
101
  )(CLMSProfileView);
@@ -14,6 +14,7 @@ import { toast } from 'react-toastify';
14
14
  import { getUser, updateUser } from '@plone/volto/actions';
15
15
  import { getBaseUrl } from '@plone/volto/helpers';
16
16
  import { Container } from 'semantic-ui-react';
17
+ import { getUserSchema } from '../../actions';
17
18
 
18
19
  const messages = defineMessages({
19
20
  UserProfile: {
@@ -83,13 +84,18 @@ class CLMSUserProfileView extends Component {
83
84
  static propTypes = {
84
85
  user: PropTypes.shape({
85
86
  '@id': PropTypes.string,
86
- description: PropTypes.string,
87
+ are_you_registering_on_behalf_on_an_organisation_: PropTypes.bool,
88
+ country: PropTypes.string,
87
89
  email: PropTypes.string,
88
90
  fullname: PropTypes.string,
91
+ how_do_you_intend_to_use_the_products: PropTypes.arrayOf(
92
+ PropTypes.string,
93
+ ),
89
94
  id: PropTypes.string,
90
- location: PropTypes.string,
91
- nickname: PropTypes.string,
92
- portrait: PropTypes.string,
95
+ organisation_institutional_domain: PropTypes.arrayOf(PropTypes.string),
96
+ organisation_name: PropTypes.string,
97
+ organisation_url: PropTypes.string,
98
+ professional_thematic_domain: PropTypes.arrayOf(PropTypes.string),
93
99
  roles: PropTypes.array,
94
100
  username: PropTypes.string,
95
101
  return_url: PropTypes.string,
@@ -100,10 +106,12 @@ class CLMSUserProfileView extends Component {
100
106
  getUser: PropTypes.func.isRequired,
101
107
  updateUser: PropTypes.func.isRequired,
102
108
  getBaseUrl: PropTypes.func.isRequired,
109
+ getUserSchema: PropTypes.func.isRequired,
103
110
  };
104
111
 
105
112
  componentDidMount() {
106
113
  this.props.getUser(this.props.userId);
114
+ this.props.getUserSchema();
107
115
  }
108
116
 
109
117
  /**
@@ -140,66 +148,30 @@ class CLMSUserProfileView extends Component {
140
148
  <>
141
149
  {loggedIn && (
142
150
  <Container>
143
- <h1 className="page-title">
144
- {this.props.intl.formatMessage(messages.UserProfile)}
145
- </h1>
146
151
  <div>
147
- {this.props.loaded && (
148
- <Form
149
- formData={this.props.user}
150
- schema={{
151
- fieldsets: [
152
- {
153
- id: 'default',
154
- title: this.props.intl.formatMessage(messages.default),
155
- fields: ['fullname', 'email', 'portrait', 'location'],
156
- },
157
- ],
158
- properties: {
159
- fullname: {
160
- description: this.props.intl.formatMessage(
161
- messages.fullnameDescription,
162
- ),
163
- title: this.props.intl.formatMessage(
164
- messages.fullnameTitle,
165
- ),
166
- type: 'string',
167
- },
168
- email: {
169
- description: this.props.intl.formatMessage(
170
- messages.emailDescription,
171
- ),
172
- title: this.props.intl.formatMessage(
173
- messages.emailTitle,
174
- ),
175
- type: 'string',
176
- },
177
- portrait: {
178
- description: this.props.intl.formatMessage(
179
- messages.portraitDescription,
180
- ),
181
- title: this.props.intl.formatMessage(
182
- messages.portraitTitle,
183
- ),
184
- type: 'object',
185
- },
186
- location: {
187
- description: this.props.intl.formatMessage(
188
- messages.locationDescription,
189
- ),
190
- title: this.props.intl.formatMessage(
191
- messages.locationTitle,
192
- ),
193
- type: 'string',
194
- },
195
- },
196
- required: ['email'],
197
- }}
198
- onSubmit={this.onSubmit}
199
- onCancel={this.onCancel}
200
- loading={this.props.loading}
201
- />
202
- )}
152
+ <h1 className="page-title">
153
+ {this.props.intl.formatMessage(messages.UserProfile)}
154
+ </h1>
155
+ <p>
156
+ Use this form to update your profile details. Be aware that if
157
+ you change your fullname and e-mail address they will be
158
+ rewriten when you log in again next time. This is because we are
159
+ using EU Login to enter this site. <br />
160
+ If you want to change your fullname and e-mail address, please
161
+ do so in your{' '}
162
+ <a href="https://ecas.ec.europa.eu/cas/">EU Login account</a>.
163
+ </p>
164
+ <div>
165
+ {this.props?.userschema?.loaded && (
166
+ <Form
167
+ formData={this.props.user}
168
+ schema={this.props.userschema.userschema}
169
+ onSubmit={this.onSubmit.bind(this)}
170
+ onCancel={this.onCancel}
171
+ loading={this.props.userschema.loading}
172
+ />
173
+ )}
174
+ </div>
203
175
  </div>
204
176
  </Container>
205
177
  )}
@@ -218,7 +190,8 @@ export default compose(
218
190
  : '',
219
191
  loaded: state.users.get.loaded,
220
192
  loading: state.users.update.loading,
193
+ userschema: state.userschema,
221
194
  }),
222
- { getUser, updateUser, getBaseUrl },
195
+ { getUser, updateUser, getBaseUrl, getUserSchema },
223
196
  ),
224
197
  )(CLMSUserProfileView);
@@ -2,7 +2,6 @@ import React from 'react';
2
2
  import { Link } from 'react-router-dom';
3
3
  import './cards.less';
4
4
  import PropTypes from 'prop-types';
5
- import CclButton from '@eeacms/volto-clms-theme/components/CclButton/CclButton';
6
5
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
7
6
  import * as mime from 'react-native-mime-types';
8
7
 
@@ -56,14 +55,9 @@ function CclCard(props) {
56
55
  </div>
57
56
  <div className="card-text">
58
57
  <div className="card-title">
59
- <a href={card?.file?.download || '#'}>
60
- {card?.title || 'Card default title'}
61
- </a>
58
+ <a href={url}>{card?.title || 'Card default title'}</a>
62
59
  </div>
63
60
  <div className="card-description">{card?.description}</div>
64
- <div className="card-button">
65
- <CclButton url={url}>Access to product</CclButton>
66
- </div>
67
61
  {children}
68
62
  </div>
69
63
  </>
@@ -99,7 +99,7 @@
99
99
  background-color: #a0b1280f;
100
100
  }
101
101
 
102
- .card-block .card-image {
102
+ .card-block .card-block-image {
103
103
  height: 12rem;
104
104
  }
105
105
 
@@ -0,0 +1,83 @@
1
+ import React, { useEffect } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import CclModal from '@eeacms/volto-clms-theme/components/CclModal/CclModal';
4
+ import { useDispatch, useSelector } from 'react-redux';
5
+ import { getRegistry } from '@eeacms/volto-clms-theme/actions';
6
+ import { FormattedMessage } from 'react-intl';
7
+ import config from '@plone/volto/registry';
8
+ import { toPublicURL } from '@plone/volto/helpers/Url/Url';
9
+ import './ccl-login-modal.css';
10
+ /**
11
+ * Login Modal component doc.
12
+ * @function CclLoginModal
13
+ * @example <CclLoginModal />
14
+ *
15
+ */
16
+ function CclLoginModal() {
17
+ const dispatch = useDispatch();
18
+ const registryRecords = useSelector((state) => state.registry.records);
19
+ const [loginUrl, setLoginUrl] = React.useState('');
20
+ const registry_key = config.settings?.registry?.login_url || null;
21
+
22
+ useEffect(() => {
23
+ if (registryRecords && registry_key in registryRecords) {
24
+ setLoginUrl(registryRecords[registry_key]);
25
+ }
26
+ }, [registryRecords, registry_key]);
27
+
28
+ function modalStatus(status) {
29
+ if (status === true) {
30
+ dispatch(getRegistry(registry_key));
31
+ }
32
+ }
33
+
34
+ return (
35
+ <CclModal
36
+ trigger={
37
+ <div className="header-login-link">
38
+ <FormattedMessage
39
+ id="loginRegister"
40
+ defaultMessage="Register/Login"
41
+ />
42
+ </div>
43
+ }
44
+ size="tiny"
45
+ modalStatus={modalStatus}
46
+ >
47
+ <div className="modal-login-title">Registration / Login</div>
48
+ <div className="modal-login-text">
49
+ <p>
50
+ This site uses EU Login to handle user registration and login. You can
51
+ read more about this service in the{' '}
52
+ <a href="https://ecas.ec.europa.eu/cas/about.html">
53
+ EU Login site help
54
+ </a>
55
+ .
56
+ </p>
57
+ <p>
58
+ {' '}
59
+ When you clik on the following link, you will be sent to EU Login and
60
+ after a successful login there you will be redirected back to this
61
+ site.
62
+ </p>
63
+ <p>
64
+ If you have any issues or questions, please contact us using the
65
+ <a href="/en/contact-service-helpdesk"> helpdesk</a>.
66
+ </p>
67
+ </div>
68
+ <a
69
+ href={toPublicURL(loginUrl) || '#'}
70
+ className="ccl-button ccl-button-green"
71
+ >
72
+ Login using EU Login
73
+ </a>
74
+ </CclModal>
75
+ );
76
+ }
77
+
78
+ CclLoginModal.propTypes = {
79
+ title: PropTypes.string.isRequired,
80
+ children: PropTypes.node.isRequired,
81
+ marginBottom: PropTypes.bool,
82
+ };
83
+ export default CclLoginModal;
@@ -0,0 +1,3 @@
1
+ .header-login-link {
2
+ color: white;
3
+ }
@@ -3,13 +3,28 @@ import { Modal } from 'semantic-ui-react';
3
3
  import './modal.less';
4
4
 
5
5
  function CclModal(props) {
6
+ let {
7
+ trigger,
8
+ children,
9
+ size = 'fullscreen',
10
+ modalStatus = () => {},
11
+ } = props;
6
12
  const [open, setOpen] = React.useState(false);
7
- let { trigger, children, size } = props;
13
+
14
+ function openModal() {
15
+ setOpen(true);
16
+ modalStatus(true);
17
+ }
18
+
19
+ function closeModal() {
20
+ setOpen(false);
21
+ modalStatus(false);
22
+ }
8
23
 
9
24
  return (
10
25
  <Modal
11
- onClose={() => setOpen(false)}
12
- onOpen={() => setOpen(true)}
26
+ onClose={() => closeModal()}
27
+ onOpen={() => openModal()}
13
28
  open={open}
14
29
  trigger={trigger}
15
30
  className={'modal-clms'}
@@ -21,8 +36,8 @@ function CclModal(props) {
21
36
  <span
22
37
  className="ccl-icon-close"
23
38
  aria-label="Close"
24
- onClick={() => setOpen(false)}
25
- onKeyDown={() => setOpen(false)}
39
+ onClick={() => closeModal()}
40
+ onKeyDown={() => closeModal()}
26
41
  tabIndex="0"
27
42
  role="button"
28
43
  ></span>
@@ -0,0 +1,91 @@
1
+ import React from 'react';
2
+
3
+ import ObjectListWidget from '@plone/volto/components/manage/Widgets/ObjectListWidget';
4
+
5
+ const ItemSchema = {
6
+ title: 'Contact',
7
+ properties: {
8
+ organisationName: {
9
+ title: 'Organisation Name',
10
+ description: 'Enter the Organisation Name of the contact.',
11
+ type: 'string',
12
+ },
13
+ deliveryPoint: {
14
+ title: 'Delivery Point',
15
+ description: 'Enter the Delivery Point of the contact.',
16
+ type: 'string',
17
+ },
18
+ city: {
19
+ title: 'City',
20
+ description: 'Enter the City of the contact.',
21
+ type: 'string',
22
+ },
23
+ administrativeArea: {
24
+ title: 'Administrative Area',
25
+ description: 'Enter the Administrative Area of the contact.',
26
+ type: 'string',
27
+ },
28
+ postalCode: {
29
+ title: 'Postal Code',
30
+ description: 'Enter the Postal Code of the contact.',
31
+ type: 'string',
32
+ },
33
+ country: {
34
+ title: 'Country',
35
+ description: 'Enter the Country of the contact.',
36
+ type: 'string',
37
+ },
38
+ electronicMailAddress: {
39
+ title: 'Electronic Mail Address',
40
+ description: 'Enter the Electronic Mail Address of the contact.',
41
+ type: 'string',
42
+ },
43
+ url: {
44
+ title: 'URL',
45
+ description: 'Enter the URL of the contact.',
46
+ type: 'string',
47
+ },
48
+ urlTitle: {
49
+ title: 'URL Title',
50
+ description: 'Enter the URL Title of the contact.',
51
+ type: 'string',
52
+ },
53
+ roleCode: {
54
+ title: 'Role Code',
55
+ description: 'Enter the Role Code of the contact.',
56
+ type: 'string',
57
+ },
58
+ },
59
+ fieldsets: [
60
+ {
61
+ id: 'default',
62
+ title: 'Contact',
63
+ fields: [
64
+ 'organisationName',
65
+ 'deliveryPoint',
66
+ 'city',
67
+ 'administrativeArea',
68
+ 'postalCode',
69
+ 'country',
70
+ 'electronicMailAddress',
71
+ 'url',
72
+ 'urlTitle',
73
+ 'roleCode',
74
+ ],
75
+ },
76
+ ],
77
+ required: [],
78
+ };
79
+
80
+ const ContactWidget = (props) => {
81
+ return (
82
+ <ObjectListWidget
83
+ schema={ItemSchema}
84
+ {...props}
85
+ value={props.value?.items || props.default?.items || []}
86
+ onChange={(id, value) => props.onChange(id, { items: value })}
87
+ />
88
+ );
89
+ };
90
+
91
+ export default ContactWidget;