@eeacms/volto-cca-policy 0.1.11 → 0.1.13

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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,20 @@ 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
+ ### [0.1.13](https://github.com/eea/volto-cca-policy/compare/0.1.12...0.1.13) - 23 March 2023
8
+
9
+ #### :hammer_and_wrench: Others
10
+
11
+ - Clear console.logs [kreafox - [`7a6098f`](https://github.com/eea/volto-cca-policy/commit/7a6098f63de6eba9eb2d4122893f38893900f945)]
12
+ - Add AddLinkForm override [kreafox - [`83bd2f4`](https://github.com/eea/volto-cca-policy/commit/83bd2f482bfc5bfa6a7795849778dc34e4d07fa1)]
13
+ - Enable video block [kreafox - [`69f4c1d`](https://github.com/eea/volto-cca-policy/commit/69f4c1d8bb6bd08a29a6ab50d1e5532295c8d2f3)]
14
+ - Update footer links [kreafox - [`9d32e61`](https://github.com/eea/volto-cca-policy/commit/9d32e6132892e310d6215e8d0e87b4e6052de6d3)]
15
+ ### [0.1.12](https://github.com/eea/volto-cca-policy/compare/0.1.11...0.1.12) - 21 March 2023
16
+
17
+ #### :hammer_and_wrench: Others
18
+
19
+ - Add readme [Tiberiu Ichim - [`d674ea0`](https://github.com/eea/volto-cca-policy/commit/d674ea01c314b20f5891a593f8e44d1fcadde63d)]
20
+ - Add customization [Tiberiu Ichim - [`2d3b3b8`](https://github.com/eea/volto-cca-policy/commit/2d3b3b821a31b91caffccb280c376ff2285965e2)]
7
21
  ### [0.1.11](https://github.com/eea/volto-cca-policy/compare/0.1.10...0.1.11) - 21 March 2023
8
22
 
9
23
  #### :hammer_and_wrench: Others
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-cca-policy",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "@eeacms/volto-cca-policy: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -0,0 +1,321 @@
1
+ /**
2
+ * Add link form.
3
+ * @module components/manage/AnchorPlugin/components/LinkButton/AddLinkForm
4
+ */
5
+
6
+ import React, { Component } from 'react';
7
+ import PropTypes from 'prop-types';
8
+ import { compose } from 'redux';
9
+
10
+ // import unionClassNames from 'union-class-names';
11
+ import cx from 'classnames';
12
+ import {
13
+ addAppURL,
14
+ isInternalURL,
15
+ flattenToAppURL,
16
+ URLUtils,
17
+ } from '@plone/volto/helpers';
18
+
19
+ import { doesNodeContainClick } from 'semantic-ui-react/dist/commonjs/lib';
20
+ import { Input, Form, Button } from 'semantic-ui-react';
21
+ import { defineMessages, injectIntl } from 'react-intl';
22
+
23
+ import clearSVG from '@plone/volto/icons/clear.svg';
24
+ import navTreeSVG from '@plone/volto/icons/nav.svg';
25
+ import aheadSVG from '@plone/volto/icons/ahead.svg';
26
+
27
+ import withObjectBrowser from '@plone/volto/components/manage/Sidebar/ObjectBrowser';
28
+ import { withRouter } from 'react-router';
29
+
30
+ import { Icon } from '@plone/volto/components';
31
+
32
+ const messages = defineMessages({
33
+ placeholder: {
34
+ id: 'Enter URL or select an item',
35
+ defaultMessage: 'Enter URL or select an item',
36
+ },
37
+ });
38
+
39
+ /**
40
+ * Add link form class.
41
+ * @class AddLinkForm
42
+ * @extends Component
43
+ */
44
+ class AddLinkForm extends Component {
45
+ static propTypes = {
46
+ onChangeValue: PropTypes.func.isRequired,
47
+ onClear: PropTypes.func.isRequired,
48
+ onOverrideContent: PropTypes.func.isRequired,
49
+ theme: PropTypes.objectOf(PropTypes.any).isRequired,
50
+ openObjectBrowser: PropTypes.func.isRequired,
51
+ };
52
+
53
+ static defaultProps = {
54
+ placeholder: 'Enter URL or select an item',
55
+ };
56
+
57
+ /**
58
+ * Constructor
59
+ * @method constructor
60
+ * @param {Object} props Component properties
61
+ * @constructs AddLinkForm
62
+ */
63
+ constructor(props) {
64
+ super(props);
65
+
66
+ this.state = {
67
+ value: isInternalURL(props.data.url)
68
+ ? flattenToAppURL(props.data.url)
69
+ : props.data.url || '',
70
+ isInvalid: false,
71
+ };
72
+ this.onRef = this.onRef.bind(this);
73
+ this.onChange = this.onChange.bind(this);
74
+ this.onKeyDown = this.onKeyDown.bind(this);
75
+ this.onSubmit = this.onSubmit.bind(this);
76
+ }
77
+
78
+ /**
79
+ * Component did mount
80
+ * @method componentDidMount
81
+ * @returns {undefined}
82
+ */
83
+ componentDidMount() {
84
+ setTimeout(() => this.input.focus(), 50);
85
+ document.addEventListener('mousedown', this.handleClickOutside, false);
86
+ }
87
+
88
+ componentWillUnmount() {
89
+ document.removeEventListener('mousedown', this.handleClickOutside, false);
90
+ }
91
+
92
+ handleClickOutside = (e) => {
93
+ if (
94
+ this.linkFormContainer.current &&
95
+ doesNodeContainClick(this.linkFormContainer.current, e)
96
+ )
97
+ return;
98
+ if (this.linkFormContainer.current && this.props.isObjectBrowserOpen)
99
+ return;
100
+ this.onClose();
101
+ };
102
+
103
+ /**
104
+ * Ref handler
105
+ * @method onRef
106
+ * @param {Object} node Node
107
+ * @returns {undefined}
108
+ */
109
+ onRef(node) {
110
+ this.input = node;
111
+ }
112
+
113
+ linkFormContainer = React.createRef();
114
+
115
+ /**
116
+ * Change handler
117
+ * @method onChange
118
+ * @param {Object} value Value
119
+ * @returns {undefined}
120
+ */
121
+ onChange(value, clear, callback) {
122
+ let nextState = { value };
123
+ // debugger;
124
+ if (!clear) {
125
+ if (
126
+ this.state.isInvalid &&
127
+ URLUtils.isUrl(URLUtils.normalizeUrl(value))
128
+ ) {
129
+ nextState.isInvalid = false;
130
+ }
131
+
132
+ if (isInternalURL(value)) {
133
+ nextState = { value: flattenToAppURL(value) };
134
+ }
135
+ }
136
+ this.setState(nextState, callback);
137
+
138
+ if (clear) this.props.onClear();
139
+ }
140
+
141
+ /**
142
+ * Select item handler
143
+ * @method onSelectItem
144
+ * @param {string} e event
145
+ * @param {string} url Url
146
+ * @returns {undefined}
147
+ */
148
+ onSelectItem = (e, url) => {
149
+ e.preventDefault();
150
+ this.setState({
151
+ value: url,
152
+ isInvalid: false,
153
+ });
154
+ this.props.onChangeValue(addAppURL(url));
155
+ };
156
+
157
+ /**
158
+ * Clear handler
159
+ * @method clear
160
+ * @param {Object} value Value
161
+ * @returns {undefined}
162
+ */
163
+ clear() {
164
+ const nextState = { value: '' };
165
+ this.setState(nextState);
166
+
167
+ this.props.onClear();
168
+ }
169
+
170
+ /**
171
+ * Close handler
172
+ * @method onClose
173
+ * @returns {undefined}
174
+ */
175
+ onClose = () => this.props.onOverrideContent(undefined);
176
+
177
+ /**
178
+ * Keydown handler
179
+ * @method onKeyDown
180
+ * @param {Object} e Event object
181
+ * @returns {undefined}
182
+ */
183
+ onKeyDown(e) {
184
+ if (e.key === 'Enter') {
185
+ e.preventDefault();
186
+ e.stopPropagation();
187
+ this.onSubmit();
188
+ } else if (e.key === 'Escape') {
189
+ e.preventDefault();
190
+ this.onClose();
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Submit handler
196
+ * @method onSubmit
197
+ * @returns {undefined}
198
+ */
199
+ onSubmit() {
200
+ let { value: url } = this.state;
201
+
202
+ const checkedURL = URLUtils.checkAndNormalizeUrl(url);
203
+ url = checkedURL.url;
204
+ if (!checkedURL.isValid) {
205
+ this.setState({ isInvalid: true });
206
+ return;
207
+ }
208
+
209
+ const editorStateUrl = isInternalURL(url) ? addAppURL(url) : url;
210
+
211
+ this.props.onChangeValue(editorStateUrl);
212
+ this.onClose();
213
+ }
214
+
215
+ /**
216
+ * Render method.
217
+ * @method render
218
+ * @returns {string} Markup for the component.
219
+ */
220
+ render() {
221
+ const { value, isInvalid } = this.state;
222
+ const className = isInvalid
223
+ ? cx(
224
+ 'ui input editor-link',
225
+ 'input-anchorlink-theme',
226
+ 'input-anchorlink-theme-Invalid',
227
+ )
228
+ : cx('ui input editor-link', 'input-anchorlink-theme');
229
+
230
+ return (
231
+ <div className="link-form-container" ref={this.linkFormContainer}>
232
+ <div
233
+ style={{ marginLeft: '5px', display: 'flex', alignItems: 'center' }}
234
+ >
235
+ <svg
236
+ xmlns="http://www.w3.org/2000/svg"
237
+ width="24"
238
+ height="24"
239
+ viewBox="0 0 36 36"
240
+ fill="#B8B2C8"
241
+ >
242
+ <g fillRule="evenodd">
243
+ <path d="M27.1318,7.333 C24.4028,4.604 19.9618,4.604 17.2328,7.333 L12.9898,11.576 C11.8428,12.723 11.1288,14.248 10.9778,15.871 C10.8228,17.541 11.2708,19.211 12.2378,20.576 C12.4818,20.919 12.7278,21.213 12.9888,21.475 C13.7848,22.271 14.7778,22.868 15.8608,23.202 C16.5498,23.415 17.2548,23.519 17.9518,23.518 C19.7808,23.518 21.5598,22.804 22.8888,21.475 L23.9498,20.414 L22.5358,19 L21.4748,20.061 C20.1648,21.371 18.2388,21.842 16.4498,21.291 C15.6668,21.049 14.9778,20.635 14.4038,20.061 C14.2218,19.879 14.0478,19.668 13.8698,19.418 C13.1778,18.443 12.8588,17.249 12.9688,16.056 C13.0768,14.896 13.5868,13.808 14.4038,12.99 L18.6468,8.747 C20.5958,6.798 23.7688,6.798 25.7178,8.747 C26.6568,9.687 27.1748,10.942 27.1748,12.283 C27.1748,13.623 26.6568,14.878 25.7178,15.818 L27.1318,17.232 C28.4488,15.915 29.1748,14.157 29.1748,12.283 C29.1748,10.408 28.4488,8.65 27.1318,7.333" />
244
+ <path d="M25.0107,16.5254 C24.2147,15.7294 23.2217,15.1324 22.1387,14.7984 C19.6417,14.0284 16.9477,14.6894 15.1107,16.5254 L14.0507,17.5864 L15.4647,19.0004 L16.5247,17.9394 C17.8357,16.6294 19.7587,16.1554 21.5497,16.7094 C22.3337,16.9514 23.0217,17.3644 23.5957,17.9394 C23.7777,18.1214 23.9527,18.3314 24.1307,18.5824 C24.8217,19.5564 25.1417,20.7514 25.0317,21.9444 C24.9237,23.1034 24.4137,24.1924 23.5957,25.0104 L19.3537,29.2534 C17.4047,31.2024 14.2317,31.2024 12.2817,29.2534 C11.3427,28.3134 10.8247,27.0574 10.8247,25.7174 C10.8247,24.3774 11.3427,23.1214 12.2817,22.1824 L10.8677,20.7684 C9.5507,22.0854 8.8247,23.8424 8.8247,25.7174 C8.8247,27.5924 9.5507,29.3504 10.8677,30.6674 C12.2327,32.0314 14.0257,32.7134 15.8177,32.7134 C17.6107,32.7134 19.4027,32.0314 20.7677,30.6674 L25.0107,26.4244 C26.1567,25.2774 26.8717,23.7524 27.0227,22.1294 C27.1777,20.4594 26.7297,18.7894 25.7617,17.4244 C25.5177,17.0814 25.2717,16.7874 25.0107,16.5254" />
245
+ </g>
246
+ </svg>
247
+ <Form.Field inline>
248
+ <div className="wrapper">
249
+ <Input
250
+ className={className}
251
+ id={`field-link`}
252
+ name="link"
253
+ value={value || ''}
254
+ onChange={({ target }) => this.onChange(target.value)}
255
+ placeholder={this.props.intl.formatMessage(
256
+ messages.placeholder,
257
+ )}
258
+ onKeyDown={this.onKeyDown}
259
+ ref={this.onRef}
260
+ />
261
+ {value.length > 0 ? (
262
+ <Button.Group>
263
+ <Button
264
+ basic
265
+ className="cancel"
266
+ onClick={(e) => {
267
+ e.preventDefault();
268
+ e.stopPropagation();
269
+ this.clear();
270
+ }}
271
+ >
272
+ <Icon name={clearSVG} size="24px" />
273
+ </Button>
274
+ </Button.Group>
275
+ ) : (
276
+ <Button.Group>
277
+ <Button
278
+ basic
279
+ icon
280
+ onClick={(e) => {
281
+ e.preventDefault();
282
+ e.stopPropagation();
283
+ this.props.openObjectBrowser({
284
+ mode: 'link',
285
+ overlay: true,
286
+ onSelectItem: (url) => {
287
+ // console.log('incoming onchange', url);
288
+ this.onChange(url, null, this.onSubmit);
289
+ // console.log('now state is', this.state);
290
+ // this.onSubmit();
291
+ },
292
+ });
293
+ }}
294
+ >
295
+ <Icon name={navTreeSVG} size="24px" />
296
+ </Button>
297
+ </Button.Group>
298
+ )}
299
+ <Button.Group>
300
+ <Button
301
+ basic
302
+ primary
303
+ disabled={!value.length > 0}
304
+ onClick={(e) => {
305
+ e.preventDefault();
306
+ e.stopPropagation();
307
+ this.onSubmit();
308
+ }}
309
+ >
310
+ <Icon name={aheadSVG} size="24px" />
311
+ </Button>
312
+ </Button.Group>
313
+ </div>
314
+ </Form.Field>
315
+ </div>
316
+ </div>
317
+ );
318
+ }
319
+ }
320
+
321
+ export default compose(injectIntl, withRouter, withObjectBrowser)(AddLinkForm);
@@ -0,0 +1,3 @@
1
+ Copy of https://raw.githubusercontent.com/plone/volto/9c1af8bdb5d6abd78adbd08d6b86499d133471cb/src/helpers/Url/Url.js
2
+
3
+ fixes mail regex crash
@@ -0,0 +1,320 @@
1
+ /**
2
+ * Url helper.
3
+ * @module helpers/Url
4
+ */
5
+
6
+ import { last, memoize } from 'lodash';
7
+ import {
8
+ urlRegex,
9
+ telRegex,
10
+ mailRegex,
11
+ } from '@plone/volto/helpers/Url/urlRegex';
12
+ import prependHttp from 'prepend-http';
13
+ import config from '@plone/volto/registry';
14
+
15
+ /**
16
+ * Get base url.
17
+ * @function getBaseUrl
18
+ * @param {string} url Url to be parsed.
19
+ * @return {string} Base url of content object.
20
+ */
21
+ export const getBaseUrl = memoize((url) => {
22
+ const { settings } = config;
23
+ if (url === undefined) return;
24
+
25
+ // We allow settings.nonContentRoutes to have strings (that are supposed to match
26
+ // ending strings of pathnames, so we are converting them to RegEx to match also
27
+ const normalized_nonContentRoutes = settings.nonContentRoutes.map((item) => {
28
+ if (item.test) {
29
+ return item;
30
+ } else {
31
+ return new RegExp(item + '$');
32
+ }
33
+ });
34
+
35
+ let adjustedUrl = normalized_nonContentRoutes.reduce(
36
+ (acc, item) => acc.replace(item, ''),
37
+ url,
38
+ );
39
+
40
+ adjustedUrl = adjustedUrl || '/';
41
+ return adjustedUrl === '/' ? '' : adjustedUrl;
42
+ });
43
+
44
+ /**
45
+ * Get parent url.
46
+ * @function getParentUrl
47
+ * @param {string} url Url to be parsed.
48
+ * @return {string} Parent url of content object.
49
+ */
50
+ export const getParentUrl = memoize((url) => {
51
+ return url.substring(0, url.lastIndexOf('/'));
52
+ });
53
+
54
+ /**
55
+ * Get id from url.
56
+ * @function getId
57
+ * @param {string} url Url to be parsed.
58
+ * @return {string} Id of content object.
59
+ */
60
+ export function getId(url) {
61
+ return last(url.replace(/\?.*$/, '').split('/'));
62
+ }
63
+
64
+ /**
65
+ * Get view of an url.
66
+ * @function getView
67
+ * @param {string} url Url to be parsed.
68
+ * @return {string} View of content object.
69
+ */
70
+ export function getView(url) {
71
+ const view = last(url.replace(/\?.*$/, '').split('/'));
72
+ if (
73
+ [
74
+ 'add',
75
+ 'layout',
76
+ 'contents',
77
+ 'edit',
78
+ 'delete',
79
+ 'diff',
80
+ 'history',
81
+ 'sharing',
82
+ 'controlpanel',
83
+ ].indexOf(view) === -1
84
+ ) {
85
+ return 'view';
86
+ }
87
+ return view === 'layout' ? 'edit' : view;
88
+ }
89
+
90
+ /**
91
+ * Flatten to app server URL - Given a URL if it starts with the API server URL
92
+ * this method flattens it (removes) the server part
93
+ * TODO: Update it when implementing non-root based app location (on a
94
+ * directory other than /, eg. /myapp)
95
+ * @method flattenToAppURL
96
+ * @param {string} url URL of the object
97
+ * @returns {string} Flattened URL to the app server
98
+ */
99
+ export function flattenToAppURL(url) {
100
+ const { settings } = config;
101
+ return (
102
+ url &&
103
+ url
104
+ .replace(settings.internalApiPath, '')
105
+ .replace(settings.apiPath, '')
106
+ .replace(settings.publicURL, '')
107
+ );
108
+ }
109
+ /**
110
+ * Given a URL it remove the querystring from the URL.
111
+ * @method stripQuerystring
112
+ * @param {string} url URL of the object
113
+ * @returns {string} URL without querystring
114
+ */
115
+ export function stripQuerystring(url) {
116
+ return url.replace(/\?.*$/, '');
117
+ }
118
+
119
+ /**
120
+ * Given a URL if it starts with the API server URL
121
+ * this method removes the /api or the /Plone part.
122
+ * @method toPublicURL
123
+ * @param {string} url URL of the object
124
+ * @returns {string} public URL
125
+ */
126
+ export function toPublicURL(url) {
127
+ const { settings } = config;
128
+ return settings.publicURL.concat(flattenToAppURL(url));
129
+ }
130
+
131
+ /**
132
+ * Returns true if the current view is a cms ui view
133
+ * @method isCmsUi
134
+ * @param {string} currentPathname pathname of the current view
135
+ * @returns {boolean} true if the current view is a cms ui view
136
+ */
137
+ export const isCmsUi = memoize((currentPathname) => {
138
+ const { settings } = config;
139
+ const fullPath = currentPathname.replace(/\?.*$/, '');
140
+ // WARNING:
141
+ // not working properly for paths like /editors or similar
142
+ // because the regexp test does not take that into account
143
+ // https://github.com/plone/volto/issues/870
144
+ return settings.nonContentRoutes.reduce(
145
+ (acc, route) => acc || new RegExp(route).test(`/${fullPath}`),
146
+ false,
147
+ );
148
+ });
149
+
150
+ /**
151
+ * Flatten to app server HTML - Given a text if it contains some urls that starts
152
+ * with the API server URL this method flattens it (removes) the server part.
153
+ * TODO: Update it when implementing non-root based app location (on a
154
+ * directory other than /, eg. /myapp)
155
+ * @method flattenHTMLToAppURL
156
+ * @param {string} html Some html snippet
157
+ * @returns {string} Same HTML with Flattened URLs to the app server
158
+ */
159
+ export function flattenHTMLToAppURL(html) {
160
+ const { settings } = config;
161
+ return settings.internalApiPath
162
+ ? html
163
+ .replace(new RegExp(settings.internalApiPath, 'g'), '')
164
+ .replace(new RegExp(settings.apiPath, 'g'), '')
165
+ : html.replace(new RegExp(settings.apiPath, 'g'), '');
166
+ }
167
+
168
+ /**
169
+ * Add the app url
170
+ * @method addAppURL
171
+ * @param {string} url URL of the object
172
+ * @returns {string} New URL with app
173
+ */
174
+ export function addAppURL(url) {
175
+ const { settings } = config;
176
+ return url.indexOf(settings.apiPath) === 0
177
+ ? url
178
+ : `${settings.apiPath}${url}`;
179
+ }
180
+
181
+ /**
182
+ * Given a URL expands it to the backend URL
183
+ * Useful when you have to actually call the backend from the
184
+ * frontend code (eg. ICS calendar download)
185
+ * It is seamless mode aware
186
+ * @method expandToBackendURL
187
+ * @param {string} url URL or path of the object
188
+ * @returns {string} New URL with the backend URL
189
+ */
190
+ export function expandToBackendURL(path) {
191
+ const { settings } = config;
192
+ const APISUFIX = settings.legacyTraverse ? '' : '/++api++';
193
+ let adjustedPath;
194
+ if (path.startsWith('http://') || path.startsWith('https://')) {
195
+ // flattenToAppURL first if we get a full URL
196
+ adjustedPath = flattenToAppURL(path);
197
+ } else {
198
+ // Next adds a / in front if not a full URL to make sure it's a valid relative path
199
+ adjustedPath = path[0] !== '/' ? `/${path}` : path;
200
+ }
201
+
202
+ let apiPath = '';
203
+ if (settings.internalApiPath && __SERVER__) {
204
+ apiPath = settings.internalApiPath;
205
+ } else if (settings.apiPath) {
206
+ apiPath = settings.apiPath;
207
+ }
208
+
209
+ return `${apiPath}${APISUFIX}${adjustedPath}`;
210
+ }
211
+
212
+ /**
213
+ * Check if internal url
214
+ * @method isInternalURL
215
+ * @param {string} url URL of the object
216
+ * @returns {boolean} True if internal url
217
+ */
218
+ export function isInternalURL(url) {
219
+ const { settings } = config;
220
+ return (
221
+ url &&
222
+ (url.indexOf(settings.publicURL) !== -1 ||
223
+ (settings.internalApiPath &&
224
+ url.indexOf(settings.internalApiPath) !== -1) ||
225
+ url.indexOf(settings.apiPath) !== -1 ||
226
+ url.charAt(0) === '/' ||
227
+ url.charAt(0) === '.' ||
228
+ url.startsWith('#'))
229
+ );
230
+ }
231
+
232
+ /**
233
+ * Check if it's a valid url
234
+ * @method isUrl
235
+ * @param {string} url URL of the object
236
+ * @returns {boolean} True if is a valid url
237
+ */
238
+ export function isUrl(url) {
239
+ return urlRegex().test(url);
240
+ }
241
+
242
+ /**
243
+ * Normalize URL, adds protocol (if required eg. user has not entered the protocol)
244
+ * @method normalizeUrl
245
+ * @param {string} url URL of the object
246
+ * @returns {boolean} URL with the protocol
247
+ */
248
+ export function normalizeUrl(url) {
249
+ return prependHttp(url);
250
+ }
251
+
252
+ /**
253
+ * Removes protocol from URL (for display)
254
+ * @method removeProtocol
255
+ * @param {string} url URL of the object
256
+ * @returns {string} URL without the protocol part
257
+ */
258
+ export function removeProtocol(url) {
259
+ return url.replace('https://', '').replace('http://', '');
260
+ }
261
+
262
+ export function isMail(text) {
263
+ return mailRegex().test(text);
264
+ }
265
+
266
+ export function isTelephone(text) {
267
+ return telRegex().test(text);
268
+ }
269
+
270
+ export function normaliseMail(email) {
271
+ if (email?.toLowerCase()?.startsWith('mailto:')) {
272
+ return email;
273
+ }
274
+ return `mailto:${email}`;
275
+ }
276
+
277
+ export function normalizeTelephone(tel) {
278
+ if (tel?.toLowerCase()?.startsWith('tel:')) {
279
+ return tel;
280
+ }
281
+ return `tel:${tel}`;
282
+ }
283
+
284
+ export function checkAndNormalizeUrl(url) {
285
+ let res = {
286
+ isMail: false,
287
+ isTelephone: false,
288
+ url: url,
289
+ isValid: true,
290
+ };
291
+ if (URLUtils.isMail(URLUtils.normaliseMail(url))) {
292
+ //Mail
293
+ res.isMail = true;
294
+ res.url = URLUtils.normaliseMail(url);
295
+ } else if (URLUtils.isTelephone(url)) {
296
+ //Phone
297
+ res.isTelephone = true;
298
+ res.url = URLUtils.normalizeTelephone(url);
299
+ } else {
300
+ //url
301
+ if (res.url && !res.url.startsWith('/') && !res.url.startsWith('#')) {
302
+ res.url = URLUtils.normalizeUrl(url);
303
+ if (!URLUtils.isUrl(res.url)) {
304
+ res.isValid = false;
305
+ }
306
+ }
307
+ if (res.url === undefined || res.url === null) res.isValid = false;
308
+ }
309
+ return res;
310
+ }
311
+
312
+ export const URLUtils = {
313
+ normalizeTelephone,
314
+ normaliseMail,
315
+ normalizeUrl,
316
+ isTelephone,
317
+ isMail,
318
+ isUrl,
319
+ checkAndNormalizeUrl,
320
+ };
package/src/index.js CHANGED
@@ -86,13 +86,13 @@ const applyConfig = (config) => {
86
86
  {
87
87
  icon: 'comment outline',
88
88
  text: 'About us',
89
- link: '/en/mission/about-us',
89
+ link: '/en/mission/about',
90
90
  children: [],
91
91
  },
92
92
  {
93
93
  icon: 'comment outline',
94
94
  text: 'Contact us',
95
- link: '/en/mission/about-us/contact-us',
95
+ link: '/en/mission/about/contact',
96
96
  },
97
97
  // {
98
98
  // icon: 'envelope outline',
@@ -119,6 +119,11 @@ const applyConfig = (config) => {
119
119
  config.blocks.blocksConfig.maps.restricted = false;
120
120
  }
121
121
 
122
+ // Enable video
123
+ if (config.blocks.blocksConfig.video) {
124
+ config.blocks.blocksConfig.video.restricted = false;
125
+ }
126
+
122
127
  //console.log(config);
123
128
  config.views.contentTypesViews = {
124
129
  ...config.views.contentTypesViews,
@@ -137,7 +142,7 @@ const applyConfig = (config) => {
137
142
 
138
143
  config.settings.contextNavigationLocations = [
139
144
  {
140
- title: 'Regional Adaptation Tool',
145
+ title: 'Regional Adaptation Support Tool',
141
146
  columns: 4,
142
147
  topLevel: 2,
143
148
  bottomLevel: 0,