@eeacms/volto-cca-policy 0.3.58 → 0.3.60

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,12 +4,18 @@ 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.3.60](https://github.com/eea/volto-cca-policy/compare/0.3.59...0.3.60) - 3 July 2025
8
+
9
+ #### :hammer_and_wrench: Others
10
+
11
+ - Let's try again [Tiberiu Ichim - [`bd4367a`](https://github.com/eea/volto-cca-policy/commit/bd4367af3b02f724e9ae6e9d14e0cd963dca4042)]
12
+ ### [0.3.59](https://github.com/eea/volto-cca-policy/compare/0.3.58...0.3.59) - 3 July 2025
13
+
7
14
  ### [0.3.58](https://github.com/eea/volto-cca-policy/compare/0.3.57...0.3.58) - 3 July 2025
8
15
 
9
16
  #### :hammer_and_wrench: Others
10
17
 
11
18
  - Solve eslint [Tiberiu Ichim - [`29f656a`](https://github.com/eea/volto-cca-policy/commit/29f656a48416a04a2ebdf82091f25134b117cd7d)]
12
- - Solve problem in redirection [Tiberiu Ichim - [`6afb231`](https://github.com/eea/volto-cca-policy/commit/6afb231df59acc0b2ff4f162420ae9c93040ee09)]
13
19
  ### [0.3.57](https://github.com/eea/volto-cca-policy/compare/0.3.56...0.3.57) - 27 June 2025
14
20
 
15
21
  #### :house: Internal changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-cca-policy",
3
- "version": "0.3.58",
3
+ "version": "0.3.60",
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 @@
1
+ Customized View.jsx to add the stripping of ++api++
@@ -0,0 +1,301 @@
1
+ /**
2
+ * View container.
3
+ * @module components/theme/View/View
4
+ */
5
+
6
+ import React, { Component } from 'react';
7
+ import PropTypes from 'prop-types';
8
+ import { connect } from 'react-redux';
9
+ import { compose } from 'redux';
10
+ import { Redirect } from 'react-router-dom';
11
+ import { Portal } from 'react-portal';
12
+ import { injectIntl } from 'react-intl';
13
+ import qs from 'query-string';
14
+
15
+ import {
16
+ ContentMetadataTags,
17
+ Comments,
18
+ Tags,
19
+ Toolbar,
20
+ } from '@plone/volto/components';
21
+ import { listActions, getContent } from '@plone/volto/actions';
22
+ import {
23
+ BodyClass,
24
+ getBaseUrl,
25
+ flattenToAppURL,
26
+ getLayoutFieldname,
27
+ hasApiExpander,
28
+ } from '@plone/volto/helpers';
29
+
30
+ import config from '@plone/volto/registry';
31
+
32
+ /**
33
+ * View container class.
34
+ * @class View
35
+ * @extends Component
36
+ */
37
+ class View extends Component {
38
+ /**
39
+ * Property types.
40
+ * @property {Object} propTypes Property types.
41
+ * @static
42
+ */
43
+ static propTypes = {
44
+ actions: PropTypes.shape({
45
+ object: PropTypes.arrayOf(PropTypes.object),
46
+ object_buttons: PropTypes.arrayOf(PropTypes.object),
47
+ user: PropTypes.arrayOf(PropTypes.object),
48
+ }),
49
+ listActions: PropTypes.func.isRequired,
50
+ /**
51
+ * Action to get the content
52
+ */
53
+ getContent: PropTypes.func.isRequired,
54
+ /**
55
+ * Pathname of the object
56
+ */
57
+ pathname: PropTypes.string.isRequired,
58
+ location: PropTypes.shape({
59
+ search: PropTypes.string,
60
+ pathname: PropTypes.string,
61
+ }).isRequired,
62
+ /**
63
+ * Version id of the object
64
+ */
65
+ versionId: PropTypes.string,
66
+ /**
67
+ * Content of the object
68
+ */
69
+ content: PropTypes.shape({
70
+ /**
71
+ * Layout of the object
72
+ */
73
+ layout: PropTypes.string,
74
+ /**
75
+ * Allow discussion of the object
76
+ */
77
+ allow_discussion: PropTypes.bool,
78
+ /**
79
+ * Title of the object
80
+ */
81
+ title: PropTypes.string,
82
+ /**
83
+ * Description of the object
84
+ */
85
+ description: PropTypes.string,
86
+ /**
87
+ * Type of the object
88
+ */
89
+ '@type': PropTypes.string,
90
+ /**
91
+ * Subjects of the object
92
+ */
93
+ subjects: PropTypes.arrayOf(PropTypes.string),
94
+ is_folderish: PropTypes.bool,
95
+ }),
96
+ error: PropTypes.shape({
97
+ /**
98
+ * Error type
99
+ */
100
+ status: PropTypes.number,
101
+ }),
102
+ };
103
+
104
+ /**
105
+ * Default properties.
106
+ * @property {Object} defaultProps Default properties.
107
+ * @static
108
+ */
109
+ static defaultProps = {
110
+ actions: null,
111
+ content: null,
112
+ versionId: null,
113
+ error: null,
114
+ };
115
+
116
+ state = {
117
+ hasObjectButtons: null,
118
+ isClient: false,
119
+ };
120
+
121
+ componentDidMount() {
122
+ // Do not trigger the actions action if the expander is present
123
+ if (!hasApiExpander('actions', getBaseUrl(this.props.pathname))) {
124
+ this.props.listActions(getBaseUrl(this.props.pathname));
125
+ }
126
+ this.props.getContent(
127
+ getBaseUrl(this.props.pathname),
128
+ this.props.versionId,
129
+ );
130
+ this.setState({ isClient: true });
131
+ }
132
+
133
+ /**
134
+ * Component will receive props
135
+ * @method componentWillReceiveProps
136
+ * @param {Object} nextProps Next properties
137
+ * @returns {undefined}
138
+ */
139
+ UNSAFE_componentWillReceiveProps(nextProps) {
140
+ if (nextProps.pathname !== this.props.pathname) {
141
+ // Do not trigger the actions action if the expander is present
142
+ if (!hasApiExpander('actions', getBaseUrl(nextProps.pathname))) {
143
+ this.props.listActions(getBaseUrl(nextProps.pathname));
144
+ }
145
+ this.props.getContent(
146
+ getBaseUrl(nextProps.pathname),
147
+ this.props.versionId,
148
+ );
149
+ }
150
+
151
+ if (nextProps.actions.object_buttons) {
152
+ const objectButtons = nextProps.actions.object_buttons;
153
+ this.setState({
154
+ hasObjectButtons: !!objectButtons.length,
155
+ });
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Default fallback view
161
+ * @method getViewDefault
162
+ * @returns {string} Markup for component.
163
+ */
164
+ getViewDefault = () => config.views.defaultView;
165
+
166
+ /**
167
+ * Get view by content type
168
+ * @method getViewByType
169
+ * @returns {string} Markup for component.
170
+ */
171
+ getViewByType = () =>
172
+ config.views.contentTypesViews[this.props.content['@type']] || null;
173
+
174
+ /**
175
+ * Get view by content layout property
176
+ * @method getViewByLayout
177
+ * @returns {string} Markup for component.
178
+ */
179
+ getViewByLayout = () =>
180
+ config.views.layoutViews[
181
+ this.props.content[getLayoutFieldname(this.props.content)]
182
+ ] || null;
183
+
184
+ /**
185
+ * Cleans the component displayName (specially for connected components)
186
+ * which have the Connect(componentDisplayName)
187
+ * @method cleanViewName
188
+ * @param {string} dirtyDisplayName The displayName
189
+ * @returns {string} Clean displayName (no Connect(...)).
190
+ */
191
+ cleanViewName = (dirtyDisplayName) =>
192
+ dirtyDisplayName
193
+ .replace('Connect(', '')
194
+ .replace('injectIntl(', '')
195
+ .replace(')', '')
196
+ .replace('connect(', '')
197
+ .toLowerCase();
198
+
199
+ /**
200
+ * Render method.
201
+ * @method render
202
+ * @returns {string} Markup for the component.
203
+ */
204
+ render() {
205
+ const { views } = config;
206
+ if (this.props.error && this.props.error.code === 301) {
207
+ const redirect = flattenToAppURL(this.props.error.url)
208
+ .replaceAll('/++api++', '/')
209
+ .split('?')[0];
210
+ // eslint-disable-next-line no-console
211
+ console.log('Redirecting', redirect);
212
+ return <Redirect to={`${redirect}${this.props.location.search}`} />;
213
+ } else if (this.props.error && !this.props.connectionRefused) {
214
+ let FoundView;
215
+ if (this.props.error.status === undefined) {
216
+ // For some reason, while development and if CORS is in place and the
217
+ // requested resource is 404, it returns undefined as status, then the
218
+ // next statement will fail
219
+ FoundView = views.errorViews.corsError;
220
+ } else {
221
+ FoundView = views.errorViews[this.props.error.status.toString()];
222
+ }
223
+ if (!FoundView) {
224
+ FoundView = views.errorViews['404']; // default to 404
225
+ }
226
+ return (
227
+ <div id="view">
228
+ <FoundView {...this.props} />
229
+ </div>
230
+ );
231
+ }
232
+ if (!this.props.content) {
233
+ return <span />;
234
+ }
235
+ const RenderedView =
236
+ this.getViewByLayout() || this.getViewByType() || this.getViewDefault();
237
+
238
+ return (
239
+ <div id="view">
240
+ <ContentMetadataTags content={this.props.content} />
241
+ {/* Body class if displayName in component is set */}
242
+ <BodyClass
243
+ className={
244
+ RenderedView.displayName
245
+ ? `view-${this.cleanViewName(RenderedView.displayName)}`
246
+ : null
247
+ }
248
+ />
249
+ <RenderedView
250
+ key={this.props.content['@id']}
251
+ content={this.props.content}
252
+ location={this.props.location}
253
+ token={this.props.token}
254
+ history={this.props.history}
255
+ />
256
+ {config.settings.showTags &&
257
+ this.props.content.subjects &&
258
+ this.props.content.subjects.length > 0 && (
259
+ <Tags tags={this.props.content.subjects} />
260
+ )}
261
+ {/* Add opt-in social sharing if required, disabled by default */}
262
+ {/* In the future this might be parameterized from the app config */}
263
+ {/* <SocialSharing
264
+ url={typeof window === 'undefined' ? '' : window.location.href}
265
+ title={this.props.content.title}
266
+ description={this.props.content.description || ''}
267
+ /> */}
268
+ {this.props.content.allow_discussion && (
269
+ <Comments pathname={this.props.pathname} />
270
+ )}
271
+ {this.state.isClient && (
272
+ <Portal node={document.getElementById('toolbar')}>
273
+ <Toolbar pathname={this.props.pathname} inner={<span />} />
274
+ </Portal>
275
+ )}
276
+ </div>
277
+ );
278
+ }
279
+ }
280
+
281
+ export default compose(
282
+ injectIntl,
283
+ connect(
284
+ (state, props) => ({
285
+ actions: state.actions.actions,
286
+ token: state.userSession.token,
287
+ content: state.content.data,
288
+ error: state.content.get.error,
289
+ apiError: state.apierror.error,
290
+ connectionRefused: state.apierror.connectionRefused,
291
+ pathname: props.location.pathname,
292
+ versionId:
293
+ qs.parse(props.location.search) &&
294
+ qs.parse(props.location.search).version,
295
+ }),
296
+ {
297
+ listActions,
298
+ getContent,
299
+ },
300
+ ),
301
+ )(View);