@eeacms/volto-clms-theme 1.0.118 → 1.0.121
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 +44 -0
- package/package.json +1 -1
- package/src/components/Blocks/CclHomeBgImageBlock/CclGreenBgView.jsx +2 -0
- package/src/components/Blocks/CclTextLinkCarouselBlock/CclTextLinkCarouselView.jsx +9 -1
- package/src/components/Blocks/CustomTemplates/VoltoSearchBlock/CheckboxTreeParentFacet.jsx +4 -11
- package/src/components/Blocks/CustomTemplates/VoltoSearchBlock/FilterList.jsx +38 -3
- package/src/components/Blocks/CustomTemplates/VoltoSearchBlock/rewriteOptions.js +14 -0
- package/src/components/Blocks/CustomTemplates/VoltoSearchBlock/utils.js +13 -1
- package/src/components/Blocks/CustomTemplates/VoltoTabsBlock/custom.less +1 -0
- package/src/components/CLMSDatasetDetailView/CLMSDatasetDetailView.jsx +3 -5
- package/src/components/CLMSDatasetDetailView/DataSetInfoContent.jsx +4 -15
- package/src/components/CLMSDatasetDetailView/DownloadDataSetContent.jsx +7 -1
- package/src/components/CLMSDatasetDetailView/RelatedUseCases.jsx +1 -1
- package/src/components/CLMSMeetingView/CLMSMeetingView.jsx +7 -1
- package/src/components/CclCard/CclCard.jsx +23 -20
- package/src/components/CclCard/cards.less +3 -12
- package/src/components/CclLoginModal/CclLoginModal.jsx +2 -5
- package/src/components/Widgets/TaxonomyWidget.jsx +1 -1
- package/src/components/Widgets/taxonomyUtils.js +2 -1
- package/src/customizations/volto/components/manage/Widgets/ArrayWidget.jsx +413 -0
- package/theme/clms/css/carousel.css +2 -4
- package/theme/clms/css/home.css +1 -2
- package/theme/clms/css/maps.less +8 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,50 @@ 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.121](https://github.com/eea/volto-clms-theme/compare/1.0.120...1.0.121) - 5 September 2022
|
|
8
|
+
|
|
9
|
+
#### :bug: Bug Fixes
|
|
10
|
+
|
|
11
|
+
- fix: CLMS-1224 this file should be removed with volto-16 [Unai - [`7cf72ab`](https://github.com/eea/volto-clms-theme/commit/7cf72aba7b1d69cf1b310a89410aa3a3753f01f3)]
|
|
12
|
+
- fix:lint problems [Unai - [`4e8b9dc`](https://github.com/eea/volto-clms-theme/commit/4e8b9dc6c3cb6813baeb4b75fea5afb1198d9640)]
|
|
13
|
+
- fix: not count children filters on checboxParentFacets [ionlizarazu - [`4b21b1c`](https://github.com/eea/volto-clms-theme/commit/4b21b1c3337e132248ad1ada6a9bf268c5332579)]
|
|
14
|
+
- fix: related use cases [Unai - [`381af05`](https://github.com/eea/volto-clms-theme/commit/381af058fe7484805e5175600b40cd80d52d2c9e)]
|
|
15
|
+
- fix: changed data resource abstract with overview [Unai - [`c630b7e`](https://github.com/eea/volto-clms-theme/commit/c630b7e6a6e093319473554a4a724fd320783f2d)]
|
|
16
|
+
- fix:redirect to download from map viewer when necesary [Unai - [`9ad9d78`](https://github.com/eea/volto-clms-theme/commit/9ad9d78e7e7b946c34da20d7edea2d68c7cd6fe5)]
|
|
17
|
+
- fix: file card modified to show effective date [Unai - [`b2467e7`](https://github.com/eea/volto-clms-theme/commit/b2467e7a3a813871811388e92b308aea62aa688c)]
|
|
18
|
+
- fix:technical documents on datasets general info view [Unai - [`532cf09`](https://github.com/eea/volto-clms-theme/commit/532cf094933c9d0ba1b9fa77609555621645972a)]
|
|
19
|
+
- fix:carousel link open in new tab [Unai - [`bcc39a5`](https://github.com/eea/volto-clms-theme/commit/bcc39a5b921fee81a653743afd1f219a79c4748f)]
|
|
20
|
+
|
|
21
|
+
#### :nail_care: Enhancements
|
|
22
|
+
|
|
23
|
+
- refactor: removed overview title from dataset [Unai - [`e08ff03`](https://github.com/eea/volto-clms-theme/commit/e08ff0348e2a371b033206e3e66f900f09edd443)]
|
|
24
|
+
|
|
25
|
+
#### :hammer_and_wrench: Others
|
|
26
|
+
|
|
27
|
+
- merge sprint-31 branch [Mikel Larreategi - [`617b5d2`](https://github.com/eea/volto-clms-theme/commit/617b5d25a17cdd264b017a8440d3c4c1c9e283bd)]
|
|
28
|
+
- rename variable [ionlizarazu - [`7b4c537`](https://github.com/eea/volto-clms-theme/commit/7b4c53783e4bbe676ee6e7982610b191a9b40532)]
|
|
29
|
+
### [1.0.120](https://github.com/eea/volto-clms-theme/compare/1.0.119...1.0.120) - 2 September 2022
|
|
30
|
+
|
|
31
|
+
#### :bug: Bug Fixes
|
|
32
|
+
|
|
33
|
+
- fix: use plain a for EU Login URL [Mikel Larreategi - [`e8d2d66`](https://github.com/eea/volto-clms-theme/commit/e8d2d664e750df517a8d955c4833a70e0f8b34e3)]
|
|
34
|
+
|
|
35
|
+
#### :hammer_and_wrench: Others
|
|
36
|
+
|
|
37
|
+
- Map login button fix [rodriama - [`0e7e520`](https://github.com/eea/volto-clms-theme/commit/0e7e520ac2515846b4af6e782a9f4cdc2375a467)]
|
|
38
|
+
- Card doc fix [rodriama - [`556e33c`](https://github.com/eea/volto-clms-theme/commit/556e33c833b9980edab3b778fc408e662fd5fffd)]
|
|
39
|
+
- ESLint fix [rodriama - [`d55db81`](https://github.com/eea/volto-clms-theme/commit/d55db818a02be4ccfcc524c1f03005600644a9e4)]
|
|
40
|
+
- Credits pop up fix [rodriama - [`3772c16`](https://github.com/eea/volto-clms-theme/commit/3772c163a0a998a7dc7b0fddd176346f2d56a4e1)]
|
|
41
|
+
- ESLint fix [rodriama - [`08a9bd8`](https://github.com/eea/volto-clms-theme/commit/08a9bd8c3cc78d928df58cc8b66fa3aea81f2b13)]
|
|
42
|
+
- Event detail segment [rodriama - [`524e3ff`](https://github.com/eea/volto-clms-theme/commit/524e3fff130ae53ffb09aa534d120677e5fd1c1a)]
|
|
43
|
+
### [1.0.119](https://github.com/eea/volto-clms-theme/compare/1.0.118...1.0.119) - 1 September 2022
|
|
44
|
+
|
|
45
|
+
#### :bug: Bug Fixes
|
|
46
|
+
|
|
47
|
+
- fix: restore taxonomy item ordering [Mikel Larreategi - [`5080a9f`](https://github.com/eea/volto-clms-theme/commit/5080a9f456888bba77042b673f62e3db5cfe86fb)]
|
|
48
|
+
- fix: reverse checkbox label ordering [ionlizarazu - [`cd2ea37`](https://github.com/eea/volto-clms-theme/commit/cd2ea377f9f6c4cdd584dd9c5df41e3574fcd686)]
|
|
49
|
+
- fix: search facet checkbox functionality. Order by title and replace starting text 00# from the checkbox labels [ionlizarazu - [`df69da5`](https://github.com/eea/volto-clms-theme/commit/df69da5124b25ac098b4204e20663524c2ebb91a)]
|
|
50
|
+
|
|
7
51
|
### [1.0.118](https://github.com/eea/volto-clms-theme/compare/1.0.117...1.0.118) - 1 September 2022
|
|
8
52
|
|
|
9
53
|
#### :bug: Bug Fixes
|
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import loadable from '@loadable/component';
|
|
3
|
+
import { UniversalLink } from '@plone/volto/components';
|
|
3
4
|
const Slider = loadable(() => import('react-slick'));
|
|
4
5
|
|
|
5
6
|
const CclTextLinkCarouselView = (props) => {
|
|
@@ -24,7 +25,14 @@ const CclTextLinkCarouselView = (props) => {
|
|
|
24
25
|
{data?.textLink?.items.map((item, index) => (
|
|
25
26
|
<div className="text-link-carousel-block" key={index}>
|
|
26
27
|
<div className="text-link-carousel-block-content">
|
|
27
|
-
<
|
|
28
|
+
<UniversalLink
|
|
29
|
+
openLinkInNewTab={true}
|
|
30
|
+
href={'' + item?.link?.[0]?.['@id']}
|
|
31
|
+
>
|
|
32
|
+
{item?.text}
|
|
33
|
+
</UniversalLink>
|
|
34
|
+
|
|
35
|
+
{/* <a href={'' + item?.link?.[0]?.['@id']}>{item?.text}</a> */}
|
|
28
36
|
</div>
|
|
29
37
|
</div>
|
|
30
38
|
))}
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
selectFacetStateToValue,
|
|
11
11
|
selectFacetValueToQuery,
|
|
12
12
|
} from '@plone/volto/components/manage/Blocks/Search/components/base';
|
|
13
|
-
import { checkAllChildren } from './utils';
|
|
13
|
+
import { checkAllChildren, uncheckOptionAndChildren } from './utils';
|
|
14
14
|
|
|
15
15
|
const hasAllChildrensSelected = (value, childrens) => {
|
|
16
16
|
var result = true;
|
|
@@ -92,16 +92,9 @@ const CheckboxListParent = ({ option, key, onChange, value, id }) => {
|
|
|
92
92
|
...checkAllChildren(value, option).map((f) => f.value),
|
|
93
93
|
])
|
|
94
94
|
: onChange(id, [
|
|
95
|
-
...value
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
(item) =>
|
|
99
|
-
option.childrens?.length > 0 &&
|
|
100
|
-
!option.childrens
|
|
101
|
-
.map((ch) => ch.value)
|
|
102
|
-
.includes(item.value),
|
|
103
|
-
)
|
|
104
|
-
.map((f) => f.value),
|
|
95
|
+
...uncheckOptionAndChildren(value, option).map(
|
|
96
|
+
(f) => f.value,
|
|
97
|
+
),
|
|
105
98
|
]);
|
|
106
99
|
}}
|
|
107
100
|
label={
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Button, Icon } from 'semantic-ui-react';
|
|
3
3
|
import { defineMessages, useIntl } from 'react-intl';
|
|
4
|
+
import { structure_taxonomy_terms } from '@eeacms/volto-clms-theme/components';
|
|
4
5
|
|
|
5
6
|
const messages = defineMessages({
|
|
6
7
|
currentFilters: {
|
|
@@ -14,7 +15,7 @@ const messages = defineMessages({
|
|
|
14
15
|
});
|
|
15
16
|
|
|
16
17
|
const FilterList = (props) => {
|
|
17
|
-
const { facets, setFacets, isEditMode, data } = props;
|
|
18
|
+
const { facets, setFacets, isEditMode, data, querystring } = props;
|
|
18
19
|
const showFilterList = !Object.values(facets).every((facet) => !facet.length);
|
|
19
20
|
|
|
20
21
|
const baseFacets = data.facets;
|
|
@@ -28,10 +29,44 @@ const FilterList = (props) => {
|
|
|
28
29
|
baseFacets.map((bf) => bf.field?.value).includes(v[0]),
|
|
29
30
|
),
|
|
30
31
|
);
|
|
32
|
+
const fieldsToAvoidChildren = data.facets
|
|
33
|
+
.filter((item) => item.type === 'checkboxTreeParentFacet')
|
|
34
|
+
.map((item) => item.field.value);
|
|
35
|
+
let filtersToAvoid = [];
|
|
36
|
+
if (querystring.loaded) {
|
|
37
|
+
filtersToAvoid = fieldsToAvoidChildren
|
|
38
|
+
.map((field) => {
|
|
39
|
+
let result = [];
|
|
40
|
+
const fieldValuesDict = querystring.indexes[field].values;
|
|
41
|
+
const fieldValues = Object.keys(fieldValuesDict).map((fieldKey) => {
|
|
42
|
+
return { value: fieldKey, label: fieldValuesDict[fieldKey].title };
|
|
43
|
+
});
|
|
44
|
+
const fieldStructuredValues = structure_taxonomy_terms(fieldValues);
|
|
45
|
+
fieldStructuredValues.forEach((parent) => {
|
|
46
|
+
parent.childrens.forEach((children) => result.push(children.value));
|
|
47
|
+
});
|
|
48
|
+
return result;
|
|
49
|
+
})
|
|
50
|
+
.flat(1);
|
|
51
|
+
}
|
|
52
|
+
const filtersToAvoidSet = new Set(filtersToAvoid);
|
|
31
53
|
|
|
32
|
-
|
|
33
|
-
|
|
54
|
+
// if (choices?.length > 0) {
|
|
55
|
+
// options = structure_taxonomy_terms(choices);
|
|
56
|
+
// }
|
|
57
|
+
const currentFiltersToCount = {};
|
|
58
|
+
Object.keys(currentFilters).forEach((filterKey) => {
|
|
59
|
+
currentFiltersToCount[filterKey] = currentFilters[filterKey].filter(
|
|
60
|
+
(filter) => {
|
|
61
|
+
return !filtersToAvoidSet.has(filter);
|
|
62
|
+
},
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
// const totalFilters = [].concat.apply([], Object.values(currentFilters))
|
|
66
|
+
// .length;
|
|
34
67
|
|
|
68
|
+
const totalFilters = [].concat.apply([], Object.values(currentFiltersToCount))
|
|
69
|
+
.length;
|
|
35
70
|
const intl = useIntl();
|
|
36
71
|
|
|
37
72
|
return showFilterList && Object.keys(currentFilters).length ? (
|
|
@@ -80,6 +80,20 @@ const rewriteOptions = (name, choices) => {
|
|
|
80
80
|
return 0;
|
|
81
81
|
});
|
|
82
82
|
}
|
|
83
|
+
if (name === 'taxonomy_technical_library_categorization') {
|
|
84
|
+
result = choices
|
|
85
|
+
.sort((a, b) => {
|
|
86
|
+
if (a.label < b.label) {
|
|
87
|
+
return -1;
|
|
88
|
+
} else if (a.label > b.label) {
|
|
89
|
+
return 1;
|
|
90
|
+
}
|
|
91
|
+
return 0;
|
|
92
|
+
})
|
|
93
|
+
.map((opt) => {
|
|
94
|
+
return { ...opt, label: opt.label.replace(/^[0-9][0-9]#/, '') };
|
|
95
|
+
});
|
|
96
|
+
}
|
|
83
97
|
return result;
|
|
84
98
|
};
|
|
85
99
|
|
|
@@ -7,5 +7,17 @@ export const checkAllChildren = (value, option) => {
|
|
|
7
7
|
value.push(ch);
|
|
8
8
|
}
|
|
9
9
|
});
|
|
10
|
-
return value;
|
|
10
|
+
return [...value, { label: option.label, value: option.value }];
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const uncheckOptionAndChildren = (value, option) => {
|
|
14
|
+
return value
|
|
15
|
+
.filter((item) => item.value !== option.value)
|
|
16
|
+
.filter((item) => {
|
|
17
|
+
if (option.childrens?.length > 0) {
|
|
18
|
+
return !option.childrens.map((ch) => ch.value).includes(item.value);
|
|
19
|
+
} else {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
});
|
|
11
23
|
};
|
|
@@ -77,6 +77,7 @@ const CLMSDatasetDetailView = ({ content, token }) => {
|
|
|
77
77
|
key={item.id}
|
|
78
78
|
loading={geonetwork_importation.loading}
|
|
79
79
|
circular
|
|
80
|
+
style={{ width: '50%' }}
|
|
80
81
|
>
|
|
81
82
|
<strong>
|
|
82
83
|
{item.title} (from {item.type}):{' '}
|
|
@@ -203,6 +204,7 @@ const CLMSDatasetDetailView = ({ content, token }) => {
|
|
|
203
204
|
key={'wms-layers-import'}
|
|
204
205
|
loading={wms_layers_importation?.loading}
|
|
205
206
|
circular
|
|
207
|
+
style={{ width: '50%' }}
|
|
206
208
|
>
|
|
207
209
|
<Modal
|
|
208
210
|
onClose={() => {
|
|
@@ -288,17 +290,13 @@ const CLMSDatasetDetailView = ({ content, token }) => {
|
|
|
288
290
|
</p>
|
|
289
291
|
)}
|
|
290
292
|
</Segment>
|
|
291
|
-
</Segment.Group>
|
|
292
|
-
)}
|
|
293
|
-
|
|
294
|
-
{user?.roles && user.roles.includes('Manager') && (
|
|
295
|
-
<Segment.Group compact horizontal>
|
|
296
293
|
<Segment
|
|
297
294
|
padded={'very'}
|
|
298
295
|
color={'olive'}
|
|
299
296
|
key={'wms-fields-import'}
|
|
300
297
|
loading={wms_fields_importation?.loading}
|
|
301
298
|
circular
|
|
299
|
+
style={{ width: '50%' }}
|
|
302
300
|
>
|
|
303
301
|
<Modal
|
|
304
302
|
onClose={() => {
|
|
@@ -14,22 +14,14 @@ import { useLocation } from 'react-router-dom';
|
|
|
14
14
|
|
|
15
15
|
const DataSetInfoContent = (props) => {
|
|
16
16
|
const dispatch = useDispatch();
|
|
17
|
-
const {
|
|
18
|
-
UID,
|
|
19
|
-
id,
|
|
20
|
-
validation,
|
|
21
|
-
dataResourceAbstract,
|
|
22
|
-
data,
|
|
23
|
-
geonetwork_identifiers,
|
|
24
|
-
citation,
|
|
25
|
-
} = props;
|
|
17
|
+
const { UID, id, validation, data, geonetwork_identifiers, citation } = props;
|
|
26
18
|
const location = useLocation();
|
|
27
19
|
const searchSubrequests = useSelector((state) => state.search.subrequests);
|
|
28
20
|
let libraries = searchSubrequests?.[id]?.items || [];
|
|
29
21
|
let librariesPending = searchSubrequests?.[id]?.loading;
|
|
30
22
|
const user = useSelector((state) => state.users.user);
|
|
31
23
|
React.useEffect(() => {
|
|
32
|
-
if (location.hash === '#
|
|
24
|
+
if (location.hash === '#General-Info' && UID) {
|
|
33
25
|
dispatch(
|
|
34
26
|
searchContent(
|
|
35
27
|
'',
|
|
@@ -66,7 +58,6 @@ const DataSetInfoContent = (props) => {
|
|
|
66
58
|
? iTitleIcons.rightPosition
|
|
67
59
|
: iTitleIcons.leftPosition;
|
|
68
60
|
}
|
|
69
|
-
|
|
70
61
|
return (
|
|
71
62
|
<div>
|
|
72
63
|
{validation?.data && validation?.data !== '<p><br/></p>' && (
|
|
@@ -77,11 +68,9 @@ const DataSetInfoContent = (props) => {
|
|
|
77
68
|
></CclCitation>
|
|
78
69
|
)}
|
|
79
70
|
<CclInfoContainer>
|
|
80
|
-
{
|
|
71
|
+
{props?.description && (
|
|
81
72
|
<CclInfoDescription
|
|
82
|
-
|
|
83
|
-
description={<StringToHTML string={dataResourceAbstract.data} />}
|
|
84
|
-
tooltip="Brief narrative summary of the content of the resource(s) with coverage, main attributes, data sources, important of the work, etc."
|
|
73
|
+
description={<StringToHTML string={props.description} />}
|
|
85
74
|
></CclInfoDescription>
|
|
86
75
|
)}
|
|
87
76
|
</CclInfoContainer>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import CclDownloadTable from '@eeacms/volto-clms-theme/components/CclDownloadTable/CclDownloadTable';
|
|
3
3
|
import CclButton from '@eeacms/volto-clms-theme/components/CclButton/CclButton';
|
|
4
|
-
import { Link, useLocation } from 'react-router-dom';
|
|
4
|
+
import { Link, useLocation, Redirect } from 'react-router-dom';
|
|
5
5
|
|
|
6
6
|
const DownloadDataSetContent = (data) => {
|
|
7
7
|
let url = '/register';
|
|
@@ -9,6 +9,12 @@ const DownloadDataSetContent = (data) => {
|
|
|
9
9
|
|
|
10
10
|
return (
|
|
11
11
|
<div>
|
|
12
|
+
{data.downloadable_files?.items[0].path === '' &&
|
|
13
|
+
location.hash === '#Download' ? (
|
|
14
|
+
<Redirect to={location.pathname + '/download-by-area'} />
|
|
15
|
+
) : (
|
|
16
|
+
''
|
|
17
|
+
)}
|
|
12
18
|
{data.token === '' && (
|
|
13
19
|
<div className="login-block">
|
|
14
20
|
<div className="login-content">
|
|
@@ -14,7 +14,7 @@ const RelatedUseCases = (props) => {
|
|
|
14
14
|
let librariesPending = searchSubrequests?.[id]?.loading;
|
|
15
15
|
const location = useLocation();
|
|
16
16
|
React.useEffect(() => {
|
|
17
|
-
if (location.hash === '#
|
|
17
|
+
if (location.hash === '#Use-cases' && UID) {
|
|
18
18
|
dispatch(
|
|
19
19
|
searchContent(
|
|
20
20
|
'',
|
|
@@ -288,7 +288,13 @@ export const CLMSMeetingView = (props) => {
|
|
|
288
288
|
</Segment.Group>
|
|
289
289
|
)}
|
|
290
290
|
{content.description}
|
|
291
|
-
<Segment
|
|
291
|
+
<Segment
|
|
292
|
+
compact
|
|
293
|
+
padded={'small'}
|
|
294
|
+
color={'olive'}
|
|
295
|
+
floated="right"
|
|
296
|
+
style={{ marginRight: 0 }}
|
|
297
|
+
>
|
|
292
298
|
<div className="dataset-info-field">
|
|
293
299
|
<div className="dataset-field-title">
|
|
294
300
|
<Header>{intl.formatMessage(messages.when)}</Header>
|
|
@@ -49,30 +49,30 @@ const CardLink = ({ url, children, className, condition = true }) => {
|
|
|
49
49
|
const DocCard = ({ card, url, showEditor, children }) => {
|
|
50
50
|
return (
|
|
51
51
|
<>
|
|
52
|
-
<div className="card-doc-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
<
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
<div className="doc-description">{card?.description}</div>
|
|
52
|
+
<div className="card-doc-header">
|
|
53
|
+
<div className="card-doc-title">
|
|
54
|
+
{card?.Type === 'TechnicalLibrary' ? (
|
|
55
|
+
<a href={`${card['@id']}/@@download/file`}>{card?.title}</a>
|
|
56
|
+
) : (
|
|
57
|
+
<Link to={url}>{card?.title}</Link>
|
|
58
|
+
)}
|
|
59
|
+
{card?.Type === 'TechnicalLibrary' && showEditor && (
|
|
60
|
+
<Link to={`${url}/edit`}>
|
|
61
|
+
<Icon
|
|
62
|
+
name={penSVG}
|
|
63
|
+
size="15px"
|
|
64
|
+
className="circled"
|
|
65
|
+
title={'Edit'}
|
|
66
|
+
/>
|
|
67
|
+
</Link>
|
|
68
|
+
)}
|
|
69
|
+
</div>
|
|
71
70
|
{card?.Type === 'TechnicalLibrary' && (
|
|
72
71
|
<div className="card-doc-size">{card.getObjSize || ''}</div>
|
|
73
72
|
)}
|
|
74
|
-
{children}
|
|
75
73
|
</div>
|
|
74
|
+
<div className="card-doc-description">{card?.description}</div>
|
|
75
|
+
{children}
|
|
76
76
|
</>
|
|
77
77
|
);
|
|
78
78
|
};
|
|
@@ -140,6 +140,9 @@ function CclCard(props) {
|
|
|
140
140
|
</div>
|
|
141
141
|
<div className="card-text">
|
|
142
142
|
<CardLink url={url}>{card?.title}</CardLink>
|
|
143
|
+
<div className="news-detail-date">
|
|
144
|
+
{cclDateFormat(card?.effective)}
|
|
145
|
+
</div>
|
|
143
146
|
<div className="card-description">{card?.description}</div>
|
|
144
147
|
{children}
|
|
145
148
|
</div>
|
|
@@ -375,13 +375,9 @@
|
|
|
375
375
|
border-bottom: solid 1px #a0b12833;
|
|
376
376
|
}
|
|
377
377
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
.card-doc:not(:last-of-type) {
|
|
384
|
-
border-bottom: solid 1px #a0b12833;
|
|
378
|
+
.card-doc-header {
|
|
379
|
+
display: flex;
|
|
380
|
+
justify-content: space-between;
|
|
385
381
|
}
|
|
386
382
|
|
|
387
383
|
.card-doc-title {
|
|
@@ -391,11 +387,6 @@
|
|
|
391
387
|
font-weight: bold;
|
|
392
388
|
}
|
|
393
389
|
|
|
394
|
-
.card-doc-text {
|
|
395
|
-
display: flex;
|
|
396
|
-
justify-content: space-between;
|
|
397
|
-
}
|
|
398
|
-
|
|
399
390
|
.card-doc-size {
|
|
400
391
|
margin-left: 1rem;
|
|
401
392
|
white-space: nowrap;
|
|
@@ -90,12 +90,9 @@ function CclLoginModal(props) {
|
|
|
90
90
|
</div>
|
|
91
91
|
<div className="actions">
|
|
92
92
|
<div className="modal-buttons">
|
|
93
|
-
<
|
|
94
|
-
href={loginUrl || '#'}
|
|
95
|
-
className="ccl-button ccl-button-green"
|
|
96
|
-
>
|
|
93
|
+
<a href={loginUrl || '#'} className="ccl-button ccl-button-green">
|
|
97
94
|
Login using EU Login
|
|
98
|
-
</
|
|
95
|
+
</a>
|
|
99
96
|
</div>
|
|
100
97
|
</div>
|
|
101
98
|
</CclModal>
|
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ArrayWidget component.
|
|
3
|
+
* @module components/manage/Widgets/ArrayWidget
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React, { Component } from 'react';
|
|
7
|
+
import { defineMessages, injectIntl } from 'react-intl';
|
|
8
|
+
import PropTypes from 'prop-types';
|
|
9
|
+
import { compose } from 'redux';
|
|
10
|
+
import { connect } from 'react-redux';
|
|
11
|
+
import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
|
|
12
|
+
import { find, isObject } from 'lodash';
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
getVocabFromHint,
|
|
16
|
+
getVocabFromField,
|
|
17
|
+
getVocabFromItems,
|
|
18
|
+
} from '@plone/volto/helpers';
|
|
19
|
+
import { getVocabulary } from '@plone/volto/actions';
|
|
20
|
+
|
|
21
|
+
import {
|
|
22
|
+
Option,
|
|
23
|
+
DropdownIndicator,
|
|
24
|
+
ClearIndicator,
|
|
25
|
+
selectTheme,
|
|
26
|
+
customSelectStyles,
|
|
27
|
+
MenuList,
|
|
28
|
+
SortableMultiValue,
|
|
29
|
+
SortableMultiValueLabel,
|
|
30
|
+
} from '@plone/volto/components/manage/Widgets/SelectStyling';
|
|
31
|
+
|
|
32
|
+
import { FormFieldWrapper } from '@plone/volto/components';
|
|
33
|
+
|
|
34
|
+
const messages = defineMessages({
|
|
35
|
+
select: {
|
|
36
|
+
id: 'Select…',
|
|
37
|
+
defaultMessage: 'Select…',
|
|
38
|
+
},
|
|
39
|
+
no_value: {
|
|
40
|
+
id: 'No value',
|
|
41
|
+
defaultMessage: 'No value',
|
|
42
|
+
},
|
|
43
|
+
no_options: {
|
|
44
|
+
id: 'No options',
|
|
45
|
+
defaultMessage: 'No options',
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
function arrayMove(array, from, to) {
|
|
50
|
+
const slicedArray = array.slice();
|
|
51
|
+
slicedArray.splice(
|
|
52
|
+
to < 0 ? array.length + to : to,
|
|
53
|
+
0,
|
|
54
|
+
slicedArray.splice(from, 1)[0],
|
|
55
|
+
);
|
|
56
|
+
return slicedArray;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function normalizeArrayValue(choices, value) {
|
|
60
|
+
if (!value || !Array.isArray(value)) return [];
|
|
61
|
+
if (value.length === 0) return value;
|
|
62
|
+
|
|
63
|
+
if (typeof value[0] === 'string') {
|
|
64
|
+
// raw value like ['foo', 'bar']
|
|
65
|
+
return value.map((v) => {
|
|
66
|
+
return {
|
|
67
|
+
label: find(choices, (c) => c.value === v)?.label || v,
|
|
68
|
+
value: v,
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (
|
|
74
|
+
isObject(value[0]) &&
|
|
75
|
+
Object.keys(value[0]).includes('token') // Array of objects, w/ label+value
|
|
76
|
+
) {
|
|
77
|
+
return value
|
|
78
|
+
.map((v) => {
|
|
79
|
+
const item = find(choices, (c) => c.value === v.token);
|
|
80
|
+
return item
|
|
81
|
+
? {
|
|
82
|
+
label: item.label || item.title || item.token,
|
|
83
|
+
value: v.token,
|
|
84
|
+
}
|
|
85
|
+
: {
|
|
86
|
+
// avoid a crash if choices doesn't include this item
|
|
87
|
+
label: v.label,
|
|
88
|
+
value: v.token,
|
|
89
|
+
};
|
|
90
|
+
})
|
|
91
|
+
.filter((f) => !!f);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function normalizeChoices(choices) {
|
|
98
|
+
if (Array.isArray(choices) && choices.length && Array.isArray(choices[0])) {
|
|
99
|
+
return choices.map((option) => ({
|
|
100
|
+
value: option[0],
|
|
101
|
+
label:
|
|
102
|
+
// Fix "None" on the serializer, to remove when fixed in p.restapi
|
|
103
|
+
option[1] !== 'None' && option[1] ? option[1] : option[0],
|
|
104
|
+
}));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return choices;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Compare values and return true if equal.
|
|
112
|
+
* Consider upper and lower case.
|
|
113
|
+
* @method compareOption
|
|
114
|
+
* @param {*} inputValue
|
|
115
|
+
* @param {*} option
|
|
116
|
+
* @param {*} accessors
|
|
117
|
+
* @returns {boolean}
|
|
118
|
+
*/
|
|
119
|
+
const compareOption = (inputValue = '', option, accessors) => {
|
|
120
|
+
const candidate = String(inputValue);
|
|
121
|
+
const optionValue = String(accessors.getOptionValue(option));
|
|
122
|
+
const optionLabel = String(accessors.getOptionLabel(option));
|
|
123
|
+
return optionValue === candidate || optionLabel === candidate;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* ArrayWidget component class.
|
|
128
|
+
* @class ArrayWidget
|
|
129
|
+
* @extends Component
|
|
130
|
+
*
|
|
131
|
+
* A createable select array widget will be rendered if the named vocabulary is
|
|
132
|
+
* in the widget definition (hint) like:
|
|
133
|
+
*
|
|
134
|
+
* ```
|
|
135
|
+
* list_field_voc_unconstrained = schema.List(
|
|
136
|
+
* title=u"List field with values from vocabulary but not constrained to them.",
|
|
137
|
+
* description=u"zope.schema.List",
|
|
138
|
+
* value_type=schema.TextLine(),
|
|
139
|
+
* required=False,
|
|
140
|
+
* missing_value=[],
|
|
141
|
+
* )
|
|
142
|
+
* directives.widget(
|
|
143
|
+
* "list_field_voc_unconstrained",
|
|
144
|
+
* AjaxSelectFieldWidget,
|
|
145
|
+
* vocabulary="plone.app.vocabularies.PortalTypes",
|
|
146
|
+
* )
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
class ArrayWidget extends Component {
|
|
150
|
+
/**
|
|
151
|
+
* Property types.
|
|
152
|
+
* @property {Object} propTypes Property types.
|
|
153
|
+
* @static
|
|
154
|
+
*/
|
|
155
|
+
static propTypes = {
|
|
156
|
+
id: PropTypes.string.isRequired,
|
|
157
|
+
title: PropTypes.string.isRequired,
|
|
158
|
+
description: PropTypes.string,
|
|
159
|
+
required: PropTypes.bool,
|
|
160
|
+
error: PropTypes.arrayOf(PropTypes.string),
|
|
161
|
+
getVocabulary: PropTypes.func.isRequired,
|
|
162
|
+
choices: PropTypes.arrayOf(
|
|
163
|
+
PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
|
164
|
+
),
|
|
165
|
+
vocabLoading: PropTypes.bool,
|
|
166
|
+
vocabLoaded: PropTypes.bool,
|
|
167
|
+
items: PropTypes.shape({
|
|
168
|
+
vocabulary: PropTypes.object,
|
|
169
|
+
}),
|
|
170
|
+
widgetOptions: PropTypes.shape({
|
|
171
|
+
vocabulary: PropTypes.object,
|
|
172
|
+
}),
|
|
173
|
+
value: PropTypes.arrayOf(
|
|
174
|
+
PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
|
|
175
|
+
),
|
|
176
|
+
onChange: PropTypes.func.isRequired,
|
|
177
|
+
wrapped: PropTypes.bool,
|
|
178
|
+
creatable: PropTypes.bool, //if widget has no vocab and you want to be creatable
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Default properties
|
|
183
|
+
* @property {Object} defaultProps Default properties.
|
|
184
|
+
* @static
|
|
185
|
+
*/
|
|
186
|
+
static defaultProps = {
|
|
187
|
+
description: null,
|
|
188
|
+
required: false,
|
|
189
|
+
items: {
|
|
190
|
+
vocabulary: null,
|
|
191
|
+
},
|
|
192
|
+
widgetOptions: {
|
|
193
|
+
vocabulary: null,
|
|
194
|
+
},
|
|
195
|
+
error: [],
|
|
196
|
+
choices: [],
|
|
197
|
+
value: null,
|
|
198
|
+
creatable: false,
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Constructor
|
|
203
|
+
* @method constructor
|
|
204
|
+
* @param {Object} props Component properties
|
|
205
|
+
* @constructs Actions
|
|
206
|
+
*/
|
|
207
|
+
constructor(props) {
|
|
208
|
+
super(props);
|
|
209
|
+
|
|
210
|
+
this.handleChange = this.handleChange.bind(this);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Component did mount
|
|
215
|
+
* @method componentDidMount
|
|
216
|
+
* @returns {undefined}
|
|
217
|
+
*/
|
|
218
|
+
componentDidMount() {
|
|
219
|
+
if (
|
|
220
|
+
!this.props.items?.choices?.length &&
|
|
221
|
+
!this.props.choices?.length &&
|
|
222
|
+
this.props.vocabBaseUrl
|
|
223
|
+
) {
|
|
224
|
+
this.props.getVocabulary({
|
|
225
|
+
vocabNameOrURL: this.props.vocabBaseUrl,
|
|
226
|
+
size: -1,
|
|
227
|
+
subrequest: this.props.lang,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
componentDidUpdate() {
|
|
233
|
+
if (
|
|
234
|
+
!this.props.items?.choices?.length &&
|
|
235
|
+
!this.props.choices?.length &&
|
|
236
|
+
this.props.vocabLoading === undefined &&
|
|
237
|
+
!this.props.vocabLoaded
|
|
238
|
+
) {
|
|
239
|
+
this.props.getVocabulary({
|
|
240
|
+
vocabNameOrURL: this.props.vocabBaseUrl,
|
|
241
|
+
size: -1,
|
|
242
|
+
subrequest: this.props.lang,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Handle the field change, store it in the local state and back to simple
|
|
249
|
+
* array of tokens for correct serialization
|
|
250
|
+
* @method handleChange
|
|
251
|
+
* @param {array} selectedOption The selected options (already aggregated).
|
|
252
|
+
* @returns {undefined}
|
|
253
|
+
*/
|
|
254
|
+
handleChange(selectedOption) {
|
|
255
|
+
this.props.onChange(
|
|
256
|
+
this.props.id,
|
|
257
|
+
selectedOption ? selectedOption.map((item) => item.value) : null,
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
onSortEnd = (selectedOption, { oldIndex, newIndex }) => {
|
|
262
|
+
const newValue = arrayMove(selectedOption, oldIndex, newIndex);
|
|
263
|
+
|
|
264
|
+
this.handleChange(newValue);
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Render method.
|
|
269
|
+
* @method render
|
|
270
|
+
* @returns {string} Markup for the component.
|
|
271
|
+
*/
|
|
272
|
+
render() {
|
|
273
|
+
const choices = normalizeChoices(this.props?.choices || []);
|
|
274
|
+
const selectedOption = normalizeArrayValue(choices, this.props.value);
|
|
275
|
+
|
|
276
|
+
const CreatableSelect = this.props.reactSelectCreateable.default;
|
|
277
|
+
const { SortableContainer } = this.props.reactSortableHOC;
|
|
278
|
+
const Select = this.props.reactSelect.default;
|
|
279
|
+
const SortableSelect =
|
|
280
|
+
// It will be only createable if the named vocabulary is in the widget definition
|
|
281
|
+
// (hint) like:
|
|
282
|
+
// list_field_voc_unconstrained = schema.List(
|
|
283
|
+
// title=u"List field with values from vocabulary but not constrained to them.",
|
|
284
|
+
// description=u"zope.schema.List",
|
|
285
|
+
// value_type=schema.TextLine(),
|
|
286
|
+
// required=False,
|
|
287
|
+
// missing_value=[],
|
|
288
|
+
// )
|
|
289
|
+
// directives.widget(
|
|
290
|
+
// "list_field_voc_unconstrained",
|
|
291
|
+
// AjaxSelectFieldWidget,
|
|
292
|
+
// vocabulary="plone.app.vocabularies.PortalTypes",
|
|
293
|
+
// )
|
|
294
|
+
this.props?.choices &&
|
|
295
|
+
!getVocabFromHint(this.props) &&
|
|
296
|
+
!this.props.creatable
|
|
297
|
+
? SortableContainer(Select)
|
|
298
|
+
: SortableContainer(CreatableSelect);
|
|
299
|
+
|
|
300
|
+
return (
|
|
301
|
+
<FormFieldWrapper {...this.props}>
|
|
302
|
+
<SortableSelect
|
|
303
|
+
useDragHandle
|
|
304
|
+
// react-sortable-hoc props:
|
|
305
|
+
axis="xy"
|
|
306
|
+
onSortEnd={this.onSortEnd}
|
|
307
|
+
distance={4}
|
|
308
|
+
// small fix for https://github.com/clauderic/react-sortable-hoc/pull/352:
|
|
309
|
+
getHelperDimensions={({ node }) => node.getBoundingClientRect()}
|
|
310
|
+
id={`field-${this.props.id}`}
|
|
311
|
+
key={this.props.id}
|
|
312
|
+
isDisabled={this.props.disabled || this.props.isDisabled}
|
|
313
|
+
className="react-select-container"
|
|
314
|
+
classNamePrefix="react-select"
|
|
315
|
+
options={
|
|
316
|
+
this.props.vocabBaseUrl
|
|
317
|
+
? choices
|
|
318
|
+
: this.props.choices
|
|
319
|
+
? [
|
|
320
|
+
...choices,
|
|
321
|
+
...(this.props.noValueOption && !this.props.default
|
|
322
|
+
? [
|
|
323
|
+
{
|
|
324
|
+
label: this.props.intl.formatMessage(
|
|
325
|
+
messages.no_value,
|
|
326
|
+
),
|
|
327
|
+
value: 'no-value',
|
|
328
|
+
},
|
|
329
|
+
]
|
|
330
|
+
: []),
|
|
331
|
+
]
|
|
332
|
+
: [
|
|
333
|
+
{
|
|
334
|
+
label: this.props.intl.formatMessage(messages.no_value),
|
|
335
|
+
value: 'no-value',
|
|
336
|
+
},
|
|
337
|
+
]
|
|
338
|
+
}
|
|
339
|
+
styles={customSelectStyles}
|
|
340
|
+
theme={selectTheme}
|
|
341
|
+
components={{
|
|
342
|
+
...(this.props.choices?.length > 25 && {
|
|
343
|
+
MenuList,
|
|
344
|
+
}),
|
|
345
|
+
MultiValue: SortableMultiValue,
|
|
346
|
+
MultiValueLabel: SortableMultiValueLabel,
|
|
347
|
+
DropdownIndicator,
|
|
348
|
+
ClearIndicator,
|
|
349
|
+
Option,
|
|
350
|
+
}}
|
|
351
|
+
value={selectedOption || []}
|
|
352
|
+
placeholder={this.props.intl.formatMessage(messages.select)}
|
|
353
|
+
onChange={this.handleChange}
|
|
354
|
+
isValidNewOption={(
|
|
355
|
+
inputValue,
|
|
356
|
+
selectValue,
|
|
357
|
+
selectOptions,
|
|
358
|
+
accessors,
|
|
359
|
+
) =>
|
|
360
|
+
!(
|
|
361
|
+
!inputValue ||
|
|
362
|
+
selectValue.some((option) =>
|
|
363
|
+
compareOption(inputValue, option, accessors),
|
|
364
|
+
) ||
|
|
365
|
+
selectOptions.some((option) =>
|
|
366
|
+
compareOption(inputValue, option, accessors),
|
|
367
|
+
)
|
|
368
|
+
)
|
|
369
|
+
}
|
|
370
|
+
isClearable
|
|
371
|
+
isMulti
|
|
372
|
+
/>
|
|
373
|
+
</FormFieldWrapper>
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export const ArrayWidgetComponent = injectIntl(ArrayWidget);
|
|
379
|
+
|
|
380
|
+
export default compose(
|
|
381
|
+
injectIntl,
|
|
382
|
+
injectLazyLibs(['reactSelect', 'reactSelectCreateable', 'reactSortableHOC']),
|
|
383
|
+
connect(
|
|
384
|
+
(state, props) => {
|
|
385
|
+
const vocabBaseUrl =
|
|
386
|
+
getVocabFromHint(props) ||
|
|
387
|
+
getVocabFromField(props) ||
|
|
388
|
+
getVocabFromItems(props);
|
|
389
|
+
|
|
390
|
+
const vocabState =
|
|
391
|
+
state.vocabularies?.[vocabBaseUrl]?.subrequests?.[state.intl.locale];
|
|
392
|
+
|
|
393
|
+
// If the schema already has the choices in it, then do not try to get the vocab,
|
|
394
|
+
// even if there is one
|
|
395
|
+
if (props.items?.choices) {
|
|
396
|
+
return {
|
|
397
|
+
choices: props.items.choices,
|
|
398
|
+
lang: state.intl.locale,
|
|
399
|
+
};
|
|
400
|
+
} else if (vocabState) {
|
|
401
|
+
return {
|
|
402
|
+
choices: vocabState.items,
|
|
403
|
+
vocabBaseUrl,
|
|
404
|
+
vocabLoading: vocabState.loading,
|
|
405
|
+
vocabLoaded: vocabState.loaded,
|
|
406
|
+
lang: state.intl.locale,
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
return { vocabBaseUrl, lang: state.intl.locale };
|
|
410
|
+
},
|
|
411
|
+
{ getVocabulary },
|
|
412
|
+
),
|
|
413
|
+
)(ArrayWidget);
|
|
@@ -496,7 +496,7 @@
|
|
|
496
496
|
.ccl-banner-info {
|
|
497
497
|
position: absolute;
|
|
498
498
|
z-index: 1;
|
|
499
|
-
right:
|
|
499
|
+
right: 2rem;
|
|
500
500
|
bottom: 2rem;
|
|
501
501
|
display: none;
|
|
502
502
|
width: 100%;
|
|
@@ -524,9 +524,7 @@
|
|
|
524
524
|
}
|
|
525
525
|
|
|
526
526
|
.ccl-banner-info-link {
|
|
527
|
-
|
|
528
|
-
width: 100%;
|
|
529
|
-
text-align: right;
|
|
527
|
+
float: right;
|
|
530
528
|
}
|
|
531
529
|
|
|
532
530
|
.tabs-block > .styled {
|
package/theme/clms/css/home.css
CHANGED
|
@@ -68,7 +68,6 @@
|
|
|
68
68
|
|
|
69
69
|
.ccl-banner-top-bar {
|
|
70
70
|
height: 2rem;
|
|
71
|
-
padding: 0 1rem;
|
|
72
71
|
border-top: 1px solid #6c6e73;
|
|
73
72
|
border-bottom: 1px solid #6c6e73;
|
|
74
73
|
background-color: #a0b128;
|
|
@@ -91,13 +90,13 @@
|
|
|
91
90
|
}
|
|
92
91
|
|
|
93
92
|
.ccl-banner-top-bar .ccl-container .ccl-banner-top-bar-right {
|
|
94
|
-
margin-left: 0.5rem;
|
|
95
93
|
cursor: pointer;
|
|
96
94
|
}
|
|
97
95
|
|
|
98
96
|
.ccl-banner-top-bar .ccl-container {
|
|
99
97
|
display: flex;
|
|
100
98
|
height: 100%;
|
|
99
|
+
padding: 0 2rem;
|
|
101
100
|
align-items: center;
|
|
102
101
|
justify-content: space-between;
|
|
103
102
|
}
|
package/theme/clms/css/maps.less
CHANGED
|
@@ -583,7 +583,14 @@
|
|
|
583
583
|
margin: 0;
|
|
584
584
|
background: none;
|
|
585
585
|
float: none;
|
|
586
|
-
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
.login-panel .login-text {
|
|
589
|
+
margin-bottom: 1rem;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
.login-panel .login-block .ccl-button {
|
|
593
|
+
margin: 0;
|
|
587
594
|
}
|
|
588
595
|
|
|
589
596
|
#login_close {
|