@eeacms/volto-cca-policy 0.1.1
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/.coverage.babel.config.js +9 -0
- package/.i18n.babel.config.js +1 -0
- package/.project.eslintrc.js +48 -0
- package/.release-it.json +17 -0
- package/CHANGELOG.md +30 -0
- package/DEVELOP.md +52 -0
- package/LICENSE.md +9 -0
- package/README.md +85 -0
- package/RELEASE.md +74 -0
- package/babel.config.js +17 -0
- package/bootstrap +41 -0
- package/cypress.config.js +26 -0
- package/jest-addon.config.js +36 -0
- package/locales/volto.pot +0 -0
- package/package.json +51 -0
- package/src/components/index.js +1 -0
- package/src/components/manage/Blocks/ContextNavigation/ContextNavigationEdit.jsx +31 -0
- package/src/components/manage/Blocks/ContextNavigation/ContextNavigationView.jsx +17 -0
- package/src/components/manage/Blocks/ContextNavigation/index.js +26 -0
- package/src/components/manage/Blocks/ContextNavigation/schema.js +81 -0
- package/src/components/manage/Blocks/LayoutSettings/LayoutSettingsEdit.jsx +32 -0
- package/src/components/manage/Blocks/LayoutSettings/LayoutSettingsView.jsx +15 -0
- package/src/components/manage/Blocks/LayoutSettings/edit.less +4 -0
- package/src/components/manage/Blocks/LayoutSettings/index.js +24 -0
- package/src/components/manage/Blocks/LayoutSettings/schema.js +32 -0
- package/src/components/manage/Blocks/Title/Edit.jsx +226 -0
- package/src/components/manage/Blocks/Title/View.jsx +35 -0
- package/src/components/manage/Blocks/Title/index.js +13 -0
- package/src/components/manage/Blocks/Title/schema.js +80 -0
- package/src/components/manage/Blocks/schema-utils.js +16 -0
- package/src/components/manage/Blocks/schema.js +52 -0
- package/src/components/theme/Banner/Banner.jsx +99 -0
- package/src/components/theme/Banner/View.jsx +241 -0
- package/src/components/theme/Banner/styles.less +20 -0
- package/src/components/theme/CustomCSS/CustomCSS.jsx +12 -0
- package/src/components/theme/DraftBackground/DraftBackground.jsx +16 -0
- package/src/components/theme/DraftBackground/draft.css +3 -0
- package/src/components/theme/DraftBackground/draft.png +0 -0
- package/src/components/theme/Homepage/HomePageInverseView.jsx +60 -0
- package/src/components/theme/Homepage/HomePageView.jsx +60 -0
- package/src/components/theme/Logo.jsx +34 -0
- package/src/components/theme/SubsiteClass.jsx +23 -0
- package/src/components/theme/Widgets/TokenWidget.jsx +16 -0
- package/src/config.js +307 -0
- package/src/customizations/@eeacms/volto-block-style/StyleWrapper/schema.js +44 -0
- package/src/customizations/@eeacms/volto-eea-design-system/ui/Header/HeaderSearchPopUp.js +80 -0
- package/src/customizations/@eeacms/volto-tabs-block/components/templates/default/schema.js +109 -0
- package/src/customizations/@eeacms/volto-tabs-block/components/templates/horizontal-responsive/schema.js +109 -0
- package/src/customizations/volto/components/manage/Form/Form.jsx +784 -0
- package/src/customizations/volto/components/manage/Form/ModalForm.jsx +326 -0
- package/src/customizations/volto/components/manage/Sharing/Sharing.jsx +495 -0
- package/src/customizations/volto/components/manage/Widgets/ObjectBrowserWidget.jsx +436 -0
- package/src/customizations/volto/components/theme/Breadcrumbs/Breadcrumbs.jsx +62 -0
- package/src/customizations/volto/components/theme/Comments/Comments.jsx +487 -0
- package/src/customizations/volto/components/theme/Footer/Footer.jsx +90 -0
- package/src/customizations/volto/components/theme/Header/Header.jsx +258 -0
- package/src/customizations/volto/components/theme/Tags/Tags.jsx +53 -0
- package/src/customizations/volto/components/theme/Unauthorized/Unauthorized.jsx +91 -0
- package/src/customizations/volto/components/theme/View/EventView.jsx +90 -0
- package/src/helpers/index.js +44 -0
- package/src/icons/content-box.svg +5 -0
- package/src/icons/image-narrow.svg +5 -0
- package/src/index.js +13 -0
- package/src/middleware/voltoCustom.js +37 -0
- package/src/policy.js +136 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { compose } from 'redux';
|
|
3
|
+
import { connect } from 'react-redux';
|
|
4
|
+
import { Icon, Button, Grid } from 'semantic-ui-react';
|
|
5
|
+
import { formatDate } from '@plone/volto/helpers/Utils/Date';
|
|
6
|
+
import config from '@plone/volto/registry';
|
|
7
|
+
|
|
8
|
+
const socialPlatforms = {
|
|
9
|
+
facebook: {
|
|
10
|
+
shareLink: (url) => `https://facebook.com/sharer.php?u=${url}`,
|
|
11
|
+
},
|
|
12
|
+
twitter: {
|
|
13
|
+
shareLink: (url) => `https://www.twitter.com/share?url=${url}`,
|
|
14
|
+
},
|
|
15
|
+
linkedin: {
|
|
16
|
+
shareLink: (url) =>
|
|
17
|
+
`https://www.linkedin.com/sharing/share-offsite/?url=${url}`,
|
|
18
|
+
},
|
|
19
|
+
reddit: {
|
|
20
|
+
shareLink: (url, title) => `https://reddit.com/submit?url=${url}`,
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const getImageSource = (image) => {
|
|
25
|
+
if (image?.download) return image.download;
|
|
26
|
+
if (image?.encoding)
|
|
27
|
+
return `data:${image['content-type']};${image['encoding']},${image['data']}`;
|
|
28
|
+
return null;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const sharePage = (url, platform) => {
|
|
32
|
+
if (!socialPlatforms[platform]) return;
|
|
33
|
+
const link = document.createElement('a');
|
|
34
|
+
link.setAttribute('href', socialPlatforms[platform].shareLink(url));
|
|
35
|
+
link.setAttribute('target', '_blank');
|
|
36
|
+
link.setAttribute('rel', 'noreferrer');
|
|
37
|
+
link.click();
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const Banner = ({ children }) => {
|
|
41
|
+
return <div className="eea banner">{children}</div>;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
Banner.Action = ({ title, icon, color, onClick, className }) => {
|
|
45
|
+
return (
|
|
46
|
+
<div className="action">
|
|
47
|
+
<Button className={className} basic icon inverted onClick={onClick}>
|
|
48
|
+
<Icon className={icon} color={color}></Icon>
|
|
49
|
+
<span className="mobile hidden">{title}</span>
|
|
50
|
+
</Button>
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
Banner.Content = ({ children, actions }) => {
|
|
56
|
+
return (
|
|
57
|
+
<div className="content">
|
|
58
|
+
<Grid>
|
|
59
|
+
<Grid.Column mobile={10} tablet={9} computer={9}>
|
|
60
|
+
{children}
|
|
61
|
+
</Grid.Column>
|
|
62
|
+
<Grid.Column mobile={2} tablet={3} computer={3} className="actions">
|
|
63
|
+
{actions}
|
|
64
|
+
</Grid.Column>
|
|
65
|
+
</Grid>
|
|
66
|
+
</div>
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
Banner.Title = ({ children }) => (
|
|
71
|
+
<h1 className="documentFirstHeading">{children}</h1>
|
|
72
|
+
);
|
|
73
|
+
Banner.Metadata = ({ children }) => <p className="metadata">{children}</p>;
|
|
74
|
+
Banner.MetadataField = ({ hidden, type = 'text', label, value, title }) => {
|
|
75
|
+
const locale = config.settings.dateLocale || 'en-gb';
|
|
76
|
+
if (hidden || !value) return '';
|
|
77
|
+
if (type === 'date' && value)
|
|
78
|
+
return (
|
|
79
|
+
<span className={`field ${type}`} title={title.replace('{}', value)}>
|
|
80
|
+
{label}{' '}
|
|
81
|
+
{formatDate({
|
|
82
|
+
date: value,
|
|
83
|
+
format: {
|
|
84
|
+
year: 'numeric',
|
|
85
|
+
month: 'short',
|
|
86
|
+
day: '2-digit',
|
|
87
|
+
},
|
|
88
|
+
locale: locale,
|
|
89
|
+
})}
|
|
90
|
+
</span>
|
|
91
|
+
);
|
|
92
|
+
return <span className={`field ${type}`}>{value}</span>;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export default compose(
|
|
96
|
+
connect((state) => ({
|
|
97
|
+
content: state.content.data,
|
|
98
|
+
})),
|
|
99
|
+
)(Banner);
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import React, { useCallback, useMemo } from 'react';
|
|
2
|
+
import { compose } from 'redux';
|
|
3
|
+
import { connect } from 'react-redux';
|
|
4
|
+
import { withRouter } from 'react-router';
|
|
5
|
+
import { defineMessages, injectIntl } from 'react-intl';
|
|
6
|
+
import { startCase } from 'lodash';
|
|
7
|
+
import qs from 'querystring';
|
|
8
|
+
import { Container, Popup } from 'semantic-ui-react';
|
|
9
|
+
import { flattenToAppURL } from '@plone/volto/helpers';
|
|
10
|
+
import Banner from './Banner';
|
|
11
|
+
import { getImageSource, sharePage } from './Banner';
|
|
12
|
+
|
|
13
|
+
import './styles.less';
|
|
14
|
+
|
|
15
|
+
const messages = defineMessages({
|
|
16
|
+
share: {
|
|
17
|
+
id: 'Share',
|
|
18
|
+
defaultMessage: 'Share',
|
|
19
|
+
},
|
|
20
|
+
share_to: {
|
|
21
|
+
id: 'Share to',
|
|
22
|
+
defaultMessage: 'Share to',
|
|
23
|
+
},
|
|
24
|
+
download: {
|
|
25
|
+
id: 'Download',
|
|
26
|
+
defaultMessage: 'Download',
|
|
27
|
+
},
|
|
28
|
+
created: {
|
|
29
|
+
id: 'Created',
|
|
30
|
+
defaultMessage: 'Created',
|
|
31
|
+
},
|
|
32
|
+
created_on: {
|
|
33
|
+
id: 'Created on',
|
|
34
|
+
defaultMessage: 'Created on',
|
|
35
|
+
},
|
|
36
|
+
published: {
|
|
37
|
+
id: 'Published',
|
|
38
|
+
defaultMessage: 'Published',
|
|
39
|
+
},
|
|
40
|
+
published_on: {
|
|
41
|
+
id: 'Published on',
|
|
42
|
+
defaultMessage: 'Published on',
|
|
43
|
+
},
|
|
44
|
+
modified: {
|
|
45
|
+
id: 'Modified',
|
|
46
|
+
defaultMessage: 'Modified',
|
|
47
|
+
},
|
|
48
|
+
modified_on: {
|
|
49
|
+
id: 'Modified on',
|
|
50
|
+
defaultMessage: 'Modified on',
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const friendlyId = (id) => {
|
|
55
|
+
if (typeof id !== 'string') return id;
|
|
56
|
+
return startCase(id);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const ContainerWrapper = ({ fluid, children }) => {
|
|
60
|
+
if (fluid) return <React.Fragment>{children}</React.Fragment>;
|
|
61
|
+
return <Container>{children}</Container>;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const Title = ({ config = {}, properties }) => {
|
|
65
|
+
const view = useMemo(() => {
|
|
66
|
+
return config.view;
|
|
67
|
+
}, [config.view]);
|
|
68
|
+
|
|
69
|
+
if (view) {
|
|
70
|
+
return view;
|
|
71
|
+
}
|
|
72
|
+
return <Banner.Title>{properties['title']}</Banner.Title>;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const View = (props) => {
|
|
76
|
+
const { banner = {}, fluid, intl, location, types = [] } = props;
|
|
77
|
+
const metadata = props.metadata || props.properties;
|
|
78
|
+
const {
|
|
79
|
+
info = [],
|
|
80
|
+
hideContentType,
|
|
81
|
+
hideCreationDate,
|
|
82
|
+
hidePublishingDate,
|
|
83
|
+
hideModificationDate,
|
|
84
|
+
hideShareButton,
|
|
85
|
+
hideDownloadButton,
|
|
86
|
+
// contentType,
|
|
87
|
+
} = props.data;
|
|
88
|
+
// Set query parameters
|
|
89
|
+
const parameters = useMemo(
|
|
90
|
+
() => qs.parse(location.search.replace('?', '')) || {},
|
|
91
|
+
[location],
|
|
92
|
+
);
|
|
93
|
+
// Set dates
|
|
94
|
+
const getDate = useCallback(
|
|
95
|
+
(hidden, key) => {
|
|
96
|
+
return !hidden && metadata[key] ? metadata[key] : null;
|
|
97
|
+
},
|
|
98
|
+
[metadata],
|
|
99
|
+
);
|
|
100
|
+
const creationDate = useMemo(() => getDate(hideCreationDate, 'created'), [
|
|
101
|
+
getDate,
|
|
102
|
+
hideCreationDate,
|
|
103
|
+
]);
|
|
104
|
+
const publishingDate = useMemo(
|
|
105
|
+
() => getDate(hidePublishingDate, 'effective'),
|
|
106
|
+
[getDate, hidePublishingDate],
|
|
107
|
+
);
|
|
108
|
+
const modificationDate = useMemo(
|
|
109
|
+
() => getDate(hideModificationDate, 'modified'),
|
|
110
|
+
[getDate, hideModificationDate],
|
|
111
|
+
);
|
|
112
|
+
// Set image source
|
|
113
|
+
const image = getImageSource(metadata['image']);
|
|
114
|
+
// Get type
|
|
115
|
+
const type = useMemo(() => {
|
|
116
|
+
return (
|
|
117
|
+
types.filter(
|
|
118
|
+
(type) =>
|
|
119
|
+
flattenToAppURL(type['@id']) ===
|
|
120
|
+
`/@types/${metadata['@type'] || parameters.type}`,
|
|
121
|
+
)[0]?.title ||
|
|
122
|
+
friendlyId(metadata['@type']) ||
|
|
123
|
+
metadata['@type'] ||
|
|
124
|
+
parameters.type
|
|
125
|
+
);
|
|
126
|
+
}, [types, metadata, parameters]);
|
|
127
|
+
|
|
128
|
+
return (
|
|
129
|
+
<Banner {...props}>
|
|
130
|
+
<div
|
|
131
|
+
className={image ? 'image' : ''}
|
|
132
|
+
style={image ? { backgroundImage: `url(${image})` } : {}}
|
|
133
|
+
>
|
|
134
|
+
<div className="gradient">
|
|
135
|
+
<ContainerWrapper fluid={fluid}>
|
|
136
|
+
<Banner.Content
|
|
137
|
+
actions={
|
|
138
|
+
<>
|
|
139
|
+
{!hideShareButton && (
|
|
140
|
+
<Popup
|
|
141
|
+
className="share-popup"
|
|
142
|
+
content={() => (
|
|
143
|
+
<>
|
|
144
|
+
<p>{intl.formatMessage(messages.share_to)}</p>
|
|
145
|
+
<div className="actions">
|
|
146
|
+
<Banner.Action
|
|
147
|
+
icon="ri-facebook-fill"
|
|
148
|
+
onClick={() => {
|
|
149
|
+
sharePage(metadata['@id'], 'facebook');
|
|
150
|
+
}}
|
|
151
|
+
/>
|
|
152
|
+
<Banner.Action
|
|
153
|
+
icon="ri-twitter-fill"
|
|
154
|
+
onClick={() => {
|
|
155
|
+
sharePage(metadata['@id'], 'twitter');
|
|
156
|
+
}}
|
|
157
|
+
/>
|
|
158
|
+
<Banner.Action
|
|
159
|
+
icon="ri-linkedin-fill"
|
|
160
|
+
onClick={() => {
|
|
161
|
+
sharePage(metadata['@id'], 'linkedin');
|
|
162
|
+
}}
|
|
163
|
+
/>
|
|
164
|
+
</div>
|
|
165
|
+
</>
|
|
166
|
+
)}
|
|
167
|
+
position="bottom center"
|
|
168
|
+
size="small"
|
|
169
|
+
trigger={
|
|
170
|
+
<Banner.Action
|
|
171
|
+
icon="ri-share-fill"
|
|
172
|
+
title={intl.formatMessage(messages.share)}
|
|
173
|
+
className="share"
|
|
174
|
+
onClick={() => {}}
|
|
175
|
+
/>
|
|
176
|
+
}
|
|
177
|
+
/>
|
|
178
|
+
)}
|
|
179
|
+
{!hideDownloadButton && (
|
|
180
|
+
<Banner.Action
|
|
181
|
+
icon="ri-download-2-fill"
|
|
182
|
+
title={intl.formatMessage(messages.download)}
|
|
183
|
+
className="download"
|
|
184
|
+
onClick={() => {
|
|
185
|
+
window.print();
|
|
186
|
+
}}
|
|
187
|
+
/>
|
|
188
|
+
)}
|
|
189
|
+
</>
|
|
190
|
+
}
|
|
191
|
+
>
|
|
192
|
+
<Title config={banner.title} properties={metadata} />
|
|
193
|
+
<Banner.Metadata>
|
|
194
|
+
<Banner.MetadataField
|
|
195
|
+
type="type"
|
|
196
|
+
hidden={hideContentType}
|
|
197
|
+
// value={contentType || properties['@type'] || parameters.type}
|
|
198
|
+
value={type}
|
|
199
|
+
/>
|
|
200
|
+
<Banner.MetadataField
|
|
201
|
+
type="date"
|
|
202
|
+
label={intl.formatMessage(messages.created)}
|
|
203
|
+
value={creationDate}
|
|
204
|
+
title={`${intl.formatMessage(messages.created_on)} {}`}
|
|
205
|
+
/>
|
|
206
|
+
<Banner.MetadataField
|
|
207
|
+
type="date"
|
|
208
|
+
label={intl.formatMessage(messages.published)}
|
|
209
|
+
value={publishingDate}
|
|
210
|
+
title={`${intl.formatMessage(messages.published_on)} {}`}
|
|
211
|
+
/>
|
|
212
|
+
<Banner.MetadataField
|
|
213
|
+
type="date"
|
|
214
|
+
label={intl.formatMessage(messages.modified)}
|
|
215
|
+
value={modificationDate}
|
|
216
|
+
title={`${intl.formatMessage(messages.modified_on)} {}`}
|
|
217
|
+
/>
|
|
218
|
+
{info.map((item, index) => (
|
|
219
|
+
<Banner.MetadataField
|
|
220
|
+
key={`header-info-${index}`}
|
|
221
|
+
value={item.description}
|
|
222
|
+
/>
|
|
223
|
+
))}
|
|
224
|
+
</Banner.Metadata>
|
|
225
|
+
</Banner.Content>
|
|
226
|
+
</ContainerWrapper>
|
|
227
|
+
</div>
|
|
228
|
+
</div>
|
|
229
|
+
</Banner>
|
|
230
|
+
);
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
export default compose(
|
|
234
|
+
injectIntl,
|
|
235
|
+
withRouter,
|
|
236
|
+
connect((state) => {
|
|
237
|
+
return {
|
|
238
|
+
types: state.types.types,
|
|
239
|
+
};
|
|
240
|
+
}),
|
|
241
|
+
)(View);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
.ui.block.title .eea.banner .content {
|
|
2
|
+
padding-right: 1rem;
|
|
3
|
+
padding-left: 1rem;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.eea.banner .documentFirstHeading {
|
|
7
|
+
border-bottom: none;
|
|
8
|
+
margin-bottom: 0;
|
|
9
|
+
|
|
10
|
+
&::before {
|
|
11
|
+
content: none;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.share-popup {
|
|
16
|
+
.actions {
|
|
17
|
+
display: flex;
|
|
18
|
+
flex-flow: row;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { connect } from 'react-redux';
|
|
3
|
+
import './draft.css';
|
|
4
|
+
import { BodyClass } from '@plone/volto/helpers';
|
|
5
|
+
|
|
6
|
+
const DraftBackground = ({ review_state }) => {
|
|
7
|
+
const draftClass = `wf-state-${review_state}`;
|
|
8
|
+
return <BodyClass className={draftClass} />;
|
|
9
|
+
};
|
|
10
|
+
function propsAreEqual(prevProps, nextProps) {
|
|
11
|
+
return prevProps.review_state === nextProps.review_state;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default connect((state) => ({
|
|
15
|
+
review_state: state.content.data?.review_state,
|
|
16
|
+
}))(React.memo(DraftBackground, propsAreEqual));
|
|
Binary file
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Document view component.
|
|
3
|
+
* @module components/theme/View/HomePageInverseView
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import PropTypes from 'prop-types';
|
|
8
|
+
|
|
9
|
+
import { DefaultView } from '@plone/volto/components/';
|
|
10
|
+
|
|
11
|
+
import { BodyClass } from '@plone/volto/helpers';
|
|
12
|
+
|
|
13
|
+
import { hasBlocksData } from '@plone/volto/helpers';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Component to display the default view.
|
|
17
|
+
* @function HomePageInverseView
|
|
18
|
+
* @param {Object} content Content object.
|
|
19
|
+
* @returns {string} Markup of the component.
|
|
20
|
+
*/
|
|
21
|
+
const HomePageInverseView = ({ content }) => {
|
|
22
|
+
return hasBlocksData(content) ? (
|
|
23
|
+
<>
|
|
24
|
+
<BodyClass className="homepage homepage-inverse" />
|
|
25
|
+
<DefaultView content={content} />
|
|
26
|
+
</>
|
|
27
|
+
) : null;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Property types.
|
|
32
|
+
* @property {Object} propTypes Property types.
|
|
33
|
+
* @static
|
|
34
|
+
*/
|
|
35
|
+
HomePageInverseView.propTypes = {
|
|
36
|
+
/**
|
|
37
|
+
* Content of the object
|
|
38
|
+
*/
|
|
39
|
+
content: PropTypes.shape({
|
|
40
|
+
/**
|
|
41
|
+
* Title of the object
|
|
42
|
+
*/
|
|
43
|
+
title: PropTypes.string,
|
|
44
|
+
/**
|
|
45
|
+
* Description of the object
|
|
46
|
+
*/
|
|
47
|
+
description: PropTypes.string,
|
|
48
|
+
/**
|
|
49
|
+
* Text of the object
|
|
50
|
+
*/
|
|
51
|
+
text: PropTypes.shape({
|
|
52
|
+
/**
|
|
53
|
+
* Data of the text of the object
|
|
54
|
+
*/
|
|
55
|
+
data: PropTypes.string,
|
|
56
|
+
}),
|
|
57
|
+
}).isRequired,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export default HomePageInverseView;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Document view component.
|
|
3
|
+
* @module components/theme/View/HomePageView
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import PropTypes from 'prop-types';
|
|
8
|
+
|
|
9
|
+
import { DefaultView } from '@plone/volto/components/';
|
|
10
|
+
|
|
11
|
+
import { BodyClass } from '@plone/volto/helpers';
|
|
12
|
+
|
|
13
|
+
import { hasBlocksData } from '@plone/volto/helpers';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Component to display the default view.
|
|
17
|
+
* @function HomePageView
|
|
18
|
+
* @param {Object} content Content object.
|
|
19
|
+
* @returns {string} Markup of the component.
|
|
20
|
+
*/
|
|
21
|
+
const HomePageView = ({ content }) => {
|
|
22
|
+
return hasBlocksData(content) ? (
|
|
23
|
+
<>
|
|
24
|
+
<BodyClass className="homepage" />
|
|
25
|
+
<DefaultView content={content} />
|
|
26
|
+
</>
|
|
27
|
+
) : null;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Property types.
|
|
32
|
+
* @property {Object} propTypes Property types.
|
|
33
|
+
* @static
|
|
34
|
+
*/
|
|
35
|
+
HomePageView.propTypes = {
|
|
36
|
+
/**
|
|
37
|
+
* Content of the object
|
|
38
|
+
*/
|
|
39
|
+
content: PropTypes.shape({
|
|
40
|
+
/**
|
|
41
|
+
* Title of the object
|
|
42
|
+
*/
|
|
43
|
+
title: PropTypes.string,
|
|
44
|
+
/**
|
|
45
|
+
* Description of the object
|
|
46
|
+
*/
|
|
47
|
+
description: PropTypes.string,
|
|
48
|
+
/**
|
|
49
|
+
* Text of the object
|
|
50
|
+
*/
|
|
51
|
+
text: PropTypes.shape({
|
|
52
|
+
/**
|
|
53
|
+
* Data of the text of the object
|
|
54
|
+
*/
|
|
55
|
+
data: PropTypes.string,
|
|
56
|
+
}),
|
|
57
|
+
}).isRequired,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export default HomePageView;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { useSelector } from 'react-redux';
|
|
2
|
+
import { defineMessages, useIntl } from 'react-intl';
|
|
3
|
+
import config from '@plone/volto/registry';
|
|
4
|
+
|
|
5
|
+
import { Logo } from '@eeacms/volto-eea-design-system/ui';
|
|
6
|
+
import LogoImage from '@eeacms/volto-eea-design-system/../theme/themes/eea/assets/images/Header/eea-logo.svg';
|
|
7
|
+
|
|
8
|
+
const messages = defineMessages({
|
|
9
|
+
site: {
|
|
10
|
+
id: 'Site',
|
|
11
|
+
defaultMessage: 'Site',
|
|
12
|
+
},
|
|
13
|
+
eeasite: {
|
|
14
|
+
id: 'European Environment Agency',
|
|
15
|
+
defaultMessage: 'European Environment Agency',
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const EEALogo = () => {
|
|
20
|
+
const lang = useSelector((state) => state.intl.locale);
|
|
21
|
+
const intl = useIntl();
|
|
22
|
+
const url = config.settings.isMultilingual ? `/${lang}` : '/';
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<Logo
|
|
26
|
+
src={LogoImage}
|
|
27
|
+
url={url}
|
|
28
|
+
title={intl.formatMessage(messages.site)}
|
|
29
|
+
alt={intl.formatMessage(messages.eeasite)}
|
|
30
|
+
/>
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export default EEALogo;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import cx from 'classnames';
|
|
3
|
+
import { useSelector } from 'react-redux';
|
|
4
|
+
import { useLocation } from 'react-router-dom';
|
|
5
|
+
|
|
6
|
+
import { BodyClass } from '@plone/volto/helpers';
|
|
7
|
+
import { isSubsiteRoot } from 'volto-subsites/utils';
|
|
8
|
+
|
|
9
|
+
const SubsiteClass = () => {
|
|
10
|
+
const subsite = useSelector(
|
|
11
|
+
(state) => state.content?.data?.['@components']?.subsite || {},
|
|
12
|
+
);
|
|
13
|
+
const location = useLocation();
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<BodyClass
|
|
17
|
+
className={cx('subsite', `subsite-${subsite.subsite_css_class?.token}`, {
|
|
18
|
+
'subsite-root': isSubsiteRoot(location.pathname, subsite),
|
|
19
|
+
})}
|
|
20
|
+
/>
|
|
21
|
+
);
|
|
22
|
+
};
|
|
23
|
+
export default SubsiteClass;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import cx from 'classnames';
|
|
3
|
+
import Tag from '@eeacms/volto-eea-design-system/ui/Tag/Tag';
|
|
4
|
+
|
|
5
|
+
export const TokenWidget = ({ value, children, className }) =>
|
|
6
|
+
value ? (
|
|
7
|
+
<span className={cx(className, 'token', 'widget')}>
|
|
8
|
+
{value.map((tag) => (
|
|
9
|
+
<Tag href={`http://search.apps.eea.europa.eu/?q=${tag}`} key={tag}>
|
|
10
|
+
{children ? children(tag) : tag}
|
|
11
|
+
</Tag>
|
|
12
|
+
))}
|
|
13
|
+
</span>
|
|
14
|
+
) : (
|
|
15
|
+
''
|
|
16
|
+
);
|