@eeacms/volto-clms-theme 1.0.63 → 1.0.64

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,9 +4,22 @@ 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.0.64](https://github.com/eea/volto-clms-theme/compare/1.0.63...1.0.64)
8
+
9
+ - Cart download page [`#192`](https://github.com/eea/volto-clms-theme/pull/192)
10
+ - texts for no tasks [`169cd93`](https://github.com/eea/volto-clms-theme/commit/169cd93a8519f08a365852efc27db7edc5498a53)
11
+ - show the selected nuts ID and improve wording [`8378a73`](https://github.com/eea/volto-clms-theme/commit/8378a7307093c4f9fa90f130d9ce0438ac443f2e)
12
+ - add a link to the download process [`444dbff`](https://github.com/eea/volto-clms-theme/commit/444dbff4cab5f0f53a307685e6ba88a808ccfa1d)
13
+ - loading process while download request is completed [`5f82fa8`](https://github.com/eea/volto-clms-theme/commit/5f82fa84c6c513653125fe80be00255d636521c1)
14
+ - download link and filesize only on Finished_ok files [`f68b30c`](https://github.com/eea/volto-clms-theme/commit/f68b30c1330e25e4cd400f83e582e8143dbba576)
15
+ - meeting anonymous form data issue [`e99e518`](https://github.com/eea/volto-clms-theme/commit/e99e5186451de427e0f4a0661e2b9300fd13c98d)
16
+ - reorganize reducer response and create a new route to render the Cart Download view separated from the Cart view [`9ac01f7`](https://github.com/eea/volto-clms-theme/commit/9ac01f7f0ac3b812b20a66d326034f34327ca93f)
17
+
7
18
  #### [1.0.63](https://github.com/eea/volto-clms-theme/compare/1.0.62...1.0.63)
8
19
 
9
- - expose timeExtent info in cart data [`fee869f`](https://github.com/eea/volto-clms-theme/commit/fee869fadeda31c227ebcbbcab294a47190b76b1)
20
+ > 28 January 2022
21
+
22
+ - expose timeExtent info in cart data [`#190`](https://github.com/eea/volto-clms-theme/pull/190)
10
23
 
11
24
  #### [1.0.62](https://github.com/eea/volto-clms-theme/compare/1.0.61...1.0.62)
12
25
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-clms-theme",
3
- "version": "1.0.63",
3
+ "version": "1.0.64",
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",
@@ -14,7 +14,7 @@ export function getDownloadtool() {
14
14
  type: GET_DOWNLOADTOOL,
15
15
  request: {
16
16
  op: 'get',
17
- path: `/@datarequest_search?status=In_progress`,
17
+ path: `/@datarequest_search`,
18
18
  },
19
19
  };
20
20
  }
@@ -17,11 +17,12 @@ import {
17
17
  postDownloadtool,
18
18
  } from '../../actions';
19
19
  import { useDispatch, useSelector } from 'react-redux';
20
-
20
+ import { Toast } from '@plone/volto/components';
21
+ import { toast } from 'react-toastify';
21
22
  import CclButton from '@eeacms/volto-clms-theme/components/CclButton/CclButton';
22
23
  import { Checkbox } from 'semantic-ui-react';
23
24
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
24
- import { Select } from 'semantic-ui-react';
25
+ import { Select, Segment } from 'semantic-ui-react';
25
26
  import { cleanDuplicatesEntries } from '@eeacms/volto-clms-utils/utils';
26
27
  import { getAvailableConversion } from './conversion';
27
28
  import useCartState from '@eeacms/volto-clms-utils/cart/useCartState';
@@ -32,6 +33,7 @@ const CLMSCartContent = (props) => {
32
33
  const cart = useSelector((state) => state.cart_items.items);
33
34
  const { removeCartItem, removeCartItems } = useCartState();
34
35
  const [cartSelection, setCartSelection] = useState([]);
36
+ const [loadingTable, setLoadingTable] = useState(false);
35
37
  const post_download_in_progress = useSelector(
36
38
  (state) => state.downloadtool.post_download_in_progress,
37
39
  );
@@ -126,10 +128,20 @@ const CLMSCartContent = (props) => {
126
128
  };
127
129
 
128
130
  function startDownloading() {
131
+ setLoadingTable(true);
129
132
  let selectedItems = getSelectedCartItems();
130
133
  const body = getDownloadToolPostBody(selectedItems);
131
134
  const unique_ids = selectedItems.map((item) => item.unique_id);
132
- dispatch(postDownloadtool(body, unique_ids));
135
+ dispatch(postDownloadtool(body, unique_ids)).then(() => {
136
+ setLoadingTable(false);
137
+ toast.success(
138
+ <Toast
139
+ success
140
+ autoClose={5000}
141
+ title={'Selected file(s) added to the downloading process.'}
142
+ />,
143
+ );
144
+ });
133
145
  }
134
146
  const setProjectionValue = (unique_id, value) => {
135
147
  const objIndex = cartItems.findIndex((obj) => obj.unique_id === unique_id);
@@ -140,148 +152,158 @@ const CLMSCartContent = (props) => {
140
152
  <>
141
153
  {cartItems?.length !== 0 ? (
142
154
  <div className="custom-table cart-table">
143
- <h2>My cart</h2>
144
- <table>
145
- <thead>
146
- <tr>
147
- <th className="table-th-warning"></th>
148
- <th className="table-th-checkbox">
149
- <div className="ccl-form">
150
- <div className="ccl-form-group">
151
- <Checkbox
152
- onChange={(e, data) => selectAllCart(data.checked)}
153
- checked={
154
- cartItems
155
- ? cartItems
156
- .filter(
157
- (item) => item.task_in_progress === false,
158
- )
159
- .map((item, key) => item.unique_id)
160
- .every(function (val) {
161
- return cartSelection.indexOf(val) !== -1;
162
- })
163
- : false
164
- }
165
- />
155
+ <Segment basic loading={loadingTable}>
156
+ <h2>My cart</h2>
157
+ <table>
158
+ <thead>
159
+ <tr>
160
+ <th className="table-th-warning"></th>
161
+ <th className="table-th-checkbox">
162
+ <div className="ccl-form">
163
+ <div className="ccl-form-group">
164
+ <Checkbox
165
+ onChange={(e, data) => selectAllCart(data.checked)}
166
+ checked={
167
+ cartItems
168
+ ? cartItems
169
+ .filter(
170
+ (item) => item.task_in_progress === false,
171
+ )
172
+ .map((item, key) => item.unique_id)
173
+ .every(function (val) {
174
+ return cartSelection.indexOf(val) !== -1;
175
+ })
176
+ : false
177
+ }
178
+ />
179
+ </div>
166
180
  </div>
167
- </div>
168
- </th>
169
- <th>Name</th>
170
- <th>Source</th>
171
- <th>Area</th>
172
- <th>Type</th>
173
- <th>Format</th>
174
- <th>Projection</th>
175
- <th>Version</th>
176
- <th>Size</th>
177
- <th></th>
178
- </tr>
179
- </thead>
180
- <tbody>
181
- {cartItems &&
182
- cartItems.map((item, key) => (
183
- <tr
184
- key={key}
185
- style={
186
- item.task_in_progress
187
- ? { opacity: 0.5, backgroundColor: '#f5f5f5' }
188
- : {}
189
- }
190
- >
191
- <td className="table-td-warning hidden-warning">
192
- {!!item.warning && (
181
+ </th>
182
+ <th>Name</th>
183
+ <th>Source</th>
184
+ <th>Area</th>
185
+ <th>Type</th>
186
+ <th>Format</th>
187
+ <th>Projection</th>
188
+ <th>Version</th>
189
+ <th>Size</th>
190
+ <th></th>
191
+ </tr>
192
+ </thead>
193
+ <tbody>
194
+ {cartItems &&
195
+ cartItems.map((item, key) => (
196
+ <tr
197
+ key={key}
198
+ style={
199
+ item.task_in_progress
200
+ ? { opacity: 0.5, backgroundColor: '#f5f5f5' }
201
+ : {}
202
+ }
203
+ >
204
+ <td className="table-td-warning hidden-warning">
205
+ {!!item.warning && (
206
+ <span
207
+ className="info-icon"
208
+ tooltip={item.warning}
209
+ direction="up"
210
+ >
211
+ <FontAwesomeIcon
212
+ icon={['fas', 'exclamation-triangle']}
213
+ />
214
+ </span>
215
+ )}
216
+ </td>
217
+ <td className="table-td-checkbox">
218
+ <div className="ccl-form">
219
+ <div className="ccl-form-group">
220
+ <Checkbox
221
+ onChange={(e, data) =>
222
+ selectCart(item.unique_id, data.checked)
223
+ }
224
+ checked={cartSelection.includes(item.unique_id)}
225
+ disabled={item.task_in_progress}
226
+ />
227
+ </div>
228
+ </div>
229
+ </td>
230
+ <td>{item.name || '-'}</td>
231
+ <td>{item.source || '-'}</td>
232
+ <td>
233
+ {item.area?.type === 'polygon'
234
+ ? 'Bounding Box'
235
+ : item.area?.type === 'nuts'
236
+ ? 'NUTS ID: ' + item.area.value
237
+ : '-'}
238
+ </td>
239
+ <td>
193
240
  <span
194
- className="info-icon"
195
- tooltip={item.warning}
196
- direction="up"
241
+ className={'tag tag-' + item?.type?.toLowerCase()}
197
242
  >
198
- <FontAwesomeIcon
199
- icon={['fas', 'exclamation-triangle']}
200
- />
243
+ {item.type || '-'}
201
244
  </span>
202
- )}
203
- </td>
204
- <td className="table-td-checkbox">
205
- <div className="ccl-form">
206
- <div className="ccl-form-group">
207
- <Checkbox
208
- onChange={(e, data) =>
209
- selectCart(item.unique_id, data.checked)
210
- }
211
- checked={cartSelection.includes(item.unique_id)}
212
- disabled={item.task_in_progress}
245
+ </td>
246
+ <td className="table-td-format">
247
+ {!item.file_id ? (
248
+ <Select
249
+ placeholder="Select format"
250
+ value={item.format?.token || item.format}
251
+ options={getAvailableConversion(
252
+ formatConversionTable,
253
+ item.format?.token || item.format,
254
+ )}
255
+ onChange={(e, data) => {
256
+ const objIndex = cartItems.findIndex(
257
+ (obj) => obj.unique_id === item.unique_id,
258
+ );
259
+ cartItems[objIndex].format = data.value;
260
+ setCartItems([...cartItems]);
261
+ }}
213
262
  />
214
- </div>
215
- </div>
216
- </td>
217
- <td>{item.name || '-'}</td>
218
- <td>{item.source || '-'}</td>
219
- <td>{item.area?.type || '-'}</td>
220
- <td>
221
- <span className={'tag tag-' + item?.type?.toLowerCase()}>
222
- {item.type || '-'}
223
- </span>
224
- </td>
225
- <td className="table-td-format">
226
- {!item.file_id ? (
227
- <Select
228
- placeholder="Select format"
229
- value={item.format?.token || item.format}
230
- options={getAvailableConversion(
231
- formatConversionTable,
232
- item.format?.token || item.format,
233
- )}
234
- onChange={(e, data) => {
235
- const objIndex = cartItems.findIndex(
236
- (obj) => obj.unique_id === item.unique_id,
237
- );
238
- cartItems[objIndex].format = data.value;
239
- setCartItems([...cartItems]);
240
- }}
241
- />
242
- ) : (
243
- item.format?.token || item.format
244
- )}
245
- </td>
246
- <td className="table-td-projections">
247
- {!item.file_id ? (
248
- <Select
249
- placeholder="Select projection"
250
- value={item.projection}
251
- options={projections.map((item) => {
252
- return {
253
- key: item,
254
- value: item,
255
- text: item,
256
- };
257
- })}
258
- onChange={(e, data) => {
259
- setProjectionValue(item.unique_id, data.value);
260
- }}
261
- />
262
- ) : (
263
- item.projection
264
- )}
265
- </td>
266
- <td>{item.version}</td>
267
- <td>{item.size}</td>
268
- <td>
269
- {item.task_in_progress ? (
270
- <FontAwesomeIcon icon="spinner" spin />
271
- ) : (
272
- <FontAwesomeIcon
273
- icon={['fas', 'trash']}
274
- style={{ cursor: 'pointer' }}
275
- onClick={() => {
276
- removeCartItem(item.unique_id);
277
- }}
278
- />
279
- )}
280
- </td>
281
- </tr>
282
- ))}
283
- </tbody>
284
- </table>
263
+ ) : (
264
+ item.format?.token || item.format
265
+ )}
266
+ </td>
267
+ <td className="table-td-projections">
268
+ {!item.file_id ? (
269
+ <Select
270
+ placeholder="Select projection"
271
+ value={item.projection}
272
+ options={projections.map((item) => {
273
+ return {
274
+ key: item,
275
+ value: item,
276
+ text: item,
277
+ };
278
+ })}
279
+ onChange={(e, data) => {
280
+ setProjectionValue(item.unique_id, data.value);
281
+ }}
282
+ />
283
+ ) : (
284
+ item.projection
285
+ )}
286
+ </td>
287
+ <td>{item.version}</td>
288
+ <td>{item.size}</td>
289
+ <td>
290
+ {item.task_in_progress ? (
291
+ <FontAwesomeIcon icon="spinner" spin />
292
+ ) : (
293
+ <FontAwesomeIcon
294
+ icon={['fas', 'trash']}
295
+ style={{ cursor: 'pointer' }}
296
+ onClick={() => {
297
+ removeCartItem(item.unique_id);
298
+ }}
299
+ />
300
+ )}
301
+ </td>
302
+ </tr>
303
+ ))}
304
+ </tbody>
305
+ </table>
306
+ </Segment>
285
307
  </div>
286
308
  ) : (
287
309
  <h2 style={{ textAlign: 'center' }}>Empty cart</h2>
@@ -8,10 +8,11 @@ import React, { useEffect, useState } from 'react';
8
8
  import { defineMessages, useIntl } from 'react-intl';
9
9
  import { getDatasetsByUid, getExtraBreadcrumbItems } from '../../actions';
10
10
  import { useDispatch, useSelector } from 'react-redux';
11
+ import { Link } from 'react-router-dom';
11
12
 
12
13
  import { CART_SESSION_KEY } from '@eeacms/volto-clms-utils/cart/useCartState';
13
14
  import CLMSCartContent from './CLMSCartContent';
14
- import CLMSTasksInProgress from './CLMSTasksInProgress';
15
+ // import CLMSTasksInProgress from './CLMSTasksInProgress';
15
16
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
16
17
  import { FormattedMessage } from 'react-intl';
17
18
  import { Helmet } from '@plone/volto/helpers';
@@ -20,10 +21,11 @@ import useCartState from '@eeacms/volto-clms-utils/cart/useCartState';
20
21
  const CLMSDownloadCartView = (props) => {
21
22
  const dispatch = useDispatch();
22
23
  const user_id = useSelector((state) => state.users.user.id);
24
+ const locale = useSelector((state) => state.intl?.locale);
23
25
  const [localSessionCart, setLocalSessionCart] = useState([]);
24
- const download_in_progress = useSelector(
25
- (state) => state.downloadtool.download_in_progress,
26
- );
26
+ // const download_in_progress = useSelector(
27
+ // (state) => state.downloadtool.download_in_progress,
28
+ // );
27
29
  const { isLoggedIn } = useCartState();
28
30
 
29
31
  const { formatMessage } = useIntl();
@@ -59,34 +61,36 @@ const CLMSDownloadCartView = (props) => {
59
61
 
60
62
  useEffect(() => {
61
63
  let localsessionUidsList = [];
62
- let downloadInProgressUidsList = [];
64
+ // let downloadInProgressUidsList = [];
63
65
  if (localSessionCart?.length !== 0) {
64
66
  localsessionUidsList = [
65
67
  ...new Set(localSessionCart.map((item) => item.UID || item.id)),
66
68
  ];
67
69
  }
68
- let progress_keys = Object.keys(download_in_progress);
69
- if (progress_keys?.length !== 0) {
70
- downloadInProgressUidsList = [
71
- ...new Set(
72
- progress_keys
73
- .map((taskID) =>
74
- download_in_progress[taskID].Datasets.map(
75
- (dataset) => dataset.DatasetID,
76
- ),
77
- )
78
- .reduce((elem1, elem2) => elem1.concat(elem2)),
79
- ),
80
- ];
81
- }
70
+ // let progress_keys = Object.keys(download_in_progress);
71
+ // if (progress_keys?.length !== 0) {
72
+ // downloadInProgressUidsList = [
73
+ // ...new Set(
74
+ // progress_keys
75
+ // .map((taskID) =>
76
+ // download_in_progress[taskID].Datasets.map(
77
+ // (dataset) => dataset.DatasetID,
78
+ // ),
79
+ // )
80
+ // .reduce((elem1, elem2) => elem1.concat(elem2)),
81
+ // ),
82
+ // ];
83
+ // }
82
84
  let uidsList = [
83
- ...new Set(localsessionUidsList.concat(downloadInProgressUidsList)),
85
+ ...new Set(localsessionUidsList),
86
+ // ...new Set(localsessionUidsList.concat(downloadInProgressUidsList)),
84
87
  ];
85
88
  if (uidsList.length > 0) {
86
89
  dispatch(getDatasetsByUid(uidsList));
87
90
  }
88
91
  // eslint-disable-next-line react-hooks/exhaustive-deps
89
- }, [download_in_progress, localSessionCart, dispatch]);
92
+ }, [localSessionCart, dispatch]);
93
+ // }, [download_in_progress, localSessionCart, dispatch]);
90
94
 
91
95
  return (
92
96
  <>
@@ -134,12 +138,21 @@ const CLMSDownloadCartView = (props) => {
134
138
  downloading the datasets
135
139
  </p>
136
140
  <ul>
137
- <li>May be can include a link to somewhere</li>
138
- <li>Or an informative text</li>
141
+ <li>
142
+ Select the files you want to download and click the button
143
+ 'Start downloading' to start with the download process.
144
+ </li>
145
+ <li>
146
+ You can visit the{' '}
147
+ <Link to={`/${locale}/cart-downloads`}>
148
+ downloading process page
149
+ </Link>
150
+ .{' '}
151
+ </li>
139
152
  </ul>
140
153
  </div>
141
154
  </div>
142
- <CLMSTasksInProgress />
155
+ {/* <CLMSTasksInProgress /> */}
143
156
  <CLMSCartContent localSessionCart={localSessionCart} />
144
157
  </div>
145
158
  </>
@@ -0,0 +1,139 @@
1
+ /**
2
+ * CLMSDownloadsView.
3
+ * @module components/CLMSDownloadsView/CLMSDownloadsView
4
+ */
5
+
6
+ import { Forbidden, Unauthorized } from '@plone/volto/components';
7
+ import React, { useEffect } from 'react';
8
+ import { defineMessages, useIntl } from 'react-intl';
9
+ import { getDatasetsByUid, getExtraBreadcrumbItems } from '../../actions';
10
+ import { useDispatch, useSelector } from 'react-redux';
11
+
12
+ import CLMSTasksInProgress from './CLMSTasksInProgress';
13
+ import { FormattedMessage } from 'react-intl';
14
+ import { Helmet } from '@plone/volto/helpers';
15
+ import useCartState from '@eeacms/volto-clms-utils/cart/useCartState';
16
+
17
+ const CLMSDownloadsView = (props) => {
18
+ const dispatch = useDispatch();
19
+ const downloadtool = useSelector((state) => state.downloadtool);
20
+ const { isLoggedIn } = useCartState();
21
+
22
+ const { formatMessage } = useIntl();
23
+ const messages = defineMessages({
24
+ CartDownloads: {
25
+ id: 'Cart Downloads',
26
+ defaultMessage: 'Cart Downloads',
27
+ },
28
+ });
29
+
30
+ useEffect(() => {
31
+ dispatch(
32
+ getExtraBreadcrumbItems([
33
+ {
34
+ title: formatMessage(messages.CartDownloads),
35
+ pathname: props.location.pathname,
36
+ },
37
+ ]),
38
+ );
39
+ // returned function will be called on component unmount
40
+ return () => {
41
+ dispatch(getExtraBreadcrumbItems([]));
42
+ };
43
+ }, [
44
+ dispatch,
45
+ formatMessage,
46
+ messages.CartDownloads,
47
+ props.location.pathname,
48
+ ]);
49
+
50
+ function getUIDList(download_data) {
51
+ let uidList = [];
52
+ let data_keys = Object.keys(download_data);
53
+ if (data_keys?.length !== 0) {
54
+ uidList = [
55
+ ...new Set(
56
+ data_keys
57
+ .map((taskID) =>
58
+ download_data[taskID].Datasets.map(
59
+ (dataset) => dataset.DatasetID,
60
+ ),
61
+ )
62
+ .reduce((elem1, elem2) => elem1.concat(elem2)),
63
+ ),
64
+ ];
65
+ }
66
+ return uidList;
67
+ }
68
+
69
+ useEffect(() => {
70
+ if (
71
+ downloadtool?.download_in_progress &&
72
+ downloadtool?.download_finished_ok &&
73
+ downloadtool?.download_finished_nok &&
74
+ downloadtool?.download_rejected
75
+ ) {
76
+ let downloadInProgressUidsList = getUIDList(
77
+ downloadtool?.download_in_progress,
78
+ );
79
+ // let downloadCancelledUidsList = getUIDList(
80
+ // downloadtool?.download_cancelled,
81
+ // );
82
+ let finishedOKUidsList = getUIDList(downloadtool?.download_finished_ok);
83
+ let finishedNOKUidsList = getUIDList(downloadtool?.download_finished_nok);
84
+ let rejectedUidsList = getUIDList(downloadtool?.download_rejected);
85
+ let uidsList = [
86
+ ...new Set(
87
+ rejectedUidsList.concat(
88
+ finishedNOKUidsList.concat(
89
+ finishedOKUidsList.concat(downloadInProgressUidsList),
90
+ ),
91
+ ),
92
+ ),
93
+ ];
94
+ if (uidsList.length > 0) {
95
+ dispatch(getDatasetsByUid(uidsList));
96
+ }
97
+ }
98
+ // eslint-disable-next-line react-hooks/exhaustive-deps
99
+ }, [downloadtool, dispatch]);
100
+
101
+ return (
102
+ <>
103
+ <Helmet title={formatMessage(messages.CartDownloads)} />
104
+ <div className="ui container">
105
+ {!isLoggedIn && (
106
+ <>
107
+ {props.token ? (
108
+ <Forbidden
109
+ pathname={props.pathname}
110
+ staticContext={props.staticContext}
111
+ />
112
+ ) : (
113
+ <Unauthorized
114
+ pathname={props.pathname}
115
+ staticContext={props.staticContext}
116
+ />
117
+ )}
118
+ </>
119
+ )}
120
+ {isLoggedIn && (
121
+ <>
122
+ <h1 className="page-title">
123
+ <FormattedMessage
124
+ id="Cart Downloads"
125
+ defaultMessage="Cart Downloads"
126
+ />
127
+ </h1>
128
+ <div className="ccl-container">
129
+ <CLMSTasksInProgress />
130
+ </div>
131
+ <hr />
132
+ </>
133
+ )}
134
+ </div>
135
+ </>
136
+ );
137
+ };
138
+
139
+ export default CLMSDownloadsView;
@@ -0,0 +1,202 @@
1
+ /**
2
+ * CLMSInProgressTask container.
3
+ * @module components/CLMSInProgressTask/CLMSInProgressTask
4
+ */
5
+
6
+ // import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
7
+ import { Grid } from 'semantic-ui-react';
8
+ import React, { useEffect, useState } from 'react';
9
+ import { deleteDownloadtool, getDownloadtool } from '../../actions';
10
+ import { useDispatch, useSelector } from 'react-redux';
11
+ import FileCard from './FileCard';
12
+ import { FormattedMessage } from 'react-intl';
13
+
14
+ const CLMSTasksInProgress = (props) => {
15
+ const dispatch = useDispatch();
16
+ const [taskInProgress, setTaskInProgress] = useState([]);
17
+ // const [cancelledTasks, setCancelledTasks] = useState([]);
18
+ const [finishedOKTasks, setFinishedOKTasks] = useState([]);
19
+ const [finishedNOKTasks, setFinishedNOKTasks] = useState([]);
20
+ const [rejectedTasks, setRejectedTasks] = useState([]);
21
+ const [showDeleteTaskLoading, setShowDeleteTaskLoading] = useState(false);
22
+ const downloadtool = useSelector((state) => state.downloadtool);
23
+
24
+ const user_id = useSelector((state) => state.users.user.id);
25
+ const datasets = useSelector((state) => state.datasetsByUid.datasets.items);
26
+
27
+ useEffect(() => {
28
+ dispatch(getDownloadtool());
29
+ }, [dispatch]);
30
+
31
+ useEffect(() => {
32
+ setTaskInProgress(downloadtool.download_in_progress);
33
+ // setCancelledTasks(downloadtool.download_cancelled);
34
+ setFinishedOKTasks(downloadtool.download_finished_ok);
35
+ setFinishedNOKTasks(downloadtool.download_finished_nok);
36
+ setRejectedTasks(downloadtool.download_rejected);
37
+ }, [downloadtool]);
38
+
39
+ useEffect(() => {
40
+ if (datasets?.length > 0) {
41
+ addDatasetName(taskInProgress, setTaskInProgress);
42
+ addDatasetName(finishedOKTasks, setFinishedOKTasks);
43
+ addDatasetName(finishedNOKTasks, setFinishedNOKTasks);
44
+ addDatasetName(rejectedTasks, setRejectedTasks);
45
+ }
46
+ // eslint-disable-next-line react-hooks/exhaustive-deps
47
+ }, [datasets]);
48
+
49
+ function addDatasetName(data, setter) {
50
+ let intermediate = [...data];
51
+ intermediate.forEach((task) => {
52
+ task.Datasets.forEach((dataset) => {
53
+ const requestedItem = datasets.find(
54
+ (requestedItem) => requestedItem.UID === dataset.DatasetID,
55
+ );
56
+ if (requestedItem) {
57
+ dataset.name = requestedItem.title;
58
+ }
59
+ });
60
+ });
61
+ setter(intermediate);
62
+ }
63
+ const deleteTaskInProgress = (task_id) => {
64
+ setShowDeleteTaskLoading(task_id);
65
+ dispatch(deleteDownloadtool(task_id));
66
+ setTimeout(() => {
67
+ dispatch(getDownloadtool(user_id));
68
+ setShowDeleteTaskLoading(false);
69
+ }, 1000); // We need delete response to check if remove_task request is completed successfully
70
+ };
71
+ return (
72
+ <Grid columns={1} stackable padded="vertically">
73
+ <Grid.Column>
74
+ <h2>
75
+ <FormattedMessage
76
+ id="Task In Progress"
77
+ defaultMessage="Task In Progress"
78
+ />
79
+ </h2>
80
+ {taskInProgress?.length !== 0 ? (
81
+ <Grid columns={2}>
82
+ {taskInProgress?.length > 0 &&
83
+ taskInProgress.map((item, key) => (
84
+ <Grid.Column key={key}>
85
+ <FileCard
86
+ item={item}
87
+ showDeleteTaskLoading={showDeleteTaskLoading}
88
+ deleteTaskInProgress={deleteTaskInProgress}
89
+ />
90
+ </Grid.Column>
91
+ ))}
92
+ </Grid>
93
+ ) : (
94
+ <p>
95
+ <FormattedMessage
96
+ id="There is no task in progress"
97
+ defaultMessage="There is no task in progress"
98
+ />
99
+ </p>
100
+ )}
101
+ {/* <h2>Cancelled Tasks</h2>
102
+ {cancelledTasks?.length > 0 &&
103
+ cancelledTasks.map((item, key) => (
104
+ <FileCard
105
+ item={item}
106
+ key={key}
107
+ showDeleteTaskLoading={showDeleteTaskLoading}
108
+ deleteTaskInProgress={deleteTaskInProgress}
109
+ />
110
+ ))} */}
111
+ </Grid.Column>
112
+ <Grid.Column>
113
+ <h2>
114
+ <FormattedMessage
115
+ id="Finished Correctly"
116
+ defaultMessage="Finished Correctly"
117
+ />
118
+ </h2>
119
+ {finishedOKTasks?.length !== 0 ? (
120
+ <Grid columns={2}>
121
+ {finishedOKTasks?.length > 0 &&
122
+ finishedOKTasks.map((item, key) => (
123
+ <Grid.Column key={key}>
124
+ <FileCard
125
+ item={item}
126
+ key={key}
127
+ showDeleteTaskLoading={showDeleteTaskLoading}
128
+ deleteTaskInProgress={deleteTaskInProgress}
129
+ />
130
+ </Grid.Column>
131
+ ))}
132
+ </Grid>
133
+ ) : (
134
+ <p>
135
+ <FormattedMessage
136
+ id="There is no correctly finished task"
137
+ defaultMessage="There is no correctly finished task"
138
+ />
139
+ </p>
140
+ )}
141
+ </Grid.Column>
142
+ <Grid.Column>
143
+ <h2>
144
+ <FormattedMessage
145
+ id="Finished Not Correctly"
146
+ defaultMessage="Finished Not Correctly"
147
+ />
148
+ </h2>
149
+ {finishedNOKTasks?.length !== 0 ? (
150
+ <Grid columns={2}>
151
+ {finishedNOKTasks?.length > 0 &&
152
+ finishedNOKTasks.map((item, key) => (
153
+ <Grid.Column key={key}>
154
+ <FileCard
155
+ item={item}
156
+ key={key}
157
+ showDeleteTaskLoading={showDeleteTaskLoading}
158
+ deleteTaskInProgress={deleteTaskInProgress}
159
+ />
160
+ </Grid.Column>
161
+ ))}
162
+ </Grid>
163
+ ) : (
164
+ <p>
165
+ <FormattedMessage
166
+ id="There is no incorrectly finished task"
167
+ defaultMessage="There is no incorrectly finished task"
168
+ />
169
+ </p>
170
+ )}
171
+ </Grid.Column>
172
+ <Grid.Column>
173
+ <h2>
174
+ <FormattedMessage id="Rejected" defaultMessage="Rejected" />
175
+ </h2>
176
+ {rejectedTasks?.length !== 0 ? (
177
+ <Grid columns={2}>
178
+ {rejectedTasks?.length > 0 &&
179
+ rejectedTasks.map((item, key) => (
180
+ <Grid.Column key={key}>
181
+ <FileCard
182
+ item={item}
183
+ key={key}
184
+ showDeleteTaskLoading={showDeleteTaskLoading}
185
+ deleteTaskInProgress={deleteTaskInProgress}
186
+ />
187
+ </Grid.Column>
188
+ ))}
189
+ </Grid>
190
+ ) : (
191
+ <p>
192
+ <FormattedMessage
193
+ id="There is no rejected task"
194
+ defaultMessage="There is no rejected task"
195
+ />
196
+ </p>
197
+ )}
198
+ </Grid.Column>
199
+ </Grid>
200
+ );
201
+ };
202
+ export default CLMSTasksInProgress;
@@ -0,0 +1,194 @@
1
+ /**
2
+ * FileCard container.
3
+ * @module components/CLMSDownloadsView/FileCard
4
+ */
5
+
6
+ import { Loader, Popup, Segment, Grid, Header } from 'semantic-ui-react';
7
+ import React from 'react';
8
+
9
+ import { Icon } from '@plone/volto/components';
10
+ // import cancelledSVG from '@plone/volto/icons/spam.svg';
11
+ import removeSVG from '@plone/volto/icons/delete.svg';
12
+ import packSVG from '@plone/volto/icons/pack.svg';
13
+ import errorSVG from '@plone/volto/icons/error.svg';
14
+ import alertSVG from '@plone/volto/icons/alert.svg';
15
+ import { defineMessages, useIntl } from 'react-intl';
16
+
17
+ const FileCard = (props) => {
18
+ const { item, showDeleteTaskLoading, deleteTaskInProgress } = props;
19
+ const { formatMessage } = useIntl();
20
+ if (item?.FinalizationDateTime) {
21
+ var FinalizationDate = new Date(Date.parse(item?.FinalizationDateTime));
22
+ var today = new Date();
23
+ var daysDiff = Math.floor(
24
+ (today.getTime() - FinalizationDate.getTime()) / (1000 * 3600 * 24),
25
+ );
26
+ }
27
+ const messages = defineMessages({
28
+ PrePackaged: {
29
+ id: 'Pre-packaged',
30
+ defaultMessage: 'Pre-packaged',
31
+ },
32
+ Download: {
33
+ id: 'Download file',
34
+ defaultMessage: 'Download file',
35
+ },
36
+ });
37
+ return (
38
+ <Segment color="olive">
39
+ <Grid
40
+ divided
41
+ centered
42
+ columns={item?.Status !== 'In_progress' ? 2 : 3}
43
+ padded
44
+ >
45
+ <Grid.Row>
46
+ <Grid.Column verticalAlign="middle" textAlign="center" width={3}>
47
+ {item?.Status === 'In_progress' && (
48
+ <Popup
49
+ content="In progress"
50
+ size="small"
51
+ trigger={<Loader active inline indeterminate size="big" />}
52
+ />
53
+ )}
54
+ {/* {item?.Status === 'Cancelled' && (
55
+ <Popup
56
+ content="Cancelled"
57
+ size="small"
58
+ trigger={
59
+ <Icon
60
+ name={cancelledSVG}
61
+ size={45}
62
+ color="#e40166"
63
+ title={'Cancelled'}
64
+ />
65
+ }
66
+ />
67
+ )} */}
68
+ {item?.Status === 'Finished_ok' && (
69
+ <Popup
70
+ content="Finished correctly"
71
+ size="small"
72
+ trigger={
73
+ <Icon
74
+ name={packSVG}
75
+ size={75}
76
+ color="#a0b128"
77
+ title={'Finished correctly'}
78
+ />
79
+ }
80
+ />
81
+ )}
82
+ {item?.Status === 'Finished_nok' && (
83
+ <Popup
84
+ content="Finished with errors"
85
+ size="small"
86
+ trigger={
87
+ <Icon
88
+ name={errorSVG}
89
+ size={75}
90
+ color="#e40166"
91
+ title={'Finished with errors'}
92
+ />
93
+ }
94
+ />
95
+ )}
96
+ {item?.Status === 'Rejected' && (
97
+ <Popup
98
+ content="Rejected download"
99
+ size="small"
100
+ trigger={
101
+ <Icon
102
+ name={alertSVG}
103
+ size={75}
104
+ color="#e40166"
105
+ title={'Rejected download'}
106
+ />
107
+ }
108
+ />
109
+ )}
110
+ </Grid.Column>
111
+ <Grid.Column width={item?.Status === 'In_progress' ? 7 : 9}>
112
+ <Header>{`Task ID: ${item?.TaskID}`}</Header>
113
+ {item?.Datasets.length === 1 && (
114
+ <p>{`${item?.Datasets[0].name} - ${
115
+ item.Datasets[0]['OutputFormat']
116
+ ? item.Datasets[0]['OutputFormat']
117
+ : formatMessage(messages.PrePackaged)
118
+ }`}</p>
119
+ )}
120
+ {item?.Datasets.length > 1 && (
121
+ <ul>
122
+ {item?.Datasets.map((dataset) => (
123
+ <li>
124
+ {`${dataset['name']} -
125
+ ${
126
+ dataset['OutputFormat']
127
+ ? dataset['OutputFormat']
128
+ : formatMessage(messages.PrePackaged)
129
+ }`}
130
+ </li>
131
+ ))}
132
+ </ul>
133
+ )}
134
+ {item?.Status === 'Finished_ok' && (
135
+ <>
136
+ {item?.FileSize && <p>{`${item.FileSize} MB`}</p>}
137
+ {item?.DownloadURL && (
138
+ <a href={item.DownloadURL} target="_blank" rel="noreferrer">
139
+ {formatMessage(messages.Download)}
140
+ </a>
141
+ )}
142
+ {item?.FinalizationDateTime &&
143
+ ` | Expires in ${10 - daysDiff} days`}
144
+ </>
145
+ )}
146
+ </Grid.Column>
147
+ {item?.Status === 'In_progress' && (
148
+ <Grid.Column width={2} verticalAlign="middle" textAlign="center">
149
+ {showDeleteTaskLoading === item?.TaskID ? (
150
+ <Loader
151
+ active
152
+ inline
153
+ indeterminate
154
+ size="small"
155
+ className="red-loader"
156
+ />
157
+ ) : (
158
+ <Popup
159
+ content="Remove in progress task"
160
+ size="small"
161
+ trigger={
162
+ <button
163
+ onClick={() => {
164
+ deleteTaskInProgress(item?.TaskID);
165
+ }}
166
+ style={{
167
+ backgroundColor: 'transparent',
168
+ color: 'inherit',
169
+ border: 'none',
170
+ padding: 0,
171
+ font: 'inherit',
172
+ cursor: 'pointer',
173
+ outline: 'inherit',
174
+ }}
175
+ >
176
+ <Icon
177
+ name={removeSVG}
178
+ size={40}
179
+ color="#e40166"
180
+ title={'Remove in progress task'}
181
+ />
182
+ </button>
183
+ }
184
+ />
185
+ )}
186
+ </Grid.Column>
187
+ )}
188
+ </Grid.Row>
189
+ </Grid>
190
+ </Segment>
191
+ );
192
+ };
193
+
194
+ export default FileCard;
@@ -131,7 +131,7 @@ export const CLMSMeetingView = (props) => {
131
131
  });
132
132
  };
133
133
  var formErrorMessagesList = [];
134
- !content.anonymous_registration_form.published &&
134
+ !content.anonymous_registration_form?.published &&
135
135
  formErrorMessagesList.push(
136
136
  intl.formatMessage(messages.form_is_not_published),
137
137
  );
@@ -334,8 +334,8 @@ export const CLMSMeetingView = (props) => {
334
334
  {content.allow_anonymous_registration ? (
335
335
  <>
336
336
  {content.anonymous_registration_form?.published &&
337
- content.anonymous_registration_form.email &&
338
- content.anonymous_registration_form.fullname && (
337
+ content.anonymous_registration_form?.email &&
338
+ content.anonymous_registration_form?.fullname && (
339
339
  <CclButton url={content.anonymous_registration_form?.url}>
340
340
  <FormattedMessage
341
341
  id="Register to this meeting"
package/src/index.js CHANGED
@@ -9,6 +9,7 @@ import BoundingWidget from './components/Widgets/BoundingWidget';
9
9
  // VIEWS IMPORTS
10
10
  import CLMSDatasetDetailView from '@eeacms/volto-clms-theme/components/CLMSDatasetDetailView/CLMSDatasetDetailView';
11
11
  import CLMSDownloadCartView from './components/CLMSDownloadCartView/CLMSDownloadCartView';
12
+ import CLMSDownloadsView from './components/CLMSDownloadsView/CLMSDownloadsView';
12
13
  import SubscriptionView from './components/CLMSSubscriptionView/SubscriptionView';
13
14
  import ConfirmSubscriptionView from './components/CLMSSubscriptionView/ConfirmSubscriptionView';
14
15
  import CLMSDownloadableFileView from '@eeacms/volto-clms-theme/components/CLMSDownloadableFileView/CLMSDownloadableFileView';
@@ -175,6 +176,10 @@ const applyConfig = (config) => {
175
176
  path: '/**/cart',
176
177
  component: CLMSDownloadCartView,
177
178
  },
179
+ {
180
+ path: '/**/cart-downloads',
181
+ component: CLMSDownloadsView,
182
+ },
178
183
  {
179
184
  path: `/(${config.settings.supportedLanguages.join('|')})/sitemap`,
180
185
  component: Sitemap,
@@ -40,12 +40,36 @@ export const downloadtoolReducer = (state = getInitialState, action = {}) => {
40
40
  };
41
41
 
42
42
  case `${GET_DOWNLOADTOOL}_SUCCESS`:
43
+ let tasks_keys = Object.keys(action.result);
44
+ let tasks_array = [];
45
+ tasks_keys.forEach((progress_key) => {
46
+ tasks_array.push({
47
+ ...action.result[progress_key],
48
+ TaskID: progress_key,
49
+ });
50
+ });
51
+ // var cancelled = tasks_array.filter((task) => task.Status === 'Cancelled');
52
+ var in_progress = tasks_array.filter(
53
+ (task) => task.Status === 'In_progress',
54
+ );
55
+ var finished_ok = tasks_array.filter(
56
+ (task) => task.Status === 'Finished_ok',
57
+ );
58
+ var finished_nok = tasks_array.filter(
59
+ (task) => task.Status === 'Finished_nok',
60
+ );
61
+ var rejected = tasks_array.filter((task) => task.Status === 'Rejected');
62
+
43
63
  return {
44
64
  ...state,
45
65
  error: null,
46
66
  loaded: true,
47
67
  loading: false,
48
- download_in_progress: action.result,
68
+ // download_cancelled: cancelled,
69
+ download_in_progress: in_progress,
70
+ download_finished_ok: finished_ok,
71
+ download_finished_nok: finished_nok,
72
+ download_rejected: rejected,
49
73
  };
50
74
  case `${POST_DOWNLOADTOOL}_PENDING`:
51
75
  return {