@eeacms/volto-eea-website-theme 1.15.0 → 1.16.0

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,7 +4,16 @@ 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
- ### [1.15.0](https://github.com/eea/volto-eea-website-theme/compare/1.14.1...1.15.0) - 2 June 2023
7
+ ### [1.16.0](https://github.com/eea/volto-eea-website-theme/compare/1.15.0...1.16.0) - 8 June 2023
8
+
9
+ #### :bug: Bug Fixes
10
+
11
+ - fix(comments): Upgrade customization of Comments.jsx to reflect the latest updates from Volto - refs #251360 [dobri1408 - [`2687b94`](https://github.com/eea/volto-eea-website-theme/commit/2687b94b5fc8738e22548c04b64eeb3bba50a12e)]
12
+
13
+ #### :hammer_and_wrench: Others
14
+
15
+ - Updated package.json [Miu Razvan - [`da82fae`](https://github.com/eea/volto-eea-website-theme/commit/da82faefe753c7fdc9f6122cc111e81a41f0e947)]
16
+ ### [1.15.0](https://github.com/eea/volto-eea-website-theme/compare/1.14.1...1.15.0) - 6 June 2023
8
17
 
9
18
  #### :rocket: New Features
10
19
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-eea-website-theme",
3
- "version": "1.15.0",
3
+ "version": "1.16.0",
4
4
  "description": "@eeacms/volto-eea-website-theme: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -0,0 +1,232 @@
1
+ /**
2
+ * Contents properties modal.
3
+ * @module components/manage/Contents/ContentsPropertiesModal
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 { isEmpty, map } from 'lodash';
11
+ import { defineMessages, injectIntl } from 'react-intl';
12
+
13
+ import { updateContent } from '@plone/volto/actions';
14
+ import { ModalForm } from '@plone/volto/components';
15
+
16
+ const messages = defineMessages({
17
+ properties: {
18
+ id: 'Properties',
19
+ defaultMessage: 'Properties',
20
+ },
21
+ default: {
22
+ id: 'Default',
23
+ defaultMessage: 'Default',
24
+ },
25
+ effectiveTitle: {
26
+ id: 'Publishing Date',
27
+ defaultMessage: 'Publishing Date',
28
+ },
29
+ effectiveDescription: {
30
+ id:
31
+ 'If this date is in the future, the content will not show up in listings and searches until this date.',
32
+ defaultMessage:
33
+ 'If this date is in the future, the content will not show up in listings and searches until this date.',
34
+ },
35
+ expiresTitle: {
36
+ id: 'Expiration Date',
37
+ defaultMessage: 'Expiration Date',
38
+ },
39
+ expiresDescription: {
40
+ id:
41
+ 'When this date is reached, the content will nolonger be visible in listings and searches.',
42
+ defaultMessage:
43
+ 'When this date is reached, the content will nolonger be visible in listings and searches.',
44
+ },
45
+ rightsTitle: {
46
+ id: 'Rights',
47
+ defaultMessage: 'Rights',
48
+ },
49
+ rightsDescription: {
50
+ id: 'Copyright statement or other rights information on this item.',
51
+ defaultMessage:
52
+ 'Copyright statement or other rights information on this item.',
53
+ },
54
+ creatorsTitle: {
55
+ id: 'Creators',
56
+ defaultMessage: 'Creators',
57
+ },
58
+ creatorsDescription: {
59
+ id:
60
+ 'Persons responsible for creating the content of this item. Please enter a list of user names, one per line. The principal creator should come first.',
61
+ defaultMessage:
62
+ 'Persons responsible for creating the content of this item. Please enter a list of user names, one per line. The principal creator should come first.',
63
+ },
64
+ excludeFromNavTitle: {
65
+ id: 'Exclude from navigation',
66
+ defaultMessage: 'Exclude from navigation',
67
+ },
68
+ excludeFromNavDescription: {
69
+ id: 'If selected, this item will not appear in the navigation tree',
70
+ defaultMessage:
71
+ 'If selected, this item will not appear in the navigation tree',
72
+ },
73
+ yes: {
74
+ id: 'Yes',
75
+ defaultMessage: 'Yes',
76
+ },
77
+ no: {
78
+ id: 'No',
79
+ defaultMessage: 'No',
80
+ },
81
+ });
82
+
83
+ /**
84
+ * ContentsPropertiesModal class.
85
+ * @class ContentsPropertiesModal
86
+ * @extends Component
87
+ */
88
+ class ContentsPropertiesModal extends Component {
89
+ /**
90
+ * Property types.
91
+ * @property {Object} propTypes Property types.
92
+ * @static
93
+ */
94
+ static propTypes = {
95
+ updateContent: PropTypes.func.isRequired,
96
+ items: PropTypes.arrayOf(PropTypes.string).isRequired,
97
+ request: PropTypes.shape({
98
+ loading: PropTypes.bool,
99
+ loaded: PropTypes.bool,
100
+ }).isRequired,
101
+ open: PropTypes.bool.isRequired,
102
+ onOk: PropTypes.func.isRequired,
103
+ onCancel: PropTypes.func.isRequired,
104
+ };
105
+
106
+ /**
107
+ * Constructor
108
+ * @method constructor
109
+ * @param {Object} props Component properties
110
+ * @constructs ContentsUploadModal
111
+ */
112
+ constructor(props) {
113
+ super(props);
114
+
115
+ this.onSubmit = this.onSubmit.bind(this);
116
+ }
117
+
118
+ /**
119
+ * Component will receive props
120
+ * @method componentWillReceiveProps
121
+ * @param {Object} nextProps Next properties
122
+ * @returns {undefined}
123
+ */
124
+ UNSAFE_componentWillReceiveProps(nextProps) {
125
+ if (this.props.request.loading && nextProps.request.loaded) {
126
+ this.props.onOk();
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Submit handler
132
+ * @method onSubmit
133
+ * @param {Object} data Form data
134
+ * @returns {undefined}
135
+ */
136
+ onSubmit(data) {
137
+ if (isEmpty(data)) {
138
+ this.props.onOk();
139
+ } else {
140
+ this.props.updateContent(
141
+ this.props.items,
142
+ map(this.props.items, () => data),
143
+ );
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Render method.
149
+ * @method render
150
+ * @returns {string} Markup for the component.
151
+ */
152
+ render() {
153
+ return (
154
+ this.props.open && (
155
+ <ModalForm
156
+ open={this.props.open}
157
+ onSubmit={this.onSubmit}
158
+ onCancel={this.props.onCancel}
159
+ title={this.props.intl.formatMessage(messages.properties)}
160
+ schema={{
161
+ fieldsets: [
162
+ {
163
+ id: 'default',
164
+ title: this.props.intl.formatMessage(messages.default),
165
+ fields: [
166
+ 'effective',
167
+ 'expires',
168
+ 'rights',
169
+ 'creators',
170
+ 'exclude_from_nav',
171
+ ],
172
+ },
173
+ ],
174
+ properties: {
175
+ effective: {
176
+ description: this.props.intl.formatMessage(
177
+ messages.effectiveDescription,
178
+ ),
179
+ title: this.props.intl.formatMessage(messages.effectiveTitle),
180
+ type: 'string',
181
+ widget: 'datetime',
182
+ },
183
+ expires: {
184
+ description: this.props.intl.formatMessage(
185
+ messages.expiresDescription,
186
+ ),
187
+ title: this.props.intl.formatMessage(messages.expiresTitle),
188
+ type: 'string',
189
+ widget: 'datetime',
190
+ },
191
+ rights: {
192
+ description: this.props.intl.formatMessage(
193
+ messages.rightsDescription,
194
+ ),
195
+ title: this.props.intl.formatMessage(messages.rightsTitle),
196
+ type: 'string',
197
+ widget: 'textarea',
198
+ },
199
+ creators: {
200
+ description: this.props.intl.formatMessage(
201
+ messages.creatorsDescription,
202
+ ),
203
+ title: this.props.intl.formatMessage(messages.creatorsTitle),
204
+ type: 'array',
205
+ },
206
+ exclude_from_nav: {
207
+ description: this.props.intl.formatMessage(
208
+ messages.excludeFromNavDescription,
209
+ ),
210
+ title: this.props.intl.formatMessage(
211
+ messages.excludeFromNavTitle,
212
+ ),
213
+ type: 'boolean',
214
+ },
215
+ },
216
+ required: [],
217
+ }}
218
+ />
219
+ )
220
+ );
221
+ }
222
+ }
223
+
224
+ export default compose(
225
+ injectIntl,
226
+ connect(
227
+ (state) => ({
228
+ request: state.content.update,
229
+ }),
230
+ { updateContent },
231
+ ),
232
+ )(ContentsPropertiesModal);
@@ -18,8 +18,10 @@ import { Portal } from 'react-portal';
18
18
  import { connect } from 'react-redux';
19
19
  import { compose } from 'redux';
20
20
  import { Button, Comment, Container, Icon } from 'semantic-ui-react';
21
+ import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
21
22
  import { formatRelativeDate } from '@plone/volto/helpers/Utils/Date';
22
23
  import config from '@plone/volto/registry';
24
+ // import { Button, Grid, Segment, Container } from 'semantic-ui-react';
23
25
 
24
26
  const messages = defineMessages({
25
27
  comment: {
@@ -296,7 +298,7 @@ class Comments extends Component {
296
298
  * @returns {string} Markup for the component.
297
299
  */
298
300
  render() {
299
- const { items } = this.props;
301
+ const { items, permissions } = this.props;
300
302
  const { collapsedComments } = this.state;
301
303
  // object with comment ids, to easily verify if any comment has children
302
304
  const allCommentsWithCildren = this.addRepliesAsChildrenToComments(items);
@@ -308,7 +310,7 @@ class Comments extends Component {
308
310
  const commentElement = (comment) => (
309
311
  <Comment key={comment.comment_id}>
310
312
  <Avatar
311
- src={comment.author_image}
313
+ src={flattenToAppURL(comment.author_image)}
312
314
  title={comment.author_name || 'Anonymous'}
313
315
  color={getColor(comment.author_username)}
314
316
  />
@@ -338,13 +340,15 @@ class Comments extends Component {
338
340
  )}
339
341
  </Comment.Text>
340
342
  <Comment.Actions>
341
- <Comment.Action
342
- as="a"
343
- aria-label={this.props.intl.formatMessage(messages.reply)}
344
- onClick={() => this.setReplyTo(comment.comment_id)}
345
- >
346
- <FormattedMessage id="Reply" defaultMessage="Reply" />
347
- </Comment.Action>
343
+ {comment.can_reply && (
344
+ <Comment.Action
345
+ as="a"
346
+ aria-label={this.props.intl.formatMessage(messages.reply)}
347
+ onClick={() => this.setReplyTo(comment.comment_id)}
348
+ >
349
+ <FormattedMessage id="Reply" defaultMessage="Reply" />
350
+ </Comment.Action>
351
+ )}
348
352
  {comment.is_editable && (
349
353
  <Comment.Action
350
354
  onClick={() =>
@@ -420,6 +424,8 @@ class Comments extends Component {
420
424
  </Comment>
421
425
  );
422
426
 
427
+ if (!permissions.view_comments) return '';
428
+
423
429
  return (
424
430
  <Container className="comments">
425
431
  <CommentEditModal
@@ -429,16 +435,17 @@ class Comments extends Component {
429
435
  id={this.state.editId}
430
436
  text={this.state.editText}
431
437
  />
432
- <div id="comment-add-id">
433
- <Form
434
- onSubmit={this.onSubmit}
435
- onCancel={this.onEditCancel}
436
- submitLabel={this.props.intl.formatMessage(messages.comment)}
437
- resetAfterSubmit
438
- schema={makeFormSchema(this.props.intl)}
439
- />
440
- </div>
441
-
438
+ {permissions.can_reply && (
439
+ <div id="comment-add-id">
440
+ <Form
441
+ onSubmit={this.onSubmit}
442
+ onCancel={this.onEditCancel}
443
+ submitLabel={this.props.intl.formatMessage(messages.comment)}
444
+ resetAfterSubmit
445
+ schema={makeFormSchema(this.props.intl)}
446
+ />
447
+ </div>
448
+ )}
442
449
  {/* all comments */}
443
450
  <Comment.Group threaded={false}>
444
451
  {allPrimaryComments.map((item) => commentElement(item))}
@@ -474,11 +481,13 @@ class Comments extends Component {
474
481
 
475
482
  export default compose(
476
483
  injectIntl,
484
+ injectLazyLibs(['moment']),
477
485
  connect(
478
486
  (state) => ({
479
487
  items: state.comments.items,
480
488
  next: state.comments.next,
481
489
  items_total: state.comments.items_total,
490
+ permissions: state.comments.permissions || {},
482
491
  addRequest: state.comments.add,
483
492
  deleteRequest: state.comments.delete,
484
493
  }),