@eeacms/volto-clms-theme 1.0.31 → 1.0.32

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,8 +4,37 @@ 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.32](https://github.com/eea/volto-clms-theme/compare/1.0.31...1.0.32)
8
+
9
+ - Downloadtool [`#99`](https://github.com/eea/volto-clms-theme/pull/99)
10
+ - Card block style fix [`#98`](https://github.com/eea/volto-clms-theme/pull/98)
11
+ - top main menu fix [`#97`](https://github.com/eea/volto-clms-theme/pull/97)
12
+ - Use cases carousel fix [`#96`](https://github.com/eea/volto-clms-theme/pull/96)
13
+ - specify form label color only for footer [`d2f1bff`](https://github.com/eea/volto-clms-theme/commit/d2f1bffd10869273e61d6b79ae6513571a417a6f)
14
+ - arcgis block version [`a32ee91`](https://github.com/eea/volto-clms-theme/commit/a32ee918271a131024e34560562795e986998600)
15
+ - optimized downloadtool reducer [`8e54177`](https://github.com/eea/volto-clms-theme/commit/8e541777362d2bde826950afaaba1034ecf4e8e6)
16
+ - card block style fix [`c5227bb`](https://github.com/eea/volto-clms-theme/commit/c5227bbd4ec9120c76fd316b425fb5fbbd56bf96)
17
+ - card block style fix [`c551081`](https://github.com/eea/volto-clms-theme/commit/c55108137230c2a1d620662bb9acd4828e98675c)
18
+ - Buttons popups and titles [`c4c71a0`](https://github.com/eea/volto-clms-theme/commit/c4c71a0bfe0a584438c37a0c192a44fa09509eea)
19
+ - CLMSTaskInProgress component [`b709830`](https://github.com/eea/volto-clms-theme/commit/b7098304abc584de50570d7b1dc272474d7e1719)
20
+ - z-index for header tools dropdown [`7e54bd1`](https://github.com/eea/volto-clms-theme/commit/7e54bd1d69b18d1d48c0d6a8b87fefa6aff64e7e)
21
+ - When task start processing add design to item [`2559caa`](https://github.com/eea/volto-clms-theme/commit/2559caa45e9b7077a2739d30ce1c4d92d2280c9c)
22
+ - on select all cart with task in progress bug fixed [`9582abe`](https://github.com/eea/volto-clms-theme/commit/9582abed5881bb9a3bdbf6f820577ce26e99019f)
23
+ - on cart items post to downloadtool, task start processing [`be7ee24`](https://github.com/eea/volto-clms-theme/commit/be7ee2434c66d34903e995944aa02298c645d503)
24
+ - downloadtool redux action and reducer [`7fcc3de`](https://github.com/eea/volto-clms-theme/commit/7fcc3de64b3db5a43d3a05cbf101b7983a8cd106)
25
+ - prettier [`4cd8768`](https://github.com/eea/volto-clms-theme/commit/4cd876832b7564640e0d0c0aabda9a85f1be9f5e)
26
+ - cartUse hook control if user_id exist [`f97b8ab`](https://github.com/eea/volto-clms-theme/commit/f97b8ab777d3b108e6964efdf8deeb9642818062)
27
+ - header cart counter moved to functional component [`d2e5bbf`](https://github.com/eea/volto-clms-theme/commit/d2e5bbf651b123935abcc8c8f3e65cc6911a8767)
28
+ - progressbar component [`046380a`](https://github.com/eea/volto-clms-theme/commit/046380a5d01deab1887727a7003b7fe6bcd23cd8)
29
+ - post cart selection to downloadtool [`23e6d52`](https://github.com/eea/volto-clms-theme/commit/23e6d52df7f8e0c75c446135099dbfb2bebde5a1)
30
+ - getCartSessionStorage when CART_SESSION_USER_KEY is loaded [`3994dc0`](https://github.com/eea/volto-clms-theme/commit/3994dc0e3ea0facc108bfcd2bc3860ee0f0448a9)
31
+ - changed the cart cache key from user_token to user_id [`e03b53d`](https://github.com/eea/volto-clms-theme/commit/e03b53d98f15a2b556d0a912fe9bc4b216f0d9c4)
32
+
7
33
  #### [1.0.31](https://github.com/eea/volto-clms-theme/compare/1.0.30...1.0.31)
8
34
 
35
+ > 14 October 2021
36
+
37
+ - style changes and arcgis-block new version [`#95`](https://github.com/eea/volto-clms-theme/pull/95)
9
38
  - Top main menu dropdown fxed [`#94`](https://github.com/eea/volto-clms-theme/pull/94)
10
39
  - volto-arcgis-block new version [`5648dcb`](https://github.com/eea/volto-clms-theme/commit/5648dcb178e418a44cf0729ee2c9a920954f820a)
11
40
  - accordion title hover color [`bca1813`](https://github.com/eea/volto-clms-theme/commit/bca181393ec304c2be811f18479c077d13897e77)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-clms-theme",
3
- "version": "1.0.31",
3
+ "version": "1.0.32",
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",
@@ -29,7 +29,7 @@
29
29
  ],
30
30
  "dependencies": {
31
31
  "volto-dropdownmenu": "2.2.7",
32
- "@eeacms/volto-arcgis-block": "0.1.8",
32
+ "@eeacms/volto-arcgis-block": "0.1.9",
33
33
  "@fortawesome/fontawesome-svg-core": "1.2.35",
34
34
  "@fortawesome/free-solid-svg-icons": "5.15.3",
35
35
  "@fortawesome/free-regular-svg-icons": "5.15.3",
@@ -4,7 +4,6 @@
4
4
  */
5
5
  export const GET_CART_ITEMS = 'GET_CART_ITEMS';
6
6
  export const SET_CART_ITEMS = 'SET_CART_ITEMS';
7
-
8
7
  /**
9
8
  * Set Cart items.
10
9
  * @function setCartItems
@@ -13,7 +12,7 @@ export const SET_CART_ITEMS = 'SET_CART_ITEMS';
13
12
  export function setCartItems(items) {
14
13
  return {
15
14
  type: SET_CART_ITEMS,
16
- items,
15
+ items: items,
17
16
  };
18
17
  }
19
18
 
@@ -22,10 +21,10 @@ export function setCartItems(items) {
22
21
  * @function getCartItems
23
22
  * @returns {Object} Get extra items action.
24
23
  */
25
- export function getCartItems(token, localStorage) {
24
+
25
+ export function getCartItems(user_id) {
26
26
  return {
27
27
  type: GET_CART_ITEMS,
28
- token,
29
- localStorage,
28
+ user_id: user_id,
30
29
  };
31
30
  }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Post cart selection to downloadtool.
3
+ * @module actions/postDownloadtool
4
+ */
5
+ export const DELETE_DOWNLOADTOOL = 'DELETE_DOWNLOADTOOL';
6
+
7
+ /**
8
+ * delete cart selection to downloadtool.
9
+ * @function deleteDownloadtool
10
+ * @returns {Object} Get extra items action.
11
+ */
12
+ export function deleteDownloadtool(user_id, task_id) {
13
+ return {
14
+ type: DELETE_DOWNLOADTOOL,
15
+ request: {
16
+ op: 'del',
17
+ data: { UserID: user_id, TaskID: task_id },
18
+ path: '/@datarequest_delete',
19
+ },
20
+ };
21
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Get cart selection to downloadtool.
3
+ * @module actions/getDownloadtool
4
+ */
5
+ export const GET_DOWNLOADTOOL = 'GET_DOWNLOADTOOL';
6
+
7
+ /**
8
+ * Get cart selection to downloadtool.
9
+ * @function GetDownloadtool
10
+ * @returns {Object} Get extra items action.
11
+ */
12
+ export function getDownloadtool(user_id) {
13
+ return {
14
+ type: GET_DOWNLOADTOOL,
15
+ request: {
16
+ op: 'get',
17
+ path: `/@datarequest_search?UserID=${user_id}&Status=In_progress`,
18
+ },
19
+ };
20
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Post cart selection to downloadtool.
3
+ * @module actions/postDownloadtool
4
+ */
5
+ export const POST_DOWNLOADTOOL = 'POST_DOWNLOADTOOL';
6
+
7
+ /**
8
+ * Post cart selection to downloadtool.
9
+ * @function PostDownloadtool
10
+ * @returns {Object} Get extra items action.
11
+ */
12
+ export function postDownloadtool(item) {
13
+ return {
14
+ type: POST_DOWNLOADTOOL,
15
+ request: {
16
+ op: 'post',
17
+ data: item,
18
+ path: '/@datarequest_post',
19
+ },
20
+ };
21
+ }
@@ -33,3 +33,15 @@ export {
33
33
  MEETING_SUBSCRIBERS,
34
34
  MeetingSubscribers,
35
35
  } from './meeting/meeting_subscribers';
36
+ export {
37
+ POST_DOWNLOADTOOL,
38
+ postDownloadtool,
39
+ } from './downloadtool/post_downloadtool';
40
+ export {
41
+ GET_DOWNLOADTOOL,
42
+ getDownloadtool,
43
+ } from './downloadtool/get_downloadtool';
44
+ export {
45
+ DELETE_DOWNLOADTOOL,
46
+ deleteDownloadtool,
47
+ } from './downloadtool/delete_downloadtool';
@@ -68,7 +68,8 @@
68
68
  }
69
69
 
70
70
  .ccl-list-items .ccl-list-item .ccl-list-item-image img {
71
- max-height: 11rem;
71
+ width: 100%;
72
+ height: 100%;
72
73
  object-fit: cover;
73
74
  }
74
75
 
@@ -6,7 +6,7 @@
6
6
  import React, { useEffect, useState } from 'react';
7
7
  import { Helmet } from '@plone/volto/helpers';
8
8
  import { defineMessages, useIntl } from 'react-intl';
9
- import { useDispatch } from 'react-redux';
9
+ import { useDispatch, useSelector } from 'react-redux';
10
10
  import { getExtraBreadcrumbItems } from '../../actions';
11
11
  import useCartState from '@eeacms/volto-clms-theme/utils/useCartState';
12
12
  import { FormattedMessage } from 'react-intl';
@@ -14,11 +14,17 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
14
14
  import { Forbidden, Unauthorized } from '@plone/volto/components';
15
15
  import { Checkbox } from 'semantic-ui-react';
16
16
  import CclButton from '@eeacms/volto-clms-theme/components/CclButton/CclButton';
17
+ import { postDownloadtool, getDownloadtool } from '../../actions';
18
+ import CLMSTasksInProgress from './CLMSTasksInProgress';
17
19
 
18
20
  const CLMSDownloadCartView = (props) => {
19
21
  const dispatch = useDispatch();
20
22
  const { cart, removeCartItem, isLoggedIn } = useCartState();
21
23
  const [cartSelection, setCartSelection] = useState([]);
24
+ const post_download_in_progress = useSelector(
25
+ (state) => state.downloadtool.post_download_in_progress,
26
+ );
27
+ const user_id = useSelector((state) => state.users.user.id);
22
28
  const selectCart = (id, checked) => {
23
29
  if (checked) setCartSelection(cartSelection.concat(id));
24
30
  else setCartSelection(cartSelection.filter((arr_id) => arr_id !== id));
@@ -26,7 +32,11 @@ const CLMSDownloadCartView = (props) => {
26
32
 
27
33
  const selectAllCart = (checked) => {
28
34
  if (checked) {
29
- setCartSelection(cart.map((item, key) => item.unique_id));
35
+ setCartSelection(
36
+ cart
37
+ .filter((item) => item.task_in_progress === false)
38
+ .map((item, key) => item.unique_id),
39
+ );
30
40
  } else {
31
41
  setCartSelection([]);
32
42
  }
@@ -56,6 +66,31 @@ const CLMSDownloadCartView = (props) => {
56
66
  };
57
67
  }, [dispatch, formatMessage, messages.Cart, props.location.pathname]);
58
68
 
69
+ const getSelectedCartItems = () => {
70
+ return cart.filter((item) => cartSelection.indexOf(item.unique_id) > -1);
71
+ };
72
+
73
+ // eslint-disable-next-line react-hooks/exhaustive-deps
74
+ const setCartItemInProgress = (in_progress_dataset_id) => {
75
+ let started_processing_item = cart.filter(
76
+ (r) => r['unique_id'] === in_progress_dataset_id,
77
+ )[0];
78
+ if (started_processing_item['unique_id']) {
79
+ removeCartItem(started_processing_item['unique_id']);
80
+ dispatch(getDownloadtool(user_id));
81
+ }
82
+ };
83
+
84
+ useEffect(() => {
85
+ let progress_keys = Object.keys(post_download_in_progress);
86
+ progress_keys.forEach((progress_key) =>
87
+ setCartItemInProgress(
88
+ post_download_in_progress[progress_key]['DatasetID'],
89
+ ),
90
+ );
91
+ // eslint-disable-next-line react-hooks/exhaustive-deps
92
+ }, [post_download_in_progress]);
93
+
59
94
  return (
60
95
  <>
61
96
  <Helmet title={formatMessage(messages.Cart)} />
@@ -105,8 +140,9 @@ const CLMSDownloadCartView = (props) => {
105
140
  </ul>
106
141
  </div>
107
142
  </div>
108
-
143
+ <CLMSTasksInProgress />
109
144
  <div className="custom-table cart-table">
145
+ <h2>My cart</h2>
110
146
  <table>
111
147
  <thead>
112
148
  <tr>
@@ -118,11 +154,21 @@ const CLMSDownloadCartView = (props) => {
118
154
  onChange={(e, data) =>
119
155
  selectAllCart(data.checked)
120
156
  }
121
- checked={cart
122
- .map((item, key) => item.unique_id)
123
- .every(function (val) {
124
- return cartSelection.indexOf(val) !== -1;
125
- })}
157
+ checked={
158
+ cart
159
+ ? cart
160
+ .filter(
161
+ (item) =>
162
+ item.task_in_progress === false,
163
+ )
164
+ .map((item, key) => item.unique_id)
165
+ .every(function (val) {
166
+ return (
167
+ cartSelection.indexOf(val) !== -1
168
+ );
169
+ })
170
+ : false
171
+ }
126
172
  />
127
173
  </div>
128
174
  </div>
@@ -142,7 +188,14 @@ const CLMSDownloadCartView = (props) => {
142
188
  <tbody>
143
189
  {cart &&
144
190
  cart.map((item, key) => (
145
- <tr key={key}>
191
+ <tr
192
+ key={key}
193
+ style={
194
+ item.task_in_progress
195
+ ? { opacity: 0.5, backgroundColor: '#f5f5f5' }
196
+ : {}
197
+ }
198
+ >
146
199
  <td className="table-td-warning hidden-warning">
147
200
  {!!item.warning && (
148
201
  <span
@@ -166,6 +219,7 @@ const CLMSDownloadCartView = (props) => {
166
219
  checked={cartSelection.includes(
167
220
  item.unique_id,
168
221
  )}
222
+ disabled={item.task_in_progress}
169
223
  />
170
224
  </div>
171
225
  </div>
@@ -177,7 +231,7 @@ const CLMSDownloadCartView = (props) => {
177
231
  <td>{item.resolution}</td>
178
232
  <td>
179
233
  <span
180
- className={'tag tag-' + item.type.toLowerCase()}
234
+ className={'tag tag-' + item?.type?.toLowerCase()}
181
235
  >
182
236
  {item.type}
183
237
  </span>
@@ -202,17 +256,21 @@ const CLMSDownloadCartView = (props) => {
202
256
  <td>{item.version}</td>
203
257
  <td>{item.size}</td>
204
258
  <td>
205
- <FontAwesomeIcon
206
- icon={['fas', 'trash']}
207
- style={{ cursor: 'pointer' }}
208
- onClick={() => {
209
- removeCartItem(item.unique_id);
210
- }}
211
- />
259
+ {item.task_in_progress ? (
260
+ <FontAwesomeIcon icon="spinner" spin />
261
+ ) : (
262
+ <FontAwesomeIcon
263
+ icon={['fas', 'trash']}
264
+ style={{ cursor: 'pointer' }}
265
+ onClick={() => {
266
+ removeCartItem(item.unique_id);
267
+ }}
268
+ />
269
+ )}
212
270
  </td>
213
271
  </tr>
214
272
  ))}
215
- {cart.length === 0 && (
273
+ {cart?.length === 0 && (
216
274
  <>
217
275
  <tr>
218
276
  <td
@@ -227,14 +285,30 @@ const CLMSDownloadCartView = (props) => {
227
285
  </tbody>
228
286
  </table>
229
287
  </div>
230
- {cart.length !== 0 && (
288
+ {cart?.length !== 0 && (
231
289
  <CclButton
232
290
  onClick={() => {
233
- // eslint-disable-next-line no-alert
234
- alert(
235
- 'ToDo\nSelected content:\n' +
236
- JSON.stringify(cartSelection),
237
- );
291
+ let selectedItems = getSelectedCartItems();
292
+ selectedItems.forEach((selected) => {
293
+ const item = {
294
+ UserID: user_id,
295
+ /*,
296
+ UID: dataset unique id;
297
+ DatasetID: dataset id;
298
+ Format: Dataset format
299
+ selected['unique_id']
300
+ selected['UID']
301
+ */
302
+ DatasetID: selected['unique_id'] || selected['UID'], // provisional, We need to send and return unique_id to can mark this element as a pending task selected['UID'],
303
+ //DatasetFormat: selected['type'], // Formats: "Shapefile"|"GDB"|"GPKG"|"Geojson"|"Geotiff"|"Netcdf"|"GML"|"WFS"
304
+ DatasetFormat: 'Shapefile',
305
+ // OutputFormat:selected['format'],
306
+ // DatasetPath: selected['path'],
307
+
308
+ OutputFormat: 'GDB',
309
+ };
310
+ dispatch(postDownloadtool(item));
311
+ });
238
312
  }}
239
313
  disabled={cartSelection.length === 0}
240
314
  >
@@ -0,0 +1,171 @@
1
+ /**
2
+ * CLMSInProgressTask container.
3
+ * @module components/CLMSInProgressTask/CLMSInProgressTask
4
+ */
5
+
6
+ import React, { useEffect, useState } from 'react';
7
+ import { useDispatch, useSelector } from 'react-redux';
8
+ import { getDownloadtool, deleteDownloadtool } from '../../actions';
9
+ // import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
10
+ import { Loader, Popup } from 'semantic-ui-react';
11
+ import removeSVG from '@plone/volto/icons/circle-dismiss.svg';
12
+ import downloadSVG from '@plone/volto/icons/download.svg';
13
+ import { Icon } from '@plone/volto/components';
14
+ import './task_in_progress.less';
15
+
16
+ const CLMSTasksInProgress = (props) => {
17
+ const dispatch = useDispatch();
18
+ const [taskInProgress, setTaskInProgress] = useState([]);
19
+ const download_in_progress = useSelector(
20
+ (state) => state.downloadtool.download_in_progress,
21
+ );
22
+
23
+ const user_id = useSelector((state) => state.users.user.id);
24
+ const [showDeleteTaskLoading, setShowDeleteTaskLoading] = useState(false);
25
+
26
+ useEffect(() => {
27
+ dispatch(getDownloadtool(user_id));
28
+ }, [user_id, dispatch]);
29
+
30
+ useEffect(() => {
31
+ let progress_keys = Object.keys(download_in_progress);
32
+ let tasks_in_progress = [];
33
+ progress_keys.forEach((progress_key) => {
34
+ tasks_in_progress.push({
35
+ ...download_in_progress[progress_key],
36
+ TaskID: progress_key,
37
+ });
38
+ });
39
+ setTaskInProgress(tasks_in_progress);
40
+ }, [download_in_progress]);
41
+ const deleteTaskInProgress = (task_id) => {
42
+ setShowDeleteTaskLoading(task_id);
43
+ dispatch(deleteDownloadtool(user_id, task_id));
44
+ setTimeout(() => {
45
+ dispatch(getDownloadtool(user_id));
46
+ setShowDeleteTaskLoading(false);
47
+ }, 1000); // We need delete response to check if remove_task request is completed successfully
48
+ };
49
+ return (
50
+ <>
51
+ {taskInProgress.length !== 0 && (
52
+ <div className="custom-table cart-table">
53
+ <h2>Tasks In Progress</h2>
54
+ <table>
55
+ <thead>
56
+ <tr>
57
+ <th>DatasetFormat</th>
58
+ <th>DatasetID || unique_id</th>
59
+ <th>OutputFormat</th>
60
+ <th>Status</th>
61
+ <th></th>
62
+ <th></th>
63
+ </tr>
64
+ </thead>
65
+ <tbody>
66
+ {taskInProgress &&
67
+ taskInProgress.map((item, key) => (
68
+ <tr
69
+ key={key}
70
+ style={{ opacity: 0.5, backgroundColor: '#f5f5f5' }}
71
+ >
72
+ <td className="table-td-format">{item.DatasetFormat}</td>
73
+ <td>{item.DatasetID}</td>
74
+ <td>{item.OutputFormat}</td>
75
+
76
+ <td>
77
+ <Popup
78
+ content="In progress"
79
+ size="small"
80
+ trigger={
81
+ <Loader active inline indeterminate size="small" />
82
+ }
83
+ />
84
+ {/* <FontAwesomeIcon icon="spinner" spin /> */}
85
+ </td>
86
+ <td>
87
+ <Popup
88
+ content="Download (Pending)"
89
+ size="small"
90
+ trigger={
91
+ <button
92
+ // disabled={true}
93
+ onClick={() => {
94
+ // deleteTaskInProgress(item.TaskID);
95
+ }}
96
+ style={{
97
+ backgroundColor: 'none',
98
+ color: 'inherit',
99
+ border: 'none',
100
+ padding: 0,
101
+ font: 'inherit',
102
+ cursor: 'pointer',
103
+ outline: 'inherit',
104
+ }}
105
+ >
106
+ <Icon
107
+ name={downloadSVG}
108
+ size="32px"
109
+ color="#A0B128"
110
+ title={'Download'}
111
+ />
112
+ </button>
113
+ }
114
+ />
115
+ </td>
116
+ <td>
117
+ {showDeleteTaskLoading === item.TaskID ? (
118
+ <Loader
119
+ active
120
+ inline
121
+ indeterminate
122
+ size="small"
123
+ className="red-loader"
124
+ />
125
+ ) : (
126
+ <Popup
127
+ content="Remove in progress task"
128
+ size="small"
129
+ trigger={
130
+ <button
131
+ onClick={() => {
132
+ deleteTaskInProgress(item.TaskID);
133
+ }}
134
+ style={{
135
+ backgroundColor: 'none',
136
+ color: 'inherit',
137
+ border: 'none',
138
+ padding: 0,
139
+ font: 'inherit',
140
+ cursor: 'pointer',
141
+ outline: 'inherit',
142
+ }}
143
+ >
144
+ <Icon
145
+ name={removeSVG}
146
+ size="32px"
147
+ color="#e40166"
148
+ title={'Remove in progress task'}
149
+ />
150
+ </button>
151
+ }
152
+ />
153
+ )}
154
+ {/* <FontAwesomeIcon
155
+ icon={['fas', 'trash']}
156
+ style={{ cursor: 'pointer' }}
157
+ onClick={() => {
158
+ deleteTaskInProgress(item.TaskID);
159
+ }}
160
+ /> */}
161
+ </td>
162
+ </tr>
163
+ ))}
164
+ </tbody>
165
+ </table>
166
+ </div>
167
+ )}
168
+ </>
169
+ );
170
+ };
171
+ export default CLMSTasksInProgress;
@@ -0,0 +1,6 @@
1
+ .red-loader.ui.loader:after {
2
+ border-top-color: #e40166;
3
+ border-right-color: transparent;
4
+ border-bottom-color: transparent;
5
+ border-left-color: transparent;
6
+ }
@@ -54,12 +54,12 @@ function CclCard(props) {
54
54
  alt="Placeholder"
55
55
  />
56
56
  </div>
57
- <div className="card-doc-title">
58
- <a href={card?.file?.download}>
59
- {card?.title || 'Card default title'}
60
- </a>
61
- </div>
62
57
  <div className="card-text">
58
+ <div className="card-title">
59
+ <a href={card?.file?.download}>
60
+ {card?.title || 'Card default title'}
61
+ </a>
62
+ </div>
63
63
  <div className="card-description">{card?.description}</div>
64
64
  <div className="card-button">
65
65
  <CclButton url={url}>Access to product</CclButton>
@@ -29,10 +29,10 @@ const CclTopMainMenu = () => {
29
29
  ) : (
30
30
  <li className="header-dropdown" key={index}>
31
31
  <>
32
- <a>
32
+ <span>
33
33
  {item.title}{' '}
34
34
  <span className="ccl-icon-chevron-thin-down"></span>
35
- </a>
35
+ </span>
36
36
  <ul>
37
37
  {item.navigationRoot?.map((element, index) => (
38
38
  <li key={index}>
@@ -5,9 +5,9 @@
5
5
  * @module components/theme/Header/Header
6
6
  */
7
7
 
8
- import React, { Component } from 'react';
8
+ import React, { Component, useEffect } from 'react';
9
9
  import PropTypes from 'prop-types';
10
- import { connect } from 'react-redux';
10
+ import { connect, useSelector, useDispatch } from 'react-redux';
11
11
 
12
12
  import { Logo, Navigation, SearchWidget } from '@plone/volto/components';
13
13
  import jwtDecode from 'jwt-decode';
@@ -25,6 +25,33 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
25
25
  import { getCartItems } from '@eeacms/volto-clms-theme/actions';
26
26
  import '@eeacms/volto-clms-theme/../theme/clms/css/header.css';
27
27
  import { Link } from 'react-router-dom';
28
+ // import useCartState from '@eeacms/volto-clms-theme/utils/useCartState';
29
+
30
+ const CartIconCounter = (props) => {
31
+ const { cart_items, users, intl } = useSelector((state) => state);
32
+
33
+ const cart = cart_items.items;
34
+ const user_id = users.user.id;
35
+
36
+ const dispatch = useDispatch();
37
+ useEffect(() => {
38
+ dispatch(getCartItems(user_id));
39
+ }, [user_id, dispatch]);
40
+ return (
41
+ cart?.length !== 0 &&
42
+ cart && (
43
+ <>
44
+ <span className="header-vertical-line"> - </span>
45
+ <span>
46
+ <Link to={`/${intl.locale}/cart`} className="header-login-link">
47
+ <FontAwesomeIcon icon={['fas', 'shopping-cart']} />
48
+ <strong>{cart?.length}</strong>
49
+ </Link>
50
+ </span>
51
+ </>
52
+ )
53
+ );
54
+ };
28
55
  /**
29
56
  * Header component class.
30
57
  * @class Header
@@ -52,12 +79,14 @@ class Header extends Component {
52
79
 
53
80
  componentDidMount() {
54
81
  this.props.getUser(this.props.token);
55
- this.props.getCartItems(this.props.rawtoken);
56
82
  }
57
83
  UNSAFE_componentWillReceiveProps(nextProps) {
58
84
  if (nextProps.token !== this.props.token) {
59
85
  this.props.getUser(nextProps.token);
60
86
  }
87
+ if (nextProps.user.id !== this.props.user.id) {
88
+ this.props.getCartItems(this.props?.user?.id);
89
+ }
61
90
  }
62
91
 
63
92
  /**
@@ -152,22 +181,7 @@ class Header extends Component {
152
181
  </>
153
182
  )}
154
183
  </Link>
155
- {this.props.cart?.length !== 0 && this.props.cart && (
156
- <>
157
- <span className="header-vertical-line"> - </span>
158
- <span>
159
- <Link
160
- to={`/${this.props.locale}/cart`}
161
- className="header-login-link"
162
- >
163
- <FontAwesomeIcon
164
- icon={['fas', 'shopping-cart']}
165
- />
166
- <strong>{this.props.cart?.length}</strong>
167
- </Link>
168
- </span>
169
- </>
170
- )}
184
+ <CartIconCounter />
171
185
  {this.props.user.id &&
172
186
  this.props.user.roles &&
173
187
  this.props.user.roles[0] === 'Member' && (
@@ -18,11 +18,12 @@ export const cartItemsReducer = (state = initialState, action = {}) => {
18
18
  items: action.items,
19
19
  };
20
20
  case GET_CART_ITEMS:
21
+ const CART_SESSION_USER_KEY = action.user_id
22
+ ? CART_SESSION_KEY.concat(`_${action.user_id}`)
23
+ : CART_SESSION_KEY;
21
24
  return {
22
25
  ...state,
23
- items: JSON.parse(
24
- localStorage.getItem(CART_SESSION_KEY.concat(action.token)),
25
- ),
26
+ items: JSON.parse(localStorage.getItem(CART_SESSION_USER_KEY)),
26
27
  };
27
28
  default:
28
29
  return state;
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Downloadtool reducer.
3
+ * @module reducers/downloadtool
4
+ */
5
+
6
+ import {
7
+ GET_DOWNLOADTOOL,
8
+ POST_DOWNLOADTOOL,
9
+ DELETE_DOWNLOADTOOL,
10
+ } from '../../actions';
11
+
12
+ const getInitialState = {
13
+ error: null,
14
+ loaded: false,
15
+ loading: false,
16
+ download_in_progress: {},
17
+ delete_download_in_progress: {},
18
+ post_download_in_progress: {},
19
+ };
20
+
21
+ export const downloadtoolReducer = (state = getInitialState, action = {}) => {
22
+ switch (action?.type) {
23
+ case `${GET_DOWNLOADTOOL}_PENDING`:
24
+ return {
25
+ ...state,
26
+ error: null,
27
+ loaded: false,
28
+ loading: true,
29
+ };
30
+ case `${GET_DOWNLOADTOOL}_FAIL`:
31
+ return {
32
+ ...state,
33
+ error: action.error,
34
+ loaded: false,
35
+ loading: false,
36
+ };
37
+
38
+ case `${GET_DOWNLOADTOOL}_SUCCESS`:
39
+ return {
40
+ ...state,
41
+ error: null,
42
+ loaded: true,
43
+ loading: false,
44
+ download_in_progress: action.result,
45
+ };
46
+ case `${POST_DOWNLOADTOOL}_PENDING`:
47
+ return {
48
+ ...state,
49
+ error: null,
50
+ loaded: false,
51
+ loading: true,
52
+ };
53
+ case `${POST_DOWNLOADTOOL}_FAIL`:
54
+ return {
55
+ ...state,
56
+ error: action.error,
57
+ loaded: false,
58
+ loading: false,
59
+ };
60
+
61
+ case `${POST_DOWNLOADTOOL}_SUCCESS`:
62
+ return {
63
+ ...state,
64
+ error: null,
65
+ loaded: true,
66
+ loading: false,
67
+ post_download_in_progress: action.result,
68
+ };
69
+ case `${DELETE_DOWNLOADTOOL}_PENDING`:
70
+ return {
71
+ ...state,
72
+ error: null,
73
+ loaded: false,
74
+ loading: true,
75
+ };
76
+ case `${DELETE_DOWNLOADTOOL}_FAIL`:
77
+ return {
78
+ ...state,
79
+ error: action.error,
80
+ loaded: false,
81
+ loading: false,
82
+ };
83
+
84
+ case `${DELETE_DOWNLOADTOOL}_SUCCESS`:
85
+ return {
86
+ ...state,
87
+ error: null,
88
+ loaded: true,
89
+ loading: false,
90
+ delete_download_in_progress: action.result,
91
+ };
92
+ default:
93
+ return state;
94
+ }
95
+ };
@@ -9,6 +9,8 @@ import { cartItemsReducer } from './cart/cart_reducer';
9
9
  import { extraBreadcrumbItemsReducer } from './extra_breadcrumbs/extra_breadcrumb_reducer';
10
10
  import { meetingRegisterReducer } from './meeting/meeting_register_reducer';
11
11
  import { meetingSubscribersReducer } from './meeting/meeting_subscribers_reducer';
12
+ import { downloadtoolReducer } from './downloadtool/downloadtool_reducer';
13
+
12
14
  /**
13
15
  * Root reducer.
14
16
  * @function
@@ -24,6 +26,7 @@ const reducers = {
24
26
  cart_items: cartItemsReducer,
25
27
  meeting_register: meetingRegisterReducer,
26
28
  subscribers: meetingSubscribersReducer,
29
+ downloadtool: downloadtoolReducer,
27
30
  };
28
31
 
29
32
  export default reducers;
@@ -7,66 +7,71 @@ import { useSelector } from 'react-redux';
7
7
  export const CART_SESSION_KEY = 'cart_session';
8
8
 
9
9
  const useCartState = () => {
10
- const [cart, setCart] = useState([]);
10
+ // const [cart, setCart] = useState([]);
11
11
  const [savedToCard, setSavedToCard] = useState(false);
12
12
  const [toasTime, setToastTime] = useState(3000);
13
- const CART_SESSION_USER_KEY = useSelector((state) =>
14
- state.userSession.token
15
- ? CART_SESSION_KEY.concat(state.userSession.token)
16
- : CART_SESSION_KEY,
17
- );
13
+ const [CART_SESSION_USER_KEY, SET_CART_SESSION_USER_KEY] = useState();
18
14
  const isLoggedIn = useSelector((state) =>
19
15
  state.userSession.token ? jwtDecode(state.userSession.token).sub : '',
20
16
  )
21
17
  ? true
22
18
  : false;
23
- // const cartState = useSelector((state) => state.cart_items.items);
24
- // const state = store.getState();
25
- // const [loggedInStatus, setLoggedInStatus] = useState(
26
- // useSelector((state) =>
27
- // state.userSession.token ? jwtDecode(state.userSession.token).sub : '',
28
- // ),
29
- // );
30
19
 
20
+ const user_id = useSelector((state) => state.users.user.id);
21
+ const cartState = useSelector((state) => state.cart_items.items);
22
+
23
+ useEffect(() => {
24
+ user_id &&
25
+ SET_CART_SESSION_USER_KEY(CART_SESSION_KEY.concat(`_${user_id}`));
26
+ getCartSessionStorage();
27
+ // eslint-disable-next-line react-hooks/exhaustive-deps
28
+ }, [CART_SESSION_USER_KEY, user_id]);
31
29
  const dispatch = useDispatch();
32
30
 
33
31
  const saveItems = (values) => {
34
32
  let items = cleanDuplicatesEntries(values);
35
- // localStorage.setItem(CART_SESSION_KEY, JSON.stringify(items));
36
33
  localStorage.setItem(CART_SESSION_USER_KEY, JSON.stringify(items));
37
- setCart(items);
38
-
34
+ dispatch(setCartItems(items ?? []));
39
35
  setSavedToCard(true);
40
36
  setTimeout(() => setSavedToCard(false), toasTime);
41
37
  };
42
38
 
43
39
  const removeAllCart = () => {
44
40
  localStorage.removeItem(CART_SESSION_USER_KEY);
45
- setCart([]);
41
+ dispatch(setCartItems([]));
46
42
  };
47
43
 
48
44
  const getCartSessionStorage = () => {
49
- setCart(JSON.parse(localStorage.getItem(CART_SESSION_USER_KEY)) || []);
45
+ CART_SESSION_USER_KEY &&
46
+ dispatch(
47
+ setCartItems(
48
+ JSON.parse(localStorage.getItem(CART_SESSION_USER_KEY)) || [],
49
+ ),
50
+ );
50
51
  };
51
52
 
52
53
  const addCartItem = async (value) => {
54
+ let card_item = value.map((item) => {
55
+ item['task_in_progress'] = false;
56
+ return item;
57
+ });
53
58
  await getCartSessionStorage();
54
- if (cart) {
55
- saveItems(cart.concat(value));
59
+ if (cartState) {
60
+ saveItems(cartState.concat(card_item));
56
61
  } else {
57
- saveItems(value);
62
+ saveItems(card_item);
58
63
  }
59
64
  };
60
65
 
61
66
  const removeCartItem = async (id) => {
62
67
  await getCartSessionStorage();
63
- let newcart = cart.slice();
64
- newcart.forEach((item) => {
68
+ let newcart = cartState.slice();
69
+ await newcart.forEach((item) => {
65
70
  if (item.unique_id === id) {
66
71
  newcart.splice(newcart.indexOf(item), 1);
67
72
  }
68
73
  });
69
- setCart(newcart);
74
+
70
75
  saveItems(newcart);
71
76
  };
72
77
 
@@ -76,15 +81,6 @@ const useCartState = () => {
76
81
  index === self.findIndex((t) => t.unique_id === arr.unique_id),
77
82
  );
78
83
 
79
- useEffect(() => {
80
- getCartSessionStorage();
81
- // eslint-disable-next-line react-hooks/exhaustive-deps
82
- }, []);
83
-
84
- useEffect(() => {
85
- dispatch(setCartItems(cart));
86
- }, [dispatch, cart]);
87
-
88
84
  const Toast = ({ message, time = toasTime }) => {
89
85
  return (
90
86
  <>
@@ -100,15 +96,26 @@ const useCartState = () => {
100
96
  );
101
97
  };
102
98
 
99
+ const changeCartItemTaskStatus = async (unique_id, in_progress) => {
100
+ await getCartSessionStorage();
101
+ let newcart = cartState.map((item) => {
102
+ if (item['unique_id'] === unique_id) {
103
+ item['task_in_progress'] = in_progress;
104
+ }
105
+ return item;
106
+ });
107
+ saveItems(newcart);
108
+ };
103
109
  // return [cart, addCartItem, removeCartSessionStorage];
104
110
 
105
111
  return {
106
- cart: cart,
112
+ cart: cartState,
107
113
  addCartItem: addCartItem,
108
114
  removeAllCart: removeAllCart,
109
115
  removeCartItem: removeCartItem,
110
116
  Toast: Toast,
111
117
  isLoggedIn: isLoggedIn,
118
+ changeCartItemTaskStatus: changeCartItemTaskStatus,
112
119
  };
113
120
  };
114
121
 
@@ -361,7 +361,6 @@
361
361
  .ccl-list-carousel .slick-slide img {
362
362
  border: none !important;
363
363
  border-radius: 1.5rem;
364
- opacity: 0.5;
365
364
  }
366
365
 
367
366
  .ccl-list-carousel .slick-slide:focus {
@@ -371,10 +370,12 @@
371
370
  /* Items */
372
371
  .ccl-list-items .ccl-list-item .ccl-list-item-image {
373
372
  width: 100%;
373
+ height: 12rem;
374
374
  }
375
375
 
376
376
  .ccl-list-items .ccl-list-item .ccl-list-item-image img {
377
377
  width: 100%;
378
+ height: 100%;
378
379
  }
379
380
 
380
381
  .ccl-list-items .ccl-list-item .ccl-list-item-date {
@@ -340,11 +340,11 @@
340
340
 
341
341
  /*---CS ADDITION---*/
342
342
 
343
- .ccl-form-check-label {
343
+ .ccl-footer-form .ccl-form-check-label {
344
344
  color: white !important;
345
345
  }
346
346
 
347
- .ccl-form-check-label a {
347
+ .ccl-footer-form .ccl-form-check-label a {
348
348
  text-decoration: underline;
349
349
  }
350
350
 
@@ -276,68 +276,68 @@
276
276
  }
277
277
 
278
278
  .ccl-header
279
- .ccl-header-nav
280
- .ccl-header-logos-container
281
- .ccl-header-logo-service-container {
279
+ .ccl-header-nav
280
+ .ccl-header-logos-container
281
+ .ccl-header-logo-service-container {
282
282
  display: none;
283
283
  height: 3.125rem;
284
284
  margin: 0;
285
285
  }
286
286
 
287
287
  .ccl-header
288
- .ccl-header-nav
289
- .ccl-header-logos-container
290
- .ccl-header-logo-service-container.ccl-service-button.ccl-service-button-full {
288
+ .ccl-header-nav
289
+ .ccl-header-logos-container
290
+ .ccl-header-logo-service-container.ccl-service-button.ccl-service-button-full {
291
291
  width: auto;
292
292
  }
293
293
 
294
294
  .ccl-header
295
- .ccl-header-nav
296
- .ccl-header-logos-container
297
- .ccl-header-logo-service-container.ccl-service-button.ccl-service-button-full
298
- .ccl-service-button-icon {
295
+ .ccl-header-nav
296
+ .ccl-header-logos-container
297
+ .ccl-header-logo-service-container.ccl-service-button.ccl-service-button-full
298
+ .ccl-service-button-icon {
299
299
  width: 2.7777777778rem;
300
300
  margin-right: 0;
301
301
  }
302
302
  @media (max-width: 820px) {
303
303
  .ccl-header
304
- .ccl-header-nav
305
- .ccl-header-logos-container
306
- .ccl-header-logo-service-container {
304
+ .ccl-header-nav
305
+ .ccl-header-logos-container
306
+ .ccl-header-logo-service-container {
307
307
  margin-right: 1.0555555556rem;
308
308
  margin-left: 1.0555555556rem;
309
309
  }
310
310
  }
311
311
  @media (max-width: 640px) {
312
312
  .ccl-header
313
- .ccl-header-nav
314
- .ccl-header-logos-container
315
- .ccl-header-logo-service-container {
313
+ .ccl-header-nav
314
+ .ccl-header-logos-container
315
+ .ccl-header-logo-service-container {
316
316
  margin-top: 1.0555555556rem;
317
317
  }
318
318
  }
319
319
 
320
320
  .ccl-header
321
- .ccl-header-nav
322
- .ccl-header-logos-container
323
- .ccl-header-logo-container {
321
+ .ccl-header-nav
322
+ .ccl-header-logos-container
323
+ .ccl-header-logo-container {
324
324
  display: flex;
325
325
  height: 3.125rem;
326
326
  margin: 0 1.1111111111rem 0 0;
327
327
  }
328
328
 
329
329
  .ccl-header
330
- .ccl-header-nav
331
- .ccl-header-logos-container
332
- .ccl-header-logo-container
333
- .ccl-header-logo {
330
+ .ccl-header-nav
331
+ .ccl-header-logos-container
332
+ .ccl-header-logo-container
333
+ .ccl-header-logo {
334
334
  height: 3.125rem;
335
335
  }
336
336
  @media (max-width: 820px) {
337
337
  .ccl-header
338
- .ccl-header-nav
339
- .ccl-header-logos-container
340
- .ccl-header-logo-container {
338
+ .ccl-header-nav
339
+ .ccl-header-logos-container
340
+ .ccl-header-logo-container {
341
341
  margin-left: 1.0555555556rem;
342
342
  }
343
343
  }
@@ -347,9 +347,9 @@
347
347
  }
348
348
  @media (max-width: 400px) {
349
349
  .ccl-header
350
- .ccl-header-nav
351
- .ccl-header-logos-container
352
- .ccl-header-logo-container {
350
+ .ccl-header-nav
351
+ .ccl-header-logos-container
352
+ .ccl-header-logo-container {
353
353
  width: 100%;
354
354
  height: 2rem;
355
355
  justify-content: space-around;
@@ -357,10 +357,10 @@
357
357
  }
358
358
 
359
359
  .ccl-header
360
- .ccl-header-nav
361
- .ccl-header-logos-container
362
- .ccl-header-logo-container
363
- .ccl-header-logo {
360
+ .ccl-header-nav
361
+ .ccl-header-logos-container
362
+ .ccl-header-logo-container
363
+ .ccl-header-logo {
364
364
  height: 2rem;
365
365
  }
366
366
 
@@ -615,7 +615,7 @@
615
615
 
616
616
  .ccl-header-tools-container .header-dropdown:hover ul {
617
617
  position: absolute;
618
- z-index: 1;
618
+ z-index: 3;
619
619
  left: 0;
620
620
  display: block;
621
621
  min-width: 100%;
@@ -675,16 +675,16 @@
675
675
  }
676
676
 
677
677
  .ccl-header
678
- .ccl-header-nav
679
- .ccl-collapsible-toolmenu
680
- > li.header-vertical-line {
678
+ .ccl-header-nav
679
+ .ccl-collapsible-toolmenu
680
+ > li.header-vertical-line {
681
681
  display: none;
682
682
  }
683
683
 
684
684
  .ccl-header
685
- .ccl-header-nav
686
- .ccl-collapsible-toolmenu
687
- > li.header-vertical-line {
685
+ .ccl-header-nav
686
+ .ccl-collapsible-toolmenu
687
+ > li.header-vertical-line {
688
688
  display: none;
689
689
  }
690
690