@eeacms/volto-clms-theme 1.1.175 → 1.1.177

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,10 @@ 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.1.177](https://github.com/eea/volto-clms-theme/compare/1.1.176...1.1.177) - 8 August 2024
8
+
9
+ ### [1.1.176](https://github.com/eea/volto-clms-theme/compare/1.1.175...1.1.176) - 8 August 2024
10
+
7
11
  ### [1.1.175](https://github.com/eea/volto-clms-theme/compare/1.1.174...1.1.175) - 8 August 2024
8
12
 
9
13
  #### :hammer_and_wrench: Others
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-clms-theme",
3
- "version": "1.1.175",
3
+ "version": "1.1.177",
4
4
  "description": "volto-clms-theme: Volto theme for CLMS site",
5
5
  "main": "src/index.js",
6
6
  "author": "CodeSyntax for the European Environment Agency",
@@ -0,0 +1,405 @@
1
+ /**
2
+ * Contents item component.
3
+ * @module components/manage/Contents/ContentsItem
4
+ */
5
+
6
+ import React from 'react';
7
+ import { Button, Table, Menu, Divider } from 'semantic-ui-react';
8
+ import { Link } from 'react-router-dom';
9
+ import PropTypes from 'prop-types';
10
+ import { map } from 'lodash';
11
+ import { useIntl, defineMessages, FormattedMessage } from 'react-intl';
12
+ import { Circle, FormattedDate, Icon, Popup } from '@plone/volto/components';
13
+ import { getContentIcon } from '@plone/volto/helpers';
14
+ import moreSVG from '@plone/volto/icons/more.svg';
15
+ import checkboxUncheckedSVG from '@plone/volto/icons/checkbox-unchecked.svg';
16
+ import checkboxCheckedSVG from '@plone/volto/icons/checkbox-checked.svg';
17
+ import cutSVG from '@plone/volto/icons/cut.svg';
18
+ import deleteSVG from '@plone/volto/icons/delete.svg';
19
+ import copySVG from '@plone/volto/icons/copy.svg';
20
+ import showSVG from '@plone/volto/icons/show.svg';
21
+ import moveUpSVG from '@plone/volto/icons/move-up.svg';
22
+ import moveDownSVG from '@plone/volto/icons/move-down.svg';
23
+ import editingSVG from '@plone/volto/icons/editing.svg';
24
+ import dragSVG from '@plone/volto/icons/drag.svg';
25
+ import cx from 'classnames';
26
+
27
+ import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
28
+
29
+ const messages = defineMessages({
30
+ private: {
31
+ id: 'private',
32
+ defaultMessage: 'Private',
33
+ },
34
+ pending: {
35
+ id: 'pending',
36
+ defaultMessage: 'Pending',
37
+ },
38
+ published: {
39
+ id: 'published',
40
+ defaultMessage: 'Published',
41
+ },
42
+ intranet: {
43
+ id: 'intranet',
44
+ defaultMessage: 'Intranet',
45
+ },
46
+ draft: {
47
+ id: 'draft',
48
+ defaultMessage: 'Draft',
49
+ },
50
+ no_workflow_state: {
51
+ id: 'no workflow state',
52
+ defaultMessage: 'No workflow state',
53
+ },
54
+ none: {
55
+ id: 'None',
56
+ defaultMessage: 'None',
57
+ },
58
+ });
59
+
60
+ function getColor(string) {
61
+ switch (string) {
62
+ case 'private':
63
+ return '#ed4033';
64
+ case 'published':
65
+ return '#007bc1';
66
+ case 'intranet':
67
+ return '#51aa55';
68
+ case 'draft':
69
+ return '#f6a808';
70
+ default:
71
+ return 'grey';
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Contents item component class.
77
+ * @function ContentsItemComponent
78
+ * @returns {string} Markup of the component.
79
+ */
80
+ export const ContentsItemComponent = ({
81
+ item,
82
+ selected,
83
+ onClick,
84
+ indexes,
85
+ onCut,
86
+ onCopy,
87
+ onDelete,
88
+ onMoveToTop,
89
+ onMoveToBottom,
90
+ connectDragPreview,
91
+ connectDragSource,
92
+ connectDropTarget,
93
+ isDragging,
94
+ order,
95
+ }) => {
96
+ const intl = useIntl();
97
+
98
+ return connectDropTarget(
99
+ connectDragPreview(
100
+ <tr
101
+ key={item['@id']}
102
+ className={cx('', { 'dragging-row': isDragging })}
103
+ aria-label={item['@id']}
104
+ >
105
+ <Table.Cell className={cx('', { 'dragging-cell': isDragging })}>
106
+ {connectDragSource(
107
+ <div style={{ display: 'inline-block' }}>
108
+ <Button icon basic>
109
+ <Icon
110
+ name={dragSVG}
111
+ size="20px"
112
+ color="#878f93"
113
+ className="content drag handle"
114
+ />
115
+ </Button>
116
+ </div>,
117
+ )}
118
+ </Table.Cell>
119
+ <Table.Cell className={cx('', { 'dragging-cell': isDragging })}>
120
+ {selected ? (
121
+ <Button
122
+ icon
123
+ basic
124
+ aria-label="Unchecked"
125
+ onClick={(e) => onClick(e, item['@id'])}
126
+ >
127
+ <Icon
128
+ name={checkboxCheckedSVG}
129
+ color="#007eb1"
130
+ size="24px"
131
+ className="checked"
132
+ />
133
+ </Button>
134
+ ) : (
135
+ <Button
136
+ icon
137
+ basic
138
+ aria-label="Checked"
139
+ onClick={(e) => onClick(e, item['@id'])}
140
+ >
141
+ <Icon
142
+ name={checkboxUncheckedSVG}
143
+ color="#826a6a"
144
+ size="24px"
145
+ className="unchecked"
146
+ />
147
+ </Button>
148
+ )}
149
+ </Table.Cell>
150
+ <Table.Cell className={cx('', { 'dragging-cell': isDragging })}>
151
+ <Link
152
+ className="icon-align-name"
153
+ to={`${item['@id']}${item.is_folderish ? '/contents' : ''}`}
154
+ >
155
+ <div className="expire-align">
156
+ <Icon
157
+ name={getContentIcon(item['@type'], item.is_folderish)}
158
+ size="20px"
159
+ className="icon-margin"
160
+ color="#878f93"
161
+ title={item['Type'] || item['@type']}
162
+ />
163
+ <span title={item.title} className="content-title-force-one-line">
164
+ {item.title}
165
+ </span>
166
+ </div>
167
+ {item.ExpirationDate !== 'None' &&
168
+ new Date(item.ExpirationDate).getTime() <
169
+ new Date().getTime() && (
170
+ <Button className="button-margin" size="mini">
171
+ <FormattedMessage id="Expired" defaultMessage="Expired" />
172
+ </Button>
173
+ )}
174
+ {item.EffectiveDate !== 'None' &&
175
+ new Date(item.EffectiveDate).getTime() > new Date().getTime() && (
176
+ <Button className="button-margin effective-future" size="mini">
177
+ <FormattedMessage id="Scheduled" defaultMessage="Scheduled" />
178
+ </Button>
179
+ )}
180
+ </Link>
181
+ </Table.Cell>
182
+ {map(indexes, (index) => (
183
+ <Table.Cell
184
+ className={cx('', { 'dragging-cell': isDragging })}
185
+ key={index.id}
186
+ >
187
+ {index.type === 'boolean' &&
188
+ (item[index.id] ? (
189
+ <FormattedMessage id="Yes" defaultMessage="Yes" />
190
+ ) : (
191
+ <FormattedMessage id="No" defaultMessage="No" />
192
+ ))}
193
+ {index.type === 'string' &&
194
+ index.id !== 'review_state' &&
195
+ item[index.id]}
196
+ {index.id === 'review_state' && (
197
+ <div>
198
+ <span>
199
+ <Circle color={getColor(item[index.id])} size="15px" />
200
+ </span>
201
+ {messages[item[index.id]]
202
+ ? intl.formatMessage(messages[item[index.id]])
203
+ : item['review_title'] ||
204
+ item['review_state'] ||
205
+ intl.formatMessage(messages.no_workflow_state)}
206
+ </div>
207
+ )}
208
+ {index.type === 'date' && (
209
+ <>
210
+ {item[index?.id] && item[index.id] !== 'None' ? (
211
+ <FormattedDate date={item[index.id]} />
212
+ ) : (
213
+ intl.formatMessage(messages.none)
214
+ )}
215
+ </>
216
+ )}
217
+ {index.type === 'array' && (
218
+ <span>{item[index.id]?.join(', ')}</span>
219
+ )}
220
+ </Table.Cell>
221
+ ))}
222
+ <Table.Cell
223
+ className={cx('', { 'dragging-cell': isDragging })}
224
+ textAlign="right"
225
+ >
226
+ <Popup
227
+ menu={true}
228
+ position="bottom right"
229
+ flowing={true}
230
+ basic={true}
231
+ on="click"
232
+ popper={{
233
+ className: 'dropdown-popup',
234
+ }}
235
+ trigger={
236
+ <Icon
237
+ name={moreSVG}
238
+ className="dropdown-popup-trigger"
239
+ size="24px"
240
+ color="#007eb1"
241
+ />
242
+ }
243
+ >
244
+ <Menu vertical borderless fluid>
245
+ <Link className="item icon-align" to={`${item['@id']}/edit`}>
246
+ <Icon name={editingSVG} color="#007eb1" size="24px" />{' '}
247
+ <FormattedMessage id="Edit" defaultMessage="Edit" />
248
+ </Link>
249
+ <Link className="item right-dropdown icon-align" to={item['@id']}>
250
+ <Icon name={showSVG} color="#007eb1" size="24px" />{' '}
251
+ <FormattedMessage id="View" defaultMessage="View" />
252
+ </Link>
253
+ <Divider />
254
+ <Menu.Item
255
+ onClick={onCut}
256
+ value={item['@id']}
257
+ className="right-dropdown icon-align"
258
+ >
259
+ <Icon name={cutSVG} color="#007eb1" size="24px" />{' '}
260
+ <FormattedMessage id="Cut" defaultMessage="Cut" />
261
+ </Menu.Item>
262
+ <Menu.Item
263
+ onClick={onCopy}
264
+ value={item['@id']}
265
+ className="right-dropdown icon-align"
266
+ >
267
+ <Icon name={copySVG} color="#007eb1" size="24px" />{' '}
268
+ <FormattedMessage id="Copy" defaultMessage="Copy" />
269
+ </Menu.Item>
270
+ <Menu.Item
271
+ onClick={onDelete}
272
+ value={item['@id']}
273
+ className="right-dropdown icon-align"
274
+ >
275
+ <Icon name={deleteSVG} color="#e40166" size="24px" />{' '}
276
+ <FormattedMessage id="Delete" defaultMessage="Delete" />
277
+ </Menu.Item>
278
+ <Divider />
279
+ <Menu.Item
280
+ onClick={onMoveToTop}
281
+ value={order}
282
+ className="right-dropdown icon-align"
283
+ >
284
+ <Icon name={moveUpSVG} color="#007eb1" size="24px" />{' '}
285
+ <FormattedMessage
286
+ id="Move to top of folder"
287
+ defaultMessage="Move to top of folder"
288
+ />
289
+ </Menu.Item>
290
+ <Menu.Item
291
+ onClick={onMoveToBottom}
292
+ value={order}
293
+ className="right-dropdown icon-align"
294
+ >
295
+ <Icon name={moveDownSVG} color="#007eb1" size="24px" />{' '}
296
+ <FormattedMessage
297
+ id="Move to bottom of folder"
298
+ defaultMessage="Move to bottom of folder"
299
+ />
300
+ </Menu.Item>
301
+ </Menu>
302
+ </Popup>
303
+ </Table.Cell>
304
+ </tr>,
305
+ ),
306
+ );
307
+ };
308
+
309
+ /**
310
+ * Property types.
311
+ * @property {Object} propTypes Property types.
312
+ * @static
313
+ */
314
+ ContentsItemComponent.propTypes = {
315
+ item: PropTypes.shape({
316
+ '@id': PropTypes.string,
317
+ title: PropTypes.string,
318
+ is_folderish: PropTypes.bool,
319
+ '@type': PropTypes.string,
320
+ }).isRequired,
321
+ selected: PropTypes.bool.isRequired,
322
+ onClick: PropTypes.func.isRequired,
323
+ indexes: PropTypes.arrayOf(
324
+ PropTypes.shape({
325
+ id: PropTypes.string,
326
+ type: PropTypes.string,
327
+ }),
328
+ ).isRequired,
329
+ onCut: PropTypes.func.isRequired,
330
+ onCopy: PropTypes.func.isRequired,
331
+ onDelete: PropTypes.func.isRequired,
332
+ onMoveToTop: PropTypes.func.isRequired,
333
+ onMoveToBottom: PropTypes.func.isRequired,
334
+ connectDragPreview: PropTypes.func.isRequired,
335
+ connectDragSource: PropTypes.func.isRequired,
336
+ connectDropTarget: PropTypes.func.isRequired,
337
+ isDragging: PropTypes.bool.isRequired,
338
+ order: PropTypes.number.isRequired,
339
+ onOrderItem: PropTypes.func.isRequired,
340
+ };
341
+
342
+ const DragDropConnector = (props) => {
343
+ const { DropTarget, DragSource } = props.reactDnd;
344
+
345
+ const DndConnectedContentsItem = React.useMemo(
346
+ () =>
347
+ DropTarget(
348
+ 'item',
349
+ {
350
+ hover(props, monitor) {
351
+ const id = monitor.getItem().id;
352
+ const dragOrder = monitor.getItem().order;
353
+ const hoverOrder = props.order;
354
+
355
+ if (dragOrder === hoverOrder) {
356
+ return;
357
+ }
358
+
359
+ props.onOrderItem(id, dragOrder, hoverOrder - dragOrder, false);
360
+
361
+ monitor.getItem().order = hoverOrder;
362
+ },
363
+ drop(props, monitor) {
364
+ const id = monitor.getItem().id;
365
+ const dragOrder = monitor.getItem().startOrder;
366
+ const dropOrder = props.order;
367
+
368
+ if (dragOrder === dropOrder) {
369
+ return;
370
+ }
371
+
372
+ props.onOrderItem(id, dragOrder, dropOrder - dragOrder, true);
373
+
374
+ monitor.getItem().order = dropOrder;
375
+ },
376
+ },
377
+ (connect) => ({
378
+ connectDropTarget: connect.dropTarget(),
379
+ }),
380
+ )(
381
+ DragSource(
382
+ 'item',
383
+ {
384
+ beginDrag(props) {
385
+ return {
386
+ id: props.item['@id'],
387
+ order: props.order,
388
+ startOrder: props.order,
389
+ };
390
+ },
391
+ },
392
+ (connect, monitor) => ({
393
+ connectDragSource: connect.dragSource(),
394
+ connectDragPreview: connect.dragPreview(),
395
+ isDragging: monitor.isDragging(),
396
+ }),
397
+ )(ContentsItemComponent),
398
+ ),
399
+ [DragSource, DropTarget],
400
+ );
401
+
402
+ return <DndConnectedContentsItem {...props} />;
403
+ };
404
+
405
+ export default injectLazyLibs('reactDnd')(DragDropConnector);
package/src/index.js CHANGED
@@ -357,7 +357,7 @@ const applyConfig = (config) => {
357
357
 
358
358
  config.settings.initialReducersBlacklist = [
359
359
  ...config.settings.initialReducersBlacklist,
360
- 'dropdownMenuNavItems',
360
+ // 'dropdownMenuNavItems',
361
361
  'reduxAsyncConnect',
362
362
  'intl',
363
363
  // 'content',
@@ -0,0 +1,6 @@
1
+ .folder-contents .ui.table .icon-align-name span.content-title-force-one-line {
2
+ max-width: 250px;
3
+ white-space: nowrap;
4
+ overflow: hidden;
5
+ text-overflow: ellipsis;
6
+ }
@@ -11,6 +11,7 @@
11
11
  @import 'faq';
12
12
  @import 'styles';
13
13
  @import 'volto-block-style-override';
14
+ @import 'contents';
14
15
 
15
16
  @import 'range';
16
17
  @import 'cards';