@eeacms/volto-clms-theme 1.0.168 → 1.0.170
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 +32 -0
- package/package.json +2 -2
- package/src/components/Blocks/CclRelatedListingBlock/CclRelatedListingView.jsx +67 -4
- package/src/components/Blocks/CustomTemplates/VoltoSearchBlock/DoubleRangeSpatialFacet.jsx +163 -0
- package/src/components/Blocks/CustomTemplates/VoltoSearchBlock/FilterList.jsx +2 -2
- package/src/components/Blocks/CustomTemplates/VoltoSearchBlock/index.js +2 -0
- package/src/components/Blocks/customBlocks.js +11 -0
- package/src/components/CLMSDatasetDetailView/DownloadDataSetContent.jsx +7 -8
- package/src/components/CLMSDownloadCartView/CLMSCartContent.jsx +188 -103
- package/src/components/CLMSDownloadCartView/cartUtils.js +87 -1
- package/src/components/CLMSDownloadsView/CLMSDownloadTasks.jsx +1 -16
- package/src/components/CclUtils/dynamicSort.js +15 -0
- package/src/components/CclUtils/index.js +2 -3
- package/src/components/CclUtils/useFilteredPagination.js +73 -0
- package/src/customizations/volto-slate/editor/less/editor.less +166 -0
- package/src/customizations/volto-slate/editor/less/globals.less +18 -0
- package/src/index.js +1 -0
- package/theme/clms/css/styles.less +12 -10
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,38 @@ 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.170](https://github.com/eea/volto-clms-theme/compare/1.0.169...1.0.170) - 14 February 2023
|
|
8
|
+
|
|
9
|
+
#### :hammer_and_wrench: Others
|
|
10
|
+
|
|
11
|
+
- Update package.json [Mikel Larreategi - [`3f4bc70`](https://github.com/eea/volto-clms-theme/commit/3f4bc70e0c6468071887c671cda9960b6660b730)]
|
|
12
|
+
### [1.0.169](https://github.com/eea/volto-clms-theme/compare/1.0.168...1.0.169) - 14 February 2023
|
|
13
|
+
|
|
14
|
+
#### :rocket: New Features
|
|
15
|
+
|
|
16
|
+
- feat: add a select for the cart Type column and add the possibility to duplicate a row [ionlizarazu - [`4e4ee1b`](https://github.com/eea/volto-clms-theme/commit/4e4ee1b418a1837da30b94d511f37d9771da75ec)]
|
|
17
|
+
|
|
18
|
+
#### :bug: Bug Fixes
|
|
19
|
+
|
|
20
|
+
- fix: cart icons [ionlizarazu - [`07377c9`](https://github.com/eea/volto-clms-theme/commit/07377c9fa15df658b615c93f5bc23cca4fc94679)]
|
|
21
|
+
- fix: wrong functionalities of cart [ionlizarazu - [`4cb2c78`](https://github.com/eea/volto-clms-theme/commit/4cb2c783fa3f678bdb179d454fced2b0656557eb)]
|
|
22
|
+
|
|
23
|
+
#### :hammer_and_wrench: Others
|
|
24
|
+
|
|
25
|
+
- typo [ionlizarazu - [`39dc6f6`](https://github.com/eea/volto-clms-theme/commit/39dc6f68540fbb9f89f8fa18f4e7319c5031925c)]
|
|
26
|
+
- add search input and pagination to related listing blocks with more than 10 elements [ionlizarazu - [`ea2df24`](https://github.com/eea/volto-clms-theme/commit/ea2df24074b54d4341fa0f9f2bf3f5cf041b8304)]
|
|
27
|
+
- download_full_dataset_text from Plone [ionlizarazu - [`33d57a1`](https://github.com/eea/volto-clms-theme/commit/33d57a1f10bee79693d9bedf31c9e342bd08e07d)]
|
|
28
|
+
- dynamicSort and useFilteredPagination [ionlizarazu - [`3d0c3fe`](https://github.com/eea/volto-clms-theme/commit/3d0c3fe54c0be7e16c05e18149705a53a0291bcf)]
|
|
29
|
+
- don't show selector when there is only one collection for this type [ionlizarazu - [`d741b92`](https://github.com/eea/volto-clms-theme/commit/d741b92bac7336058f40c16e9fc5b5d03dcce36f)]
|
|
30
|
+
- add items as downloadableObjects in case we are rendering them with Universal Link [Mikel Larreategi - [`d6d64d5`](https://github.com/eea/volto-clms-theme/commit/d6d64d57dbff70cc145f2d29a3c173ed348c5ba0)]
|
|
31
|
+
- new DoubleRange facet for Spatial resolutions [ionlizarazu - [`dee81d4`](https://github.com/eea/volto-clms-theme/commit/dee81d407282aae8afeabffa69d2d9668bd50d6d)]
|
|
32
|
+
- search block with no facets [ionlizarazu - [`5ea89fc`](https://github.com/eea/volto-clms-theme/commit/5ea89fc6282143c28fdc2056a85509cda31c26b8)]
|
|
33
|
+
- comment deleted [Unai - [`5dcadea`](https://github.com/eea/volto-clms-theme/commit/5dcadeaf8f4343c527c3676bfbe0a074205d6070)]
|
|
34
|
+
- comment deleted [Unai - [`3dbd923`](https://github.com/eea/volto-clms-theme/commit/3dbd923b37e5734c96c13b954c94dfed0127abea)]
|
|
35
|
+
- unused code [Unai - [`e8c9bce`](https://github.com/eea/volto-clms-theme/commit/e8c9bcefb7d23e7fa5c71443b6b8c3bc802a6ded)]
|
|
36
|
+
- lint fix [Unai - [`620390c`](https://github.com/eea/volto-clms-theme/commit/620390cf7a6f7381bc409c4ddd727207f3d4ea77)]
|
|
37
|
+
- prettier fix [Unai - [`39942ee`](https://github.com/eea/volto-clms-theme/commit/39942ee85949c2277840deb8baa2256ccba42931)]
|
|
38
|
+
- slate style overrided and margin-left -15rem added to fix 1426 [Unai - [`1ff3792`](https://github.com/eea/volto-clms-theme/commit/1ff3792eacd42b527979bd1b4bb905b8e78d1eb3)]
|
|
7
39
|
### [1.0.168](https://github.com/eea/volto-clms-theme/compare/1.0.167...1.0.168) - 7 February 2023
|
|
8
40
|
|
|
9
41
|
#### :bug: Bug Fixes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eeacms/volto-clms-theme",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.170",
|
|
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",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"volto-cookie-banner": "2.1.0",
|
|
38
38
|
"@eeacms/volto-accordion-block": "3.5.0",
|
|
39
39
|
"@eeacms/volto-arcgis-block": "*",
|
|
40
|
-
"@eeacms/volto-clms-utils": "0.1.
|
|
40
|
+
"@eeacms/volto-clms-utils": "0.1.7",
|
|
41
41
|
"@eeacms/volto-columns-block": "4.4.3",
|
|
42
42
|
"@eeacms/volto-metadata-block": "^2.1.0",
|
|
43
43
|
"@eeacms/volto-react-table-widget": "0.1.1",
|
|
@@ -1,12 +1,22 @@
|
|
|
1
|
+
import React from 'react';
|
|
1
2
|
import { useDispatch, useSelector } from 'react-redux';
|
|
3
|
+
import { Segment, Input, Pagination } from 'semantic-ui-react';
|
|
2
4
|
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import config from '@plone/volto/registry';
|
|
5
5
|
import { searchContent } from '@plone/volto/actions';
|
|
6
|
-
import {
|
|
6
|
+
import { Icon } from '@plone/volto/components';
|
|
7
|
+
import paginationLeftSVG from '@plone/volto/icons/left-key.svg';
|
|
8
|
+
import paginationRightSVG from '@plone/volto/icons/right-key.svg';
|
|
9
|
+
import config from '@plone/volto/registry';
|
|
10
|
+
|
|
11
|
+
import { useFilteredPagination } from '../../CclUtils/useFilteredPagination';
|
|
7
12
|
|
|
8
13
|
const CclRelatedListingView = (props) => {
|
|
9
14
|
const { data, id, properties, metadata } = props;
|
|
15
|
+
const use_pagination = useFilteredPagination([]);
|
|
16
|
+
const p_functions = use_pagination.functions;
|
|
17
|
+
const p_data = use_pagination.data;
|
|
18
|
+
const { pagination, currentPage, paginationSize, dataList } = p_data;
|
|
19
|
+
|
|
10
20
|
const dispatch = useDispatch();
|
|
11
21
|
const searchSubrequests = useSelector(
|
|
12
22
|
(state) => state.search.subrequests?.[props.id],
|
|
@@ -59,6 +69,11 @@ const CclRelatedListingView = (props) => {
|
|
|
59
69
|
}
|
|
60
70
|
|
|
61
71
|
React.useEffect(() => {
|
|
72
|
+
if (searchSubrequests?.loaded) {
|
|
73
|
+
p_functions.setOriginalDataList([...searchSubrequests.items]);
|
|
74
|
+
p_functions.setDataList([...searchSubrequests.items]);
|
|
75
|
+
}
|
|
76
|
+
|
|
62
77
|
uid &&
|
|
63
78
|
!searchSubrequests?.loading &&
|
|
64
79
|
!searchSubrequests?.loaded &&
|
|
@@ -83,7 +98,55 @@ const CclRelatedListingView = (props) => {
|
|
|
83
98
|
return (
|
|
84
99
|
<>
|
|
85
100
|
{searchSubrequests?.loaded && libraries.length > 0 ? (
|
|
86
|
-
<
|
|
101
|
+
<div>
|
|
102
|
+
{paginationSize < libraries.length && (
|
|
103
|
+
<div className="block search">
|
|
104
|
+
<div className="search-wrapper">
|
|
105
|
+
<div className="search-input">
|
|
106
|
+
<Input
|
|
107
|
+
id={`${props.id}-searchtext`}
|
|
108
|
+
placeholder={'Search in the following items'}
|
|
109
|
+
fluid
|
|
110
|
+
onChange={(event, value) => {
|
|
111
|
+
p_functions.applySearch(event, value, 'title');
|
|
112
|
+
p_functions.setCurrentPage(1);
|
|
113
|
+
}}
|
|
114
|
+
/>
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
)}
|
|
119
|
+
<TemplateView items={pagination} variation={template_id} />
|
|
120
|
+
{dataList.length / paginationSize > 1 && (
|
|
121
|
+
<div className="pagination-wrapper">
|
|
122
|
+
<Pagination
|
|
123
|
+
activePage={currentPage}
|
|
124
|
+
totalPages={Math.ceil(dataList.length / paginationSize)}
|
|
125
|
+
onPageChange={(e, { activePage }) => {
|
|
126
|
+
p_functions.setCurrentPage(activePage);
|
|
127
|
+
}}
|
|
128
|
+
firstItem={null}
|
|
129
|
+
lastItem={null}
|
|
130
|
+
prevItem={{
|
|
131
|
+
content: <Icon name={paginationLeftSVG} size="18px" />,
|
|
132
|
+
icon: true,
|
|
133
|
+
'aria-disabled': currentPage === 1,
|
|
134
|
+
className: currentPage === 1 ? 'disabled' : null,
|
|
135
|
+
}}
|
|
136
|
+
nextItem={{
|
|
137
|
+
content: <Icon name={paginationRightSVG} size="18px" />,
|
|
138
|
+
icon: true,
|
|
139
|
+
'aria-disabled':
|
|
140
|
+
currentPage === Math.ceil(dataList.length / paginationSize),
|
|
141
|
+
className:
|
|
142
|
+
currentPage === Math.ceil(dataList.length / paginationSize)
|
|
143
|
+
? 'disabled'
|
|
144
|
+
: null,
|
|
145
|
+
}}
|
|
146
|
+
></Pagination>
|
|
147
|
+
</div>
|
|
148
|
+
)}
|
|
149
|
+
</div>
|
|
87
150
|
) : (
|
|
88
151
|
<p>There are no related items.</p>
|
|
89
152
|
)}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import 'react-input-range/lib/css/index.css';
|
|
2
|
+
import './range.css';
|
|
3
|
+
|
|
4
|
+
import React from 'react';
|
|
5
|
+
|
|
6
|
+
import InputRange from 'react-input-range';
|
|
7
|
+
import { Segment } from 'semantic-ui-react';
|
|
8
|
+
import {
|
|
9
|
+
selectFacetStateToValue,
|
|
10
|
+
selectFacetValueToQuery,
|
|
11
|
+
} from '@plone/volto/components/manage/Blocks/Search/components/base';
|
|
12
|
+
|
|
13
|
+
const doubleRangeSpatialFacetSchemaEnhancer = ({ schema, formData }) => {
|
|
14
|
+
// adds (enables) the 'multiple' field after the 'type' dropdown
|
|
15
|
+
let { fields } = schema.fieldsets[0];
|
|
16
|
+
const pos = fields.indexOf('type') + 1;
|
|
17
|
+
fields = [
|
|
18
|
+
...fields.slice(0, pos),
|
|
19
|
+
'step',
|
|
20
|
+
'multiple',
|
|
21
|
+
...fields.slice(pos, fields.length),
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
schema.properties = {
|
|
25
|
+
...schema.properties,
|
|
26
|
+
step: { title: 'Step', type: 'number', default: 1 },
|
|
27
|
+
};
|
|
28
|
+
schema.fieldsets[0].fields = fields;
|
|
29
|
+
return schema;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const mToKm = (m) => {
|
|
33
|
+
return m >= 1000 ? Math.round((m / 1000) * 10) / 10 + 'km' : m + 'm';
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const realToCoded = (number, step) => {
|
|
37
|
+
// the meters are going to be the same
|
|
38
|
+
if (number <= 1000) return number;
|
|
39
|
+
// for the km we are going to code any km after the first as tens
|
|
40
|
+
// so 2 km will be 1020 and 3 km will be 1040
|
|
41
|
+
const relation = step ? parseInt(step) : 1;
|
|
42
|
+
const thousands = Math.floor(number / 1000);
|
|
43
|
+
const hundreds = Math.floor((number - thousands * 1000) / 100);
|
|
44
|
+
const tens = Math.floor((number - thousands * 1000 - hundreds * 100) / 10);
|
|
45
|
+
let finalThousands = thousands;
|
|
46
|
+
if (hundreds > 0 || tens > 0) finalThousands = thousands + 1;
|
|
47
|
+
return 1000 + parseInt(finalThousands * relation);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const codedToReal = (number, step) => {
|
|
51
|
+
// the meters are going to be the same
|
|
52
|
+
if (number <= 1000) return number;
|
|
53
|
+
// for the km we have to decode any tens after 1000
|
|
54
|
+
// so 1020 will be 2 km and 1040 will be 3 km
|
|
55
|
+
const relation = step ? parseInt(step) : 1;
|
|
56
|
+
const codedThousands = parseInt(number) - 1000;
|
|
57
|
+
return parseInt(codedThousands * (1000 / relation));
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const convertToRange = (values, step) => {
|
|
61
|
+
return {
|
|
62
|
+
min: realToCoded(
|
|
63
|
+
Math.min.apply(
|
|
64
|
+
Math,
|
|
65
|
+
values.map(function (o) {
|
|
66
|
+
return o.value.replace(/[a-zA-Z]/, '');
|
|
67
|
+
}),
|
|
68
|
+
),
|
|
69
|
+
step,
|
|
70
|
+
),
|
|
71
|
+
max: realToCoded(
|
|
72
|
+
Math.max.apply(
|
|
73
|
+
Math,
|
|
74
|
+
values.map(function (o) {
|
|
75
|
+
return o.value.replace(/[a-zA-Z]/, '');
|
|
76
|
+
}),
|
|
77
|
+
),
|
|
78
|
+
step,
|
|
79
|
+
),
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const DoubleRangeSpatialFacet = (props) => {
|
|
84
|
+
const { facet, choices, onChange, value } = props;
|
|
85
|
+
const facetValue = value;
|
|
86
|
+
var [open, setOpen] = React.useState(false);
|
|
87
|
+
|
|
88
|
+
const startingValues = convertToRange(choices, facet?.step);
|
|
89
|
+
|
|
90
|
+
const onChangeRange = (nValue, onChangeR, sValue) => {
|
|
91
|
+
const fixedValue = {
|
|
92
|
+
min: nValue.min < sValue.min ? sValue.min : nValue.min,
|
|
93
|
+
max: nValue.max > sValue.max ? sValue.max : nValue.max,
|
|
94
|
+
};
|
|
95
|
+
onChangeR(
|
|
96
|
+
facet.field.value,
|
|
97
|
+
[...Array(fixedValue.max - fixedValue.min + 1).keys()].map((i) =>
|
|
98
|
+
(i + fixedValue.min).toString(),
|
|
99
|
+
),
|
|
100
|
+
);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<fieldset className="ccl-fieldset">
|
|
105
|
+
<div
|
|
106
|
+
className="ccl-expandable__button"
|
|
107
|
+
aria-expanded={open}
|
|
108
|
+
onClick={() => setOpen(!open)}
|
|
109
|
+
onKeyDown={() => setOpen(!open)}
|
|
110
|
+
tabIndex={0}
|
|
111
|
+
role={'button'}
|
|
112
|
+
>
|
|
113
|
+
<legend className="ccl-form-legend">{facet.title}</legend>
|
|
114
|
+
</div>
|
|
115
|
+
<div className="range-container">
|
|
116
|
+
<Segment basic padded>
|
|
117
|
+
<InputRange
|
|
118
|
+
minValue={startingValues.min}
|
|
119
|
+
maxValue={startingValues.max}
|
|
120
|
+
step={facet.step ? parseInt(facet.step) : 1}
|
|
121
|
+
value={
|
|
122
|
+
facetValue.length > 0
|
|
123
|
+
? {
|
|
124
|
+
min: convertToRange(facetValue, facet?.step).min,
|
|
125
|
+
max: convertToRange(facetValue, facet?.step).max,
|
|
126
|
+
}
|
|
127
|
+
: {
|
|
128
|
+
min: startingValues.min,
|
|
129
|
+
max: startingValues.max,
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
onChange={(changedValue) =>
|
|
133
|
+
onChangeRange(
|
|
134
|
+
{
|
|
135
|
+
min: codedToReal(changedValue.min, facet?.step),
|
|
136
|
+
max: codedToReal(changedValue.max, facet?.step),
|
|
137
|
+
},
|
|
138
|
+
onChange,
|
|
139
|
+
{
|
|
140
|
+
min: codedToReal(startingValues.min, facet?.step),
|
|
141
|
+
max: codedToReal(startingValues.max, facet?.step),
|
|
142
|
+
},
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
formatLabel={(value) => {
|
|
146
|
+
if (facet.field.value === 'spatial_resolution') {
|
|
147
|
+
return mToKm(codedToReal(value, facet?.step));
|
|
148
|
+
} else {
|
|
149
|
+
return value;
|
|
150
|
+
}
|
|
151
|
+
}}
|
|
152
|
+
/>
|
|
153
|
+
</Segment>
|
|
154
|
+
<br />
|
|
155
|
+
</div>
|
|
156
|
+
</fieldset>
|
|
157
|
+
);
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
DoubleRangeSpatialFacet.schemaEnhancer = doubleRangeSpatialFacetSchemaEnhancer;
|
|
161
|
+
DoubleRangeSpatialFacet.stateToValue = selectFacetStateToValue;
|
|
162
|
+
DoubleRangeSpatialFacet.valueToQuery = selectFacetValueToQuery;
|
|
163
|
+
export default DoubleRangeSpatialFacet;
|
|
@@ -18,14 +18,14 @@ const FilterList = (props) => {
|
|
|
18
18
|
const { facets, setFacets, isEditMode, data, querystring } = props;
|
|
19
19
|
const showFilterList = !Object.values(facets).every((facet) => !facet.length);
|
|
20
20
|
|
|
21
|
-
const baseFacets = data
|
|
21
|
+
const baseFacets = data?.facets;
|
|
22
22
|
const currentFilters = Object.fromEntries(
|
|
23
23
|
Object.entries(facets)
|
|
24
24
|
.filter((v) => v[1] && v[0] !== 'SearchableText')
|
|
25
25
|
.filter(
|
|
26
26
|
(v) =>
|
|
27
27
|
v[1] &&
|
|
28
|
-
baseFacets
|
|
28
|
+
baseFacets?.length > 0 &&
|
|
29
29
|
baseFacets.map((bf) => bf.field?.value).includes(v[0]),
|
|
30
30
|
),
|
|
31
31
|
);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import DoubleRangeSpatialFacet from './DoubleRangeSpatialFacet';
|
|
1
2
|
import DoubleRangeFacet from './DoubleRangeFacet';
|
|
2
3
|
import AccordionFacet from './AccordionFacet';
|
|
3
4
|
import RightModalFacets from './RightModalFacets';
|
|
@@ -11,6 +12,7 @@ export {
|
|
|
11
12
|
AccordionFacet,
|
|
12
13
|
WithType,
|
|
13
14
|
DoubleRangeFacet,
|
|
15
|
+
DoubleRangeSpatialFacet,
|
|
14
16
|
CheckboxTreeFacet,
|
|
15
17
|
CheckboxTreeParentFacet,
|
|
16
18
|
rewriteOptions,
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
RightModalFacets,
|
|
4
4
|
WithType,
|
|
5
5
|
DoubleRangeFacet,
|
|
6
|
+
DoubleRangeSpatialFacet,
|
|
6
7
|
CheckboxTreeFacet,
|
|
7
8
|
CheckboxTreeParentFacet,
|
|
8
9
|
rewriteOptions,
|
|
@@ -385,6 +386,16 @@ const customBlocks = (config) => ({
|
|
|
385
386
|
valueToQuery: DoubleRangeFacet.valueToQuery,
|
|
386
387
|
filterListComponent: SelectFacetFilterListEntry,
|
|
387
388
|
},
|
|
389
|
+
{
|
|
390
|
+
id: 'doubleRangeSpatialFacet',
|
|
391
|
+
title: 'Double Range for Spatial Resolutions',
|
|
392
|
+
view: WithType(DoubleRangeSpatialFacet, 'range'),
|
|
393
|
+
isDefault: false,
|
|
394
|
+
schemaEnhancer: DoubleRangeSpatialFacet.schemaEnhancer,
|
|
395
|
+
stateToValue: DoubleRangeSpatialFacet.stateToValue,
|
|
396
|
+
valueToQuery: DoubleRangeSpatialFacet.valueToQuery,
|
|
397
|
+
filterListComponent: SelectFacetFilterListEntry,
|
|
398
|
+
},
|
|
388
399
|
{
|
|
389
400
|
id: 'checkboxTreeFacet',
|
|
390
401
|
title: 'Checkbox Tree',
|
|
@@ -6,7 +6,7 @@ import { useLocation } from 'react-router-dom';
|
|
|
6
6
|
import CclButton from '@eeacms/volto-clms-theme/components/CclButton/CclButton';
|
|
7
7
|
import CclDownloadTable from '@eeacms/volto-clms-theme/components/CclDownloadTable/CclDownloadTable';
|
|
8
8
|
import CclLoginModal from '@eeacms/volto-clms-theme/components/CclLoginModal/CclLoginModal';
|
|
9
|
-
import {
|
|
9
|
+
import { StringToHTML } from '@eeacms/volto-clms-theme/components/CclUtils';
|
|
10
10
|
|
|
11
11
|
const DownloadDataSetContent = (data, token) => {
|
|
12
12
|
const location = useLocation();
|
|
@@ -58,13 +58,12 @@ const DownloadDataSetContent = (data, token) => {
|
|
|
58
58
|
<br />
|
|
59
59
|
<br />
|
|
60
60
|
<h2>Download full dataset</h2>
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
</p>
|
|
61
|
+
{data.download_full_dataset_text?.data && (
|
|
62
|
+
<StringToHTML
|
|
63
|
+
string={data.download_full_dataset_text?.data || ''}
|
|
64
|
+
/>
|
|
65
|
+
)}
|
|
66
|
+
|
|
68
67
|
{/* {data.token === '' ? (
|
|
69
68
|
<CclButton
|
|
70
69
|
url={location.pathname + '/download-by-area'}
|
|
@@ -1,33 +1,38 @@
|
|
|
1
|
-
/* eslint-disable react-hooks/exhaustive-deps */
|
|
2
|
-
/**
|
|
3
|
-
* CLMSCartContent container.
|
|
4
|
-
* @module components/CLMSDownloadCartView/CLMSCartContent
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { Checkbox, Modal, Segment, Select } from 'semantic-ui-react';
|
|
8
1
|
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { useDispatch, useSelector } from 'react-redux';
|
|
3
|
+
import { Checkbox, Modal, Segment, Select } from 'semantic-ui-react';
|
|
4
|
+
|
|
5
|
+
import { Icon } from '@plone/volto/components';
|
|
6
|
+
import { Toast } from '@plone/volto/components';
|
|
7
|
+
import removeSVG from '@plone/volto/icons/delete.svg';
|
|
8
|
+
import addDocumentSVG from '@plone/volto/icons/add-document.svg';
|
|
9
|
+
import CclButton from '@eeacms/volto-clms-theme/components/CclButton/CclButton';
|
|
10
|
+
import useCartState from '@eeacms/volto-clms-utils/cart/useCartState';
|
|
11
|
+
import { cleanDuplicatesEntries } from '@eeacms/volto-clms-utils/utils';
|
|
12
|
+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
13
|
+
|
|
14
|
+
import { getDownloadtool, postDownloadtool } from '../../actions';
|
|
9
15
|
import {
|
|
10
|
-
getCartObjectFromMapviewer,
|
|
11
|
-
getCartObjectFromPrepackaged,
|
|
12
16
|
getDownloadToolPostBody,
|
|
13
17
|
formatNaming,
|
|
14
18
|
originalFormatNaming,
|
|
19
|
+
getCollectionByItem,
|
|
20
|
+
duplicateCartItem,
|
|
21
|
+
concatRequestedCartItem,
|
|
15
22
|
} from './cartUtils';
|
|
16
|
-
import { getDownloadtool, postDownloadtool } from '../../actions';
|
|
17
|
-
import { useDispatch, useSelector } from 'react-redux';
|
|
18
|
-
|
|
19
|
-
import CclButton from '@eeacms/volto-clms-theme/components/CclButton/CclButton';
|
|
20
|
-
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
21
|
-
import { Toast } from '@plone/volto/components';
|
|
22
|
-
import { cleanDuplicatesEntries } from '@eeacms/volto-clms-utils/utils';
|
|
23
23
|
import { getAvailableConversion } from './conversion';
|
|
24
24
|
import { toast } from 'react-toastify';
|
|
25
|
-
|
|
25
|
+
|
|
26
|
+
/* eslint-disable react-hooks/exhaustive-deps */
|
|
27
|
+
/**
|
|
28
|
+
* CLMSCartContent container.
|
|
29
|
+
* @module components/CLMSDownloadCartView/CLMSCartContent
|
|
30
|
+
*/
|
|
26
31
|
|
|
27
32
|
const CLMSCartContent = (props) => {
|
|
28
33
|
const { localSessionCart } = props;
|
|
29
34
|
const dispatch = useDispatch();
|
|
30
|
-
const { removeCartItem, removeCartItems } = useCartState();
|
|
35
|
+
const { removeCartItem, removeCartItems, updateCart } = useCartState();
|
|
31
36
|
|
|
32
37
|
// state connections
|
|
33
38
|
const cart = useSelector((state) => state.cart_items.items);
|
|
@@ -67,46 +72,17 @@ const CLMSCartContent = (props) => {
|
|
|
67
72
|
cart.length > 0 &&
|
|
68
73
|
cart.length !== newCart.length
|
|
69
74
|
) {
|
|
70
|
-
concatRequestedCartItem(
|
|
75
|
+
concatRequestedCartItem(
|
|
76
|
+
cartItems,
|
|
77
|
+
setCartItems,
|
|
78
|
+
localSessionCart,
|
|
79
|
+
datasets_items,
|
|
80
|
+
projections,
|
|
81
|
+
nutsnames,
|
|
82
|
+
);
|
|
71
83
|
}
|
|
72
84
|
}, [cart, datasets_items]);
|
|
73
85
|
|
|
74
|
-
useEffect(() => {
|
|
75
|
-
if (Object.keys(nutsnames).length > 0 && cart.length > 0) {
|
|
76
|
-
concatRequestedCartItem();
|
|
77
|
-
}
|
|
78
|
-
}, [nutsnames]);
|
|
79
|
-
|
|
80
|
-
function concatRequestedCartItem() {
|
|
81
|
-
let newCartItems = [...cartItems];
|
|
82
|
-
localSessionCart.forEach((localItem) => {
|
|
83
|
-
const requestedItem = datasets_items
|
|
84
|
-
? datasets_items.find((req) => req.UID === localItem.UID)
|
|
85
|
-
: false;
|
|
86
|
-
if (requestedItem) {
|
|
87
|
-
const file_data = requestedItem?.downloadable_files?.items.find(
|
|
88
|
-
(item) => item['@id'] === localItem.file_id,
|
|
89
|
-
);
|
|
90
|
-
if (file_data) {
|
|
91
|
-
newCartItems.push(
|
|
92
|
-
getCartObjectFromPrepackaged(file_data, requestedItem),
|
|
93
|
-
);
|
|
94
|
-
setCartItems(cleanDuplicatesEntries(newCartItems));
|
|
95
|
-
} else {
|
|
96
|
-
newCartItems.push(
|
|
97
|
-
getCartObjectFromMapviewer(
|
|
98
|
-
localItem,
|
|
99
|
-
requestedItem,
|
|
100
|
-
projections,
|
|
101
|
-
nutsnames,
|
|
102
|
-
),
|
|
103
|
-
);
|
|
104
|
-
setCartItems(cleanDuplicatesEntries(newCartItems));
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
|
|
110
86
|
const selectAllCart = (checked) => {
|
|
111
87
|
if (checked) {
|
|
112
88
|
setCartSelection(
|
|
@@ -212,8 +188,11 @@ const CLMSCartContent = (props) => {
|
|
|
212
188
|
}
|
|
213
189
|
};
|
|
214
190
|
|
|
215
|
-
const TypeNaming = (
|
|
216
|
-
const
|
|
191
|
+
const TypeNaming = ({ item }) => {
|
|
192
|
+
const types_options =
|
|
193
|
+
item?.type_options?.length > 0
|
|
194
|
+
? [...new Set(item.type_options.map((ddi) => ddi.name))]
|
|
195
|
+
: [];
|
|
217
196
|
if (item.file_id) {
|
|
218
197
|
return (
|
|
219
198
|
<span className={'tag tag-' + item?.type?.toLowerCase()}>
|
|
@@ -223,22 +202,51 @@ const CLMSCartContent = (props) => {
|
|
|
223
202
|
} else if (!item.type) {
|
|
224
203
|
return '-';
|
|
225
204
|
} else {
|
|
226
|
-
let
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
205
|
+
let defaultType = getCollectionByItem(item);
|
|
206
|
+
return types_options.length > 1 ? (
|
|
207
|
+
<Select
|
|
208
|
+
placeholder="Select type"
|
|
209
|
+
value={defaultType.name}
|
|
210
|
+
options={types_options.map((option) => {
|
|
211
|
+
return {
|
|
212
|
+
key: option,
|
|
213
|
+
value: option,
|
|
214
|
+
text: option,
|
|
215
|
+
};
|
|
216
|
+
})}
|
|
217
|
+
onChange={(e, data) => {
|
|
218
|
+
const new_cartItems = [...cartItems];
|
|
219
|
+
const objIndex = new_cartItems.findIndex(
|
|
220
|
+
(obj) => obj.unique_id === item.unique_id,
|
|
221
|
+
);
|
|
222
|
+
const first_type_id = item.type_options.filter(
|
|
223
|
+
(t_o) => t_o.name === data.value,
|
|
224
|
+
)[0].id;
|
|
225
|
+
new_cartItems[objIndex].type = first_type_id;
|
|
226
|
+
const dataset = datasets_items
|
|
227
|
+
? datasets_items.find((req) => req.UID === item.dataset_uid)
|
|
228
|
+
: false;
|
|
229
|
+
const format_item = dataset.dataset_download_information.items.find(
|
|
230
|
+
(item) => item['@id'] === first_type_id,
|
|
231
|
+
);
|
|
232
|
+
new_cartItems[objIndex].format = format_item.full_format;
|
|
233
|
+
setCartItems([...new_cartItems]);
|
|
234
|
+
}}
|
|
235
|
+
/>
|
|
236
|
+
) : (
|
|
237
|
+
defaultType.name
|
|
238
|
+
);
|
|
230
239
|
}
|
|
231
240
|
};
|
|
232
241
|
|
|
233
|
-
const CollectionNaming = (
|
|
234
|
-
const { item } = typeProps;
|
|
242
|
+
const CollectionNaming = ({ item }) => {
|
|
235
243
|
if (item.file_id) {
|
|
236
244
|
return '-';
|
|
237
245
|
} else if (!item.type) {
|
|
238
246
|
return '-';
|
|
239
247
|
}
|
|
240
|
-
|
|
241
|
-
|
|
248
|
+
return item.type_options.filter((t_o) => t_o.id === item.type).length >
|
|
249
|
+
1 ? (
|
|
242
250
|
<Select
|
|
243
251
|
placeholder="Select type"
|
|
244
252
|
value={
|
|
@@ -248,30 +256,65 @@ const CLMSCartContent = (props) => {
|
|
|
248
256
|
}
|
|
249
257
|
options={
|
|
250
258
|
item?.type_options?.length > 0 &&
|
|
251
|
-
item?.type_options
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
+
item?.type_options
|
|
260
|
+
.filter(
|
|
261
|
+
(o) =>
|
|
262
|
+
o.name ===
|
|
263
|
+
item?.type_options.find((t_o) => t_o.id === item.type).name,
|
|
264
|
+
)
|
|
265
|
+
.map((option) => {
|
|
266
|
+
return {
|
|
267
|
+
key: option.id,
|
|
268
|
+
value: option.id,
|
|
269
|
+
text: option.collection ?? '-',
|
|
270
|
+
};
|
|
271
|
+
})
|
|
259
272
|
}
|
|
260
273
|
onChange={(e, data) => {
|
|
261
|
-
const
|
|
274
|
+
const new_cartItems = [...cartItems];
|
|
275
|
+
const objIndex = new_cartItems.findIndex(
|
|
262
276
|
(obj) => obj.unique_id === item.unique_id,
|
|
263
277
|
);
|
|
264
|
-
|
|
278
|
+
new_cartItems[objIndex].type = data.value;
|
|
265
279
|
const dataset = datasets_items
|
|
266
280
|
? datasets_items.find((req) => req.UID === item.dataset_uid)
|
|
267
281
|
: false;
|
|
268
282
|
const format_item = dataset.dataset_download_information.items.find(
|
|
269
283
|
(item) => item['@id'] === data.value,
|
|
270
284
|
);
|
|
271
|
-
|
|
272
|
-
setCartItems([...
|
|
285
|
+
new_cartItems[objIndex].format = format_item.full_format;
|
|
286
|
+
setCartItems([...new_cartItems]);
|
|
273
287
|
}}
|
|
274
288
|
/>
|
|
289
|
+
) : (
|
|
290
|
+
getCollectionByItem(item).collection ?? '-'
|
|
291
|
+
);
|
|
292
|
+
};
|
|
293
|
+
const FormatNaming = ({ item }) => {
|
|
294
|
+
const format_options = getAvailableConversion(
|
|
295
|
+
formatConversionTable,
|
|
296
|
+
originalFormatNaming(item),
|
|
297
|
+
);
|
|
298
|
+
const item_format_name = formatNaming(item);
|
|
299
|
+
return !item.file_id ? (
|
|
300
|
+
format_options.length > 1 ? (
|
|
301
|
+
<Select
|
|
302
|
+
placeholder="Select format"
|
|
303
|
+
value={item_format_name}
|
|
304
|
+
options={format_options}
|
|
305
|
+
onChange={(e, data) => {
|
|
306
|
+
const objIndex = cartItems.findIndex(
|
|
307
|
+
(obj) => obj.unique_id === item.unique_id,
|
|
308
|
+
);
|
|
309
|
+
cartItems[objIndex].format = data.value;
|
|
310
|
+
setCartItems([...cartItems]);
|
|
311
|
+
}}
|
|
312
|
+
/>
|
|
313
|
+
) : (
|
|
314
|
+
item_format_name
|
|
315
|
+
)
|
|
316
|
+
) : (
|
|
317
|
+
item_format_name
|
|
275
318
|
);
|
|
276
319
|
};
|
|
277
320
|
|
|
@@ -307,6 +350,7 @@ const CLMSCartContent = (props) => {
|
|
|
307
350
|
<th>Format</th>
|
|
308
351
|
<th>Projection</th>
|
|
309
352
|
<th></th>
|
|
353
|
+
<th></th>
|
|
310
354
|
</tr>
|
|
311
355
|
</thead>
|
|
312
356
|
<tbody>
|
|
@@ -364,25 +408,7 @@ const CLMSCartContent = (props) => {
|
|
|
364
408
|
<CollectionNaming item={item} />
|
|
365
409
|
</td>
|
|
366
410
|
<td className="table-td-format">
|
|
367
|
-
{
|
|
368
|
-
<Select
|
|
369
|
-
placeholder="Select format"
|
|
370
|
-
value={formatNaming(item)}
|
|
371
|
-
options={getAvailableConversion(
|
|
372
|
-
formatConversionTable,
|
|
373
|
-
originalFormatNaming(item),
|
|
374
|
-
)}
|
|
375
|
-
onChange={(e, data) => {
|
|
376
|
-
const objIndex = cartItems.findIndex(
|
|
377
|
-
(obj) => obj.unique_id === item.unique_id,
|
|
378
|
-
);
|
|
379
|
-
cartItems[objIndex].format = data.value;
|
|
380
|
-
setCartItems([...cartItems]);
|
|
381
|
-
}}
|
|
382
|
-
/>
|
|
383
|
-
) : (
|
|
384
|
-
formatNaming(item)
|
|
385
|
-
)}
|
|
411
|
+
<FormatNaming item={item} />
|
|
386
412
|
</td>
|
|
387
413
|
<td className="table-td-projections">
|
|
388
414
|
{!item.file_id ? (
|
|
@@ -407,14 +433,73 @@ const CLMSCartContent = (props) => {
|
|
|
407
433
|
<td>
|
|
408
434
|
{item.task_in_progress ? (
|
|
409
435
|
<FontAwesomeIcon icon="spinner" spin />
|
|
436
|
+
) : !item.file_id ? (
|
|
437
|
+
<span
|
|
438
|
+
className="info-icon"
|
|
439
|
+
tooltip="Add a duplicated row below"
|
|
440
|
+
direction="up"
|
|
441
|
+
>
|
|
442
|
+
<button
|
|
443
|
+
onClick={() => {
|
|
444
|
+
duplicateCartItem(
|
|
445
|
+
item.unique_id,
|
|
446
|
+
cartItems,
|
|
447
|
+
setCartItems,
|
|
448
|
+
updateCart,
|
|
449
|
+
);
|
|
450
|
+
}}
|
|
451
|
+
style={{
|
|
452
|
+
backgroundColor: 'transparent',
|
|
453
|
+
color: 'inherit',
|
|
454
|
+
border: 'none',
|
|
455
|
+
padding: 0,
|
|
456
|
+
font: 'inherit',
|
|
457
|
+
cursor: 'pointer',
|
|
458
|
+
outline: 'inherit',
|
|
459
|
+
}}
|
|
460
|
+
>
|
|
461
|
+
<Icon
|
|
462
|
+
name={addDocumentSVG}
|
|
463
|
+
size={25}
|
|
464
|
+
title={'Add a duplicated row below'}
|
|
465
|
+
/>
|
|
466
|
+
</button>
|
|
467
|
+
</span>
|
|
410
468
|
) : (
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
469
|
+
<></>
|
|
470
|
+
)}
|
|
471
|
+
</td>
|
|
472
|
+
<td>
|
|
473
|
+
{item.task_in_progress ? (
|
|
474
|
+
<FontAwesomeIcon icon="spinner" spin />
|
|
475
|
+
) : (
|
|
476
|
+
<span
|
|
477
|
+
className="info-icon"
|
|
478
|
+
tooltip="Remove this row from the cart"
|
|
479
|
+
direction="up"
|
|
480
|
+
>
|
|
481
|
+
<button
|
|
482
|
+
onClick={() => {
|
|
483
|
+
removeCartItem(item.unique_id);
|
|
484
|
+
}}
|
|
485
|
+
style={{
|
|
486
|
+
backgroundColor: 'transparent',
|
|
487
|
+
color: 'inherit',
|
|
488
|
+
border: 'none',
|
|
489
|
+
padding: 0,
|
|
490
|
+
font: 'inherit',
|
|
491
|
+
cursor: 'pointer',
|
|
492
|
+
outline: 'inherit',
|
|
493
|
+
}}
|
|
494
|
+
>
|
|
495
|
+
<Icon
|
|
496
|
+
name={removeSVG}
|
|
497
|
+
size={25}
|
|
498
|
+
color="#e40166"
|
|
499
|
+
title={'Remove this row from the cart'}
|
|
500
|
+
/>
|
|
501
|
+
</button>
|
|
502
|
+
</span>
|
|
418
503
|
)}
|
|
419
504
|
</td>
|
|
420
505
|
</tr>
|
|
@@ -1,13 +1,22 @@
|
|
|
1
|
+
import { cleanDuplicatesEntries } from '@eeacms/volto-clms-utils/utils';
|
|
2
|
+
|
|
1
3
|
export const formatNaming = (item) => {
|
|
2
4
|
return item?.format?.token || item?.format;
|
|
3
5
|
};
|
|
4
6
|
|
|
5
7
|
export const originalFormatNaming = (item) => {
|
|
6
8
|
const original = item?.original_format?.token || item?.original_format;
|
|
7
|
-
const
|
|
9
|
+
const collection = getCollectionByItem(item);
|
|
10
|
+
const format = collection?.full_format?.token || collection?.full_format;
|
|
8
11
|
return format ? format : original;
|
|
9
12
|
};
|
|
10
13
|
|
|
14
|
+
export const getCollectionByItem = (item) => {
|
|
15
|
+
return item?.type_options
|
|
16
|
+
? item.type_options.find((t_o) => t_o['id'] === item.type)
|
|
17
|
+
: { id: '' };
|
|
18
|
+
};
|
|
19
|
+
|
|
11
20
|
export const getDownloadToolPostBody = (selectedItems) => {
|
|
12
21
|
const datasetList = selectedItems.map((item) => {
|
|
13
22
|
let body_extras = {};
|
|
@@ -108,3 +117,80 @@ export const getCartObjectFromMapviewer = (
|
|
|
108
117
|
timeExtent: local_cart_data.timeExtent || [],
|
|
109
118
|
};
|
|
110
119
|
};
|
|
120
|
+
|
|
121
|
+
export const duplicateCartItem = (
|
|
122
|
+
unique_id,
|
|
123
|
+
cartItems,
|
|
124
|
+
setCartItems,
|
|
125
|
+
updateCart,
|
|
126
|
+
) => {
|
|
127
|
+
if (cartItems.length > 0) {
|
|
128
|
+
const itemIndex = cartItems.findIndex((obj) => obj.unique_id === unique_id);
|
|
129
|
+
const new_item = Object.assign(
|
|
130
|
+
{},
|
|
131
|
+
{
|
|
132
|
+
...cartItems[itemIndex],
|
|
133
|
+
unique_id: cartItems[itemIndex].unique_id + '-copy',
|
|
134
|
+
},
|
|
135
|
+
);
|
|
136
|
+
while (cartItems.some((c_i) => c_i.unique_id === new_item.unique_id)) {
|
|
137
|
+
new_item['unique_id'] = new_item.unique_id + '-copy';
|
|
138
|
+
}
|
|
139
|
+
cartItems.splice(itemIndex + 1, 0, new_item);
|
|
140
|
+
refreshCart(cartItems, setCartItems, updateCart);
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
export const refreshCart = (cartItems, setCartItems, updateCart) => {
|
|
145
|
+
setCartItems([...cartItems]);
|
|
146
|
+
updateCart([
|
|
147
|
+
...cartItems.map((c_i) => {
|
|
148
|
+
const file_id = c_i.file_id ? { file_id: c_i.file_id } : {};
|
|
149
|
+
const id = c_i.id ? { id: c_i.id } : {};
|
|
150
|
+
return {
|
|
151
|
+
...file_id,
|
|
152
|
+
...id,
|
|
153
|
+
UID: c_i.dataset_uid,
|
|
154
|
+
unique_id: c_i.unique_id,
|
|
155
|
+
area: c_i.area,
|
|
156
|
+
};
|
|
157
|
+
}),
|
|
158
|
+
]);
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export const concatRequestedCartItem = (
|
|
162
|
+
cartItems,
|
|
163
|
+
setCartItems,
|
|
164
|
+
localSessionCart,
|
|
165
|
+
datasets_items,
|
|
166
|
+
projections,
|
|
167
|
+
nutsnames,
|
|
168
|
+
) => {
|
|
169
|
+
let newCartItems = [...cartItems];
|
|
170
|
+
localSessionCart.forEach((localItem) => {
|
|
171
|
+
const requestedItem = datasets_items
|
|
172
|
+
? datasets_items.find((req) => req.UID === localItem.UID)
|
|
173
|
+
: false;
|
|
174
|
+
if (requestedItem) {
|
|
175
|
+
const file_data = requestedItem?.downloadable_files?.items.find(
|
|
176
|
+
(item) => item['@id'] === localItem.file_id,
|
|
177
|
+
);
|
|
178
|
+
if (file_data) {
|
|
179
|
+
newCartItems.push(
|
|
180
|
+
getCartObjectFromPrepackaged(file_data, requestedItem),
|
|
181
|
+
);
|
|
182
|
+
setCartItems(cleanDuplicatesEntries(newCartItems));
|
|
183
|
+
} else {
|
|
184
|
+
newCartItems.push(
|
|
185
|
+
getCartObjectFromMapviewer(
|
|
186
|
+
localItem,
|
|
187
|
+
requestedItem,
|
|
188
|
+
projections,
|
|
189
|
+
nutsnames,
|
|
190
|
+
),
|
|
191
|
+
);
|
|
192
|
+
setCartItems(cleanDuplicatesEntries(newCartItems));
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
};
|
|
@@ -10,6 +10,7 @@ import { useDispatch, useSelector } from 'react-redux';
|
|
|
10
10
|
import FileCard from './FileCard';
|
|
11
11
|
import { FormattedMessage } from 'react-intl';
|
|
12
12
|
import { Grid } from 'semantic-ui-react';
|
|
13
|
+
import { dynamicSort } from '../CclUtils';
|
|
13
14
|
|
|
14
15
|
const CLMSDownloadTasks = (props) => {
|
|
15
16
|
const dispatch = useDispatch();
|
|
@@ -145,22 +146,6 @@ const CLMSDownloadTasks = (props) => {
|
|
|
145
146
|
setter(intermediate);
|
|
146
147
|
}
|
|
147
148
|
|
|
148
|
-
const dynamicSort = (property) => {
|
|
149
|
-
var sortOrder = 1;
|
|
150
|
-
if (property[0] === '-') {
|
|
151
|
-
sortOrder = -1;
|
|
152
|
-
property = property.substr(1);
|
|
153
|
-
}
|
|
154
|
-
return function (a, b) {
|
|
155
|
-
/* next line works with strings and numbers,
|
|
156
|
-
* and you may want to customize it to your needs
|
|
157
|
-
*/
|
|
158
|
-
var result =
|
|
159
|
-
a[property] < b[property] ? -1 : a[property] > b[property] ? 1 : 0;
|
|
160
|
-
return result * sortOrder;
|
|
161
|
-
};
|
|
162
|
-
};
|
|
163
|
-
|
|
164
149
|
const deleteTaskInProgress = (task_id) => {
|
|
165
150
|
setShowDeleteTaskLoading(task_id);
|
|
166
151
|
dispatch(deleteDownloadtool(task_id));
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const dynamicSort = (property) => {
|
|
2
|
+
var sortOrder = 1;
|
|
3
|
+
if (property[0] === '-') {
|
|
4
|
+
sortOrder = -1;
|
|
5
|
+
property = property.substr(1);
|
|
6
|
+
}
|
|
7
|
+
return function (a, b) {
|
|
8
|
+
/* next line works with strings and numbers,
|
|
9
|
+
* and you may want to customize it to your needs
|
|
10
|
+
*/
|
|
11
|
+
var result =
|
|
12
|
+
a[property] < b[property] ? -1 : a[property] > b[property] ? 1 : 0;
|
|
13
|
+
return result * sortOrder;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import StringToHTML from './StringToHTML';
|
|
2
2
|
|
|
3
|
-
export { toBase64, fromBase64 } from './base64';
|
|
4
|
-
|
|
5
3
|
export { StringToHTML };
|
|
6
|
-
|
|
4
|
+
export { toBase64, fromBase64 } from './base64';
|
|
5
|
+
export { dynamicSort } from './dynamicSort';
|
|
7
6
|
export {
|
|
8
7
|
workOpportunitiesCclDateFormat,
|
|
9
8
|
workOpportunitiesCclDateTimeFormat,
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { dynamicSort } from './dynamicSort';
|
|
3
|
+
export const useFilteredPagination = (original_data) => {
|
|
4
|
+
const [originalDataList, setOriginalDataList] = useState(original_data);
|
|
5
|
+
const [dataList, setDataList] = useState(original_data);
|
|
6
|
+
const [paginationSize, setPaginationSize] = useState(10);
|
|
7
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
8
|
+
const [pagination, setPagination] = useState(
|
|
9
|
+
original_data.slice(
|
|
10
|
+
(currentPage - 1) * paginationSize,
|
|
11
|
+
(currentPage - 1) * paginationSize + paginationSize,
|
|
12
|
+
),
|
|
13
|
+
);
|
|
14
|
+
const [search, setSearch] = useState({});
|
|
15
|
+
const applySearch = (e, { value }, field, setter) => {
|
|
16
|
+
const new_filters = { [field]: value };
|
|
17
|
+
setSearch(new_filters);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const applyOrder = (criteria) => {
|
|
21
|
+
setDataList([...dataList.sort(dynamicSort(criteria))]);
|
|
22
|
+
};
|
|
23
|
+
const clearSearch = () => {
|
|
24
|
+
setDataList(originalDataList);
|
|
25
|
+
setSearch({});
|
|
26
|
+
};
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
let filtered_data_list = [...originalDataList];
|
|
29
|
+
Object.entries(search).forEach((filter) => {
|
|
30
|
+
const filter_key = filter[0];
|
|
31
|
+
const filter_data = filter[1];
|
|
32
|
+
if (filter_data.length > 0) {
|
|
33
|
+
filtered_data_list = filtered_data_list.filter((data) => {
|
|
34
|
+
return data[filter_key]
|
|
35
|
+
.toLowerCase()
|
|
36
|
+
.includes(filter_data.toLowerCase());
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
setDataList(filtered_data_list);
|
|
41
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
42
|
+
}, [search]);
|
|
43
|
+
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
setPagination(
|
|
46
|
+
dataList.slice(
|
|
47
|
+
(currentPage - 1) * paginationSize,
|
|
48
|
+
(currentPage - 1) * paginationSize + paginationSize,
|
|
49
|
+
),
|
|
50
|
+
);
|
|
51
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
52
|
+
}, [dataList, currentPage, paginationSize]);
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
functions: {
|
|
56
|
+
setCurrentPage,
|
|
57
|
+
setPaginationSize,
|
|
58
|
+
applySearch,
|
|
59
|
+
setDataList,
|
|
60
|
+
setOriginalDataList,
|
|
61
|
+
clearSearch,
|
|
62
|
+
applyOrder,
|
|
63
|
+
},
|
|
64
|
+
data: {
|
|
65
|
+
pagination,
|
|
66
|
+
currentPage,
|
|
67
|
+
paginationSize,
|
|
68
|
+
originalDataList,
|
|
69
|
+
dataList,
|
|
70
|
+
search,
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
};
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
@import 'globals.less';
|
|
2
|
+
|
|
3
|
+
@addon: 'volto-slate';
|
|
4
|
+
@addontype: 'editor';
|
|
5
|
+
@addonelement: 'slate';
|
|
6
|
+
|
|
7
|
+
// TODO: move these to less variables
|
|
8
|
+
|
|
9
|
+
& {
|
|
10
|
+
.slate-inline-toolbar {
|
|
11
|
+
position: absolute;
|
|
12
|
+
|
|
13
|
+
/* should be above admin panes (100), and below the Link modal form (1000) */
|
|
14
|
+
z-index: 1500;
|
|
15
|
+
|
|
16
|
+
top: -10000px;
|
|
17
|
+
left: -10000px;
|
|
18
|
+
|
|
19
|
+
max-width: 100vw;
|
|
20
|
+
opacity: 0;
|
|
21
|
+
|
|
22
|
+
&.upper {
|
|
23
|
+
transform: translateY(-100%);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.toolbar-wrapper.active {
|
|
28
|
+
margin-bottom: 0.6em;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.slate-editor p {
|
|
32
|
+
/* In editor the <p> are wrapped in weird markup */
|
|
33
|
+
margin-bottom: 0 !important;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.slate-toolbar {
|
|
37
|
+
display: flex;
|
|
38
|
+
box-sizing: border-box;
|
|
39
|
+
padding: 3px;
|
|
40
|
+
border: none;
|
|
41
|
+
margin-left: -15rem;
|
|
42
|
+
background: #fff;
|
|
43
|
+
border-radius: 2px;
|
|
44
|
+
box-shadow: 0 0 8px rgba(0, 0, 0, 0.1);
|
|
45
|
+
font-family: 'Poppins', 'Helvetica Neue', Arial, Helvetica, sans-serif;
|
|
46
|
+
font-size: 1rem;
|
|
47
|
+
font-weight: normal;
|
|
48
|
+
|
|
49
|
+
.expando {
|
|
50
|
+
flex-grow: 1;
|
|
51
|
+
background-color: #fff;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.toolbar-separator {
|
|
55
|
+
display: inline-block;
|
|
56
|
+
height: 32px;
|
|
57
|
+
border-right: 1px solid #ddd;
|
|
58
|
+
margin: 0 0.5rem;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.toolbar-separator + .button-wrapper {
|
|
62
|
+
margin-left: 0px;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.button-wrapper {
|
|
66
|
+
display: inline-block;
|
|
67
|
+
margin-left: 3px;
|
|
68
|
+
|
|
69
|
+
.ui.tiny.compact.icon.toggle.button {
|
|
70
|
+
width: 32px;
|
|
71
|
+
height: 32px;
|
|
72
|
+
box-sizing: border-box;
|
|
73
|
+
padding: 4px !important;
|
|
74
|
+
border: 0;
|
|
75
|
+
background: rgba(255, 255, 255, 0.975);
|
|
76
|
+
border-radius: 1px;
|
|
77
|
+
color: @brown;
|
|
78
|
+
font-size: 18px;
|
|
79
|
+
vertical-align: bottom;
|
|
80
|
+
|
|
81
|
+
& > svg {
|
|
82
|
+
fill: #888;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
&:hover,
|
|
86
|
+
&:focus {
|
|
87
|
+
background: #f3f3f3;
|
|
88
|
+
outline: 0; /* reset for :focus */
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
&.active {
|
|
92
|
+
background: #efefef !important;
|
|
93
|
+
border-radius: 3px;
|
|
94
|
+
box-shadow: inset 0 0 0 1px @blue !important;
|
|
95
|
+
color: @blue !important;
|
|
96
|
+
|
|
97
|
+
& > svg {
|
|
98
|
+
fill: #444;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.ui.buttons {
|
|
105
|
+
width: 100%;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.ui.button:not(.icon) > .icon:not(.button):not(.dropdown) {
|
|
109
|
+
margin: auto auto auto auto !important;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.ui.button:last-child {
|
|
113
|
+
margin-right: 0 !important;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.highlight-selection {
|
|
118
|
+
background-color: grey;
|
|
119
|
+
color: white;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.ui.input.editor-link input {
|
|
123
|
+
padding: 0;
|
|
124
|
+
border: none;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.sidebar-container {
|
|
129
|
+
.slate-editor {
|
|
130
|
+
ul {
|
|
131
|
+
li {
|
|
132
|
+
display: list-item;
|
|
133
|
+
padding: 0;
|
|
134
|
+
|
|
135
|
+
span {
|
|
136
|
+
display: initial;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.power-user-menu {
|
|
144
|
+
position: absolute;
|
|
145
|
+
z-index: 10;
|
|
146
|
+
top: 29px;
|
|
147
|
+
left: -9px;
|
|
148
|
+
width: 210px;
|
|
149
|
+
background-color: rgba(255, 255, 255, 0.975);
|
|
150
|
+
border-radius: 2px;
|
|
151
|
+
box-shadow: 0 0 8px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
152
|
+
|
|
153
|
+
.ui.menu {
|
|
154
|
+
border: 0;
|
|
155
|
+
border-radius: 2px;
|
|
156
|
+
|
|
157
|
+
.icon {
|
|
158
|
+
margin-right: 12px;
|
|
159
|
+
vertical-align: middle;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.item.active {
|
|
163
|
+
background: #efefef !important;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/* Needed by semantic.less */
|
|
2
|
+
@type: 'extra';
|
|
3
|
+
@element: 'custom';
|
|
4
|
+
|
|
5
|
+
@import (multiple, reference, optional) '../../theme.config';
|
|
6
|
+
|
|
7
|
+
/* Enables customization of addons */
|
|
8
|
+
.loadAddonOverrides() {
|
|
9
|
+
@import (optional)
|
|
10
|
+
'@{siteFolder}/../addons/@{addon}/@{addontype}s/@{addonelement}.overrides';
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/* Helper to load variables */
|
|
14
|
+
.loadAddonVariables() {
|
|
15
|
+
@import (optional) '@{addonelement}.variables';
|
|
16
|
+
@import (optional)
|
|
17
|
+
'@{siteFolder}/../addons/@{addon}/@{addontype}s/@{addonelement}.variables';
|
|
18
|
+
}
|
package/src/index.js
CHANGED
|
@@ -150,9 +150,9 @@ a:hover,
|
|
|
150
150
|
/* CLMS-1356 */
|
|
151
151
|
@media only screen and (max-width: 768px) {
|
|
152
152
|
.ccl-container {
|
|
153
|
-
width: auto!important;
|
|
154
|
-
margin-right: 1em!important;
|
|
155
|
-
margin-left: 1em!important;
|
|
153
|
+
width: auto !important;
|
|
154
|
+
margin-right: 1em !important;
|
|
155
|
+
margin-left: 1em !important;
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
158
|
|
|
@@ -568,8 +568,9 @@ body:not(.contenttype-lrf:not(.section-cart):not(.section-profile))
|
|
|
568
568
|
/* Downloads cart CLMS-1357 */
|
|
569
569
|
@media only screen and (max-width: 500px) {
|
|
570
570
|
.center.aligned.middle.aligned.two.wide.column {
|
|
571
|
-
padding:0px;
|
|
571
|
+
padding: 0px;
|
|
572
572
|
}
|
|
573
|
+
|
|
573
574
|
.ui.olive.segment {
|
|
574
575
|
padding-left: 2px;
|
|
575
576
|
}
|
|
@@ -920,11 +921,11 @@ body:not(.contenttype-lrf:not(.section-cart):not(.section-profile))
|
|
|
920
921
|
.dataset-download-table .ui.message {
|
|
921
922
|
left: 25%;
|
|
922
923
|
width: 50%;
|
|
923
|
-
background-color: #
|
|
924
|
+
background-color: #f8f8f9;
|
|
925
|
+
box-shadow: 0px 0px 4px 0px #dadada;
|
|
924
926
|
color: inherit;
|
|
925
927
|
font-size: 1rem;
|
|
926
928
|
font-weight: bold;
|
|
927
|
-
box-shadow: 0px 0px 4px 0px #dadada;
|
|
928
929
|
}
|
|
929
930
|
|
|
930
931
|
.dataset-download-table .ui.checkbox input:checked ~ label:before,
|
|
@@ -942,8 +943,8 @@ body:not(.contenttype-lrf:not(.section-cart):not(.section-profile))
|
|
|
942
943
|
}
|
|
943
944
|
|
|
944
945
|
.dataset-download-table > .ui.basic.segment {
|
|
945
|
-
padding-left: 0px;
|
|
946
946
|
padding-right: 0px;
|
|
947
|
+
padding-left: 0px;
|
|
947
948
|
}
|
|
948
949
|
|
|
949
950
|
/* Downloads */
|
|
@@ -1255,14 +1256,15 @@ div#page-document h1.documentFirstHeading {
|
|
|
1255
1256
|
|
|
1256
1257
|
// CLMS-1344
|
|
1257
1258
|
#sidebar-metadata .react-select__option {
|
|
1258
|
-
white-space: nowrap;
|
|
1259
1259
|
width: fit-content;
|
|
1260
|
+
white-space: nowrap;
|
|
1260
1261
|
}
|
|
1261
1262
|
|
|
1262
1263
|
// CLMS-1424
|
|
1263
1264
|
.cart-table td {
|
|
1264
1265
|
word-break: unset !important;
|
|
1265
1266
|
}
|
|
1267
|
+
|
|
1266
1268
|
.cart-table .dropdown {
|
|
1267
1269
|
min-width: 7rem !important;
|
|
1268
1270
|
}
|
|
@@ -1273,8 +1275,8 @@ div#page-document h1.documentFirstHeading {
|
|
|
1273
1275
|
|
|
1274
1276
|
// CLMS-1460
|
|
1275
1277
|
.technical-library-edit-link {
|
|
1276
|
-
vertical-align: middle;
|
|
1277
1278
|
margin-left: 5px;
|
|
1279
|
+
vertical-align: middle;
|
|
1278
1280
|
}
|
|
1279
1281
|
|
|
1280
1282
|
// CLMS-1542
|
|
@@ -1294,4 +1296,4 @@ main {
|
|
|
1294
1296
|
// CLMS-1588
|
|
1295
1297
|
.carousel-text-link-container {
|
|
1296
1298
|
min-height: 30px;
|
|
1297
|
-
}
|
|
1299
|
+
}
|