@eeacms/volto-clms-theme 1.1.208 → 1.1.209

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,19 @@ 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.209](https://github.com/eea/volto-clms-theme/compare/1.1.208...1.1.209) - 30 January 2025
8
+
9
+ #### :rocket: New Features
10
+
11
+ - feat: Improve the order of documents in the technical library of the product/product group - refs #283044 [ana-oprea - [`6feba8a`](https://github.com/eea/volto-clms-theme/commit/6feba8a82ec84a6186cee3da719de7b10a356947)]
12
+
13
+ #### :bug: Bug Fixes
14
+
15
+ - fix(test): modify widget tests for dataset and add test for product content type [ana-oprea - [`d7534cc`](https://github.com/eea/volto-clms-theme/commit/d7534cc4f26e77bcfcc91d3988f4f974ec3116f4)]
16
+
17
+ #### :hammer_and_wrench: Others
18
+
19
+ - fix eslint [ana-oprea - [`785ccf8`](https://github.com/eea/volto-clms-theme/commit/785ccf86f60e3275b7f392fb3b47f0eb6845f7b2)]
7
20
  ### [1.1.208](https://github.com/eea/volto-clms-theme/compare/1.1.207...1.1.208) - 13 January 2025
8
21
 
9
22
  #### :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.208",
3
+ "version": "1.1.209",
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",
@@ -27,7 +27,7 @@ const CclRelatedListingEdit = (props) => {
27
27
  (variation) => variation.id === data.variation,
28
28
  );
29
29
  TemplateView = theVariation?.template;
30
- template_id = theVariation.templateId;
30
+ template_id = theVariation.templateID;
31
31
  } else {
32
32
  TemplateView = defaultVariation.template;
33
33
  template_id = defaultVariation.id;
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useCallback, useMemo } from 'react';
1
+ import React, { useEffect, useCallback, useMemo, useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { useLocation } from 'react-router-dom';
4
4
  import { useDispatch, useSelector } from 'react-redux';
@@ -41,34 +41,39 @@ const DocumentItem = React.memo(({ item, provided }) => (
41
41
  const OrderDocumentsWidget = (props) => {
42
42
  const { id, formData, onChange, value } = props;
43
43
  const UID = formData?.UID;
44
+ const contentType = formData?.['@type'] || undefined;
44
45
  const location = useLocation();
45
46
  const dispatch = useDispatch();
46
47
  const searchSubrequests = useSelector((state) => state.search.subrequests);
47
- const [documentsList, setDocumentsList] = React.useState([]);
48
- const [isLoading, setIsLoading] = React.useState(true);
48
+ const [documentsList, setDocumentsList] = useState([]);
49
+ const [isLoading, setIsLoading] = useState(true);
50
+ const [isVisible, setIsVisible] = useState(false);
49
51
 
50
52
  const fetchDocuments = useCallback(() => {
51
- if (UID) {
52
- const sort_on = ['documentation_sorting', 'sortable_title'];
53
- const sort_order = ['ascending', 'ascending'];
53
+ const sort_on = ['documentation_sorting', 'sortable_title'];
54
+ const sort_order = ['ascending', 'ascending'];
54
55
 
56
+ if (UID) {
55
57
  setIsLoading(true);
58
+ const searchParams = {
59
+ portal_type: 'TechnicalLibrary',
60
+ path: 'en/technical-library',
61
+ sort_on: sort_on,
62
+ sort_order: sort_order,
63
+ b_size: 99999,
64
+ };
65
+
66
+ if (contentType === 'DataSet') {
67
+ searchParams.associated_datasets = UID;
68
+ } else if (contentType === 'Product') {
69
+ searchParams.associated_products = UID;
70
+ }
71
+
56
72
  dispatch(
57
- searchContent(
58
- 'en/technical-library',
59
- {
60
- portal_type: 'TechnicalLibrary',
61
- path: 'en/technical-library',
62
- associated_datasets: UID,
63
- sort_on: sort_on,
64
- sort_order: sort_order,
65
- b_size: 99999,
66
- },
67
- id,
68
- ),
73
+ searchContent('en/technical-library', searchParams, id),
69
74
  ).finally(() => setIsLoading(false));
70
75
  }
71
- }, [id, UID, dispatch]);
76
+ }, [id, UID, contentType, dispatch]);
72
77
 
73
78
  const handleDragEnd = useCallback(
74
79
  (result) => {
@@ -86,8 +91,8 @@ const OrderDocumentsWidget = (props) => {
86
91
  [documentsList, onChange, id],
87
92
  );
88
93
 
89
- const memoizedList = useMemo(
90
- () => (
94
+ const memoizedList = useMemo(() => {
95
+ return (
91
96
  <DragDropContext onDragEnd={handleDragEnd}>
92
97
  <Droppable droppableId="documents">
93
98
  {(provided) => (
@@ -110,9 +115,8 @@ const OrderDocumentsWidget = (props) => {
110
115
  )}
111
116
  </Droppable>
112
117
  </DragDropContext>
113
- ),
114
- [documentsList, handleDragEnd],
115
- );
118
+ );
119
+ }, [documentsList, handleDragEnd]);
116
120
 
117
121
  useEffect(() => {
118
122
  fetchDocuments();
@@ -130,9 +134,9 @@ const OrderDocumentsWidget = (props) => {
130
134
  const newItems = receivedDocumentsList.filter(
131
135
  (item) => !value.items.some((item2) => item2.id === item.id),
132
136
  );
133
- setDocumentsList([...value.items, ...newItems]);
137
+ setDocumentsList([...value?.items, ...newItems]);
134
138
  } else {
135
- setDocumentsList(value.items);
139
+ setDocumentsList(value?.items);
136
140
  }
137
141
  }
138
142
  }, [searchSubrequests, id, value]);
@@ -143,6 +147,18 @@ const OrderDocumentsWidget = (props) => {
143
147
  draggable={true}
144
148
  className="drag-drop-list-widget"
145
149
  >
150
+ {contentType === 'Product' && (
151
+ <Button
152
+ basic
153
+ size="small"
154
+ type="button"
155
+ onClick={() => setIsVisible((prev) => !prev)}
156
+ aria-label="Toggle document list visibility"
157
+ className="order-docs-button"
158
+ >
159
+ {isVisible ? 'Hide' : 'Show'}
160
+ </Button>
161
+ )}
146
162
  <div className="order-documents-area">
147
163
  <div className="documents-list-header">
148
164
  <div>Technical Document Title</div>
@@ -150,7 +166,7 @@ const OrderDocumentsWidget = (props) => {
150
166
  {isLoading ? (
151
167
  <div className="loading-documents">Loading documents...</div>
152
168
  ) : (
153
- memoizedList
169
+ (contentType === 'DataSet' || isVisible) && memoizedList
154
170
  )}
155
171
  </div>
156
172
  </FormFieldWrapper>
@@ -55,7 +55,7 @@ describe('OrderDocumentsWidget', () => {
55
55
  <MemoryRouter>
56
56
  <OrderDocumentsWidget
57
57
  id="testId"
58
- formData={{ UID: 'someUID' }}
58
+ formData={{ UID: 'someUID', '@type': 'DataSet' }}
59
59
  onChange={mockOnChange}
60
60
  value={{ items: [] }}
61
61
  />
@@ -80,7 +80,7 @@ describe('OrderDocumentsWidget', () => {
80
80
  id="testId"
81
81
  formData={{ UID: 'someUID' }}
82
82
  onChange={mockOnChange}
83
- value={{ items: [] }}
83
+ value={{ items: [], '@type': 'DataSet' }}
84
84
  />
85
85
  </MemoryRouter>
86
86
  </Provider>,
@@ -96,7 +96,7 @@ describe('OrderDocumentsWidget', () => {
96
96
  <MemoryRouter>
97
97
  <OrderDocumentsWidget
98
98
  id="testId"
99
- formData={{ UID: 'someUID' }}
99
+ formData={{ UID: 'someUID', '@type': 'DataSet' }}
100
100
  onChange={mockOnChange}
101
101
  value={{
102
102
  items: [
@@ -151,7 +151,7 @@ describe('OrderDocumentsWidget', () => {
151
151
  <MemoryRouter>
152
152
  <OrderDocumentsWidget
153
153
  id="testId"
154
- formData={{ UID: 'someUID' }}
154
+ formData={{ UID: 'someUID', '@type': 'DataSet' }}
155
155
  onChange={mockOnChange}
156
156
  value={{ items: [] }}
157
157
  />
@@ -190,7 +190,7 @@ describe('OrderDocumentsWidget', () => {
190
190
  <MemoryRouter>
191
191
  <OrderDocumentsWidget
192
192
  id="testId"
193
- formData={{ UID: 'someUID' }}
193
+ formData={{ UID: 'someUID', '@type': 'DataSet' }}
194
194
  onChange={mockOnChange}
195
195
  value={{ items: [] }}
196
196
  />
@@ -206,4 +206,35 @@ describe('OrderDocumentsWidget', () => {
206
206
  expect(screen.getByText('Document 3')).toBeInTheDocument();
207
207
  expect(screen.getByText('Document 4')).toBeInTheDocument();
208
208
  });
209
+
210
+ it('renders the widget with documents', async () => {
211
+ act(() => {
212
+ render(
213
+ <Provider store={store}>
214
+ <MemoryRouter>
215
+ <OrderDocumentsWidget
216
+ id="testId"
217
+ formData={{ UID: 'someUID', '@type': 'Product' }}
218
+ onChange={mockOnChange}
219
+ value={{ items: [] }}
220
+ />
221
+ </MemoryRouter>
222
+ </Provider>,
223
+ );
224
+ });
225
+ await Promise.resolve();
226
+
227
+ expect(screen.getByText('Show')).toBeInTheDocument();
228
+ fireEvent.click(screen.getByText('Show'));
229
+
230
+ expect(screen.getByText('Technical Document Title')).toBeInTheDocument();
231
+ expect(screen.getByText('Document 1')).toBeInTheDocument();
232
+ expect(screen.getByText('Document 2')).toBeInTheDocument();
233
+ expect(screen.getByText('Document 3')).toBeInTheDocument();
234
+
235
+ expect(screen.getByText('Hide')).toBeInTheDocument();
236
+ fireEvent.click(screen.getByText('Hide'));
237
+
238
+ expect(screen.getByText('Technical Document Title')).toBeInTheDocument();
239
+ });
209
240
  });
@@ -1,7 +1,7 @@
1
1
  .order-documents-area {
2
2
  width: 100%;
3
3
  max-width: 800px;
4
- margin: 16px auto;
4
+ margin: 16px 0;
5
5
  border: 1px solid #e0e0e0;
6
6
  border-radius: 8px;
7
7
  overflow: hidden;
@@ -41,6 +41,7 @@
41
41
  background-color: #ffffff;
42
42
  transition: background-color 0.2s ease;
43
43
  cursor: grab;
44
+ box-shadow: none;
44
45
  }
45
46
 
46
47
  .document-item:last-child {
@@ -64,4 +65,26 @@
64
65
  background-color: #f0f8ff;
65
66
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
66
67
  }
68
+
69
+ .document-item {
70
+ .ui.basic.icon.button[aria-label='Drag handle'] {
71
+ box-shadow: none;
72
+ }
73
+ }
74
+ }
75
+
76
+ .field-wrapper-technical_documents_order {
77
+ .ui.basic.button.order-docs-button {
78
+ display: inline-block;
79
+ padding: 7px 10px;
80
+ border: 2px solid #007eb1;
81
+ margin-top: 20px;
82
+ border-radius: 10px;
83
+ color: #007eb1 !important;
84
+ cursor: pointer;
85
+ opacity: 0.8;
86
+ box-shadow: none;
87
+ max-width: 200px;
88
+ text-align: center;
89
+ }
67
90
  }