@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.
Files changed (65) hide show
  1. package/.coverage.babel.config.js +9 -0
  2. package/.i18n.babel.config.js +1 -0
  3. package/.project.eslintrc.js +48 -0
  4. package/.release-it.json +17 -0
  5. package/CHANGELOG.md +30 -0
  6. package/DEVELOP.md +52 -0
  7. package/LICENSE.md +9 -0
  8. package/README.md +85 -0
  9. package/RELEASE.md +74 -0
  10. package/babel.config.js +17 -0
  11. package/bootstrap +41 -0
  12. package/cypress.config.js +26 -0
  13. package/jest-addon.config.js +36 -0
  14. package/locales/volto.pot +0 -0
  15. package/package.json +51 -0
  16. package/src/components/index.js +1 -0
  17. package/src/components/manage/Blocks/ContextNavigation/ContextNavigationEdit.jsx +31 -0
  18. package/src/components/manage/Blocks/ContextNavigation/ContextNavigationView.jsx +17 -0
  19. package/src/components/manage/Blocks/ContextNavigation/index.js +26 -0
  20. package/src/components/manage/Blocks/ContextNavigation/schema.js +81 -0
  21. package/src/components/manage/Blocks/LayoutSettings/LayoutSettingsEdit.jsx +32 -0
  22. package/src/components/manage/Blocks/LayoutSettings/LayoutSettingsView.jsx +15 -0
  23. package/src/components/manage/Blocks/LayoutSettings/edit.less +4 -0
  24. package/src/components/manage/Blocks/LayoutSettings/index.js +24 -0
  25. package/src/components/manage/Blocks/LayoutSettings/schema.js +32 -0
  26. package/src/components/manage/Blocks/Title/Edit.jsx +226 -0
  27. package/src/components/manage/Blocks/Title/View.jsx +35 -0
  28. package/src/components/manage/Blocks/Title/index.js +13 -0
  29. package/src/components/manage/Blocks/Title/schema.js +80 -0
  30. package/src/components/manage/Blocks/schema-utils.js +16 -0
  31. package/src/components/manage/Blocks/schema.js +52 -0
  32. package/src/components/theme/Banner/Banner.jsx +99 -0
  33. package/src/components/theme/Banner/View.jsx +241 -0
  34. package/src/components/theme/Banner/styles.less +20 -0
  35. package/src/components/theme/CustomCSS/CustomCSS.jsx +12 -0
  36. package/src/components/theme/DraftBackground/DraftBackground.jsx +16 -0
  37. package/src/components/theme/DraftBackground/draft.css +3 -0
  38. package/src/components/theme/DraftBackground/draft.png +0 -0
  39. package/src/components/theme/Homepage/HomePageInverseView.jsx +60 -0
  40. package/src/components/theme/Homepage/HomePageView.jsx +60 -0
  41. package/src/components/theme/Logo.jsx +34 -0
  42. package/src/components/theme/SubsiteClass.jsx +23 -0
  43. package/src/components/theme/Widgets/TokenWidget.jsx +16 -0
  44. package/src/config.js +307 -0
  45. package/src/customizations/@eeacms/volto-block-style/StyleWrapper/schema.js +44 -0
  46. package/src/customizations/@eeacms/volto-eea-design-system/ui/Header/HeaderSearchPopUp.js +80 -0
  47. package/src/customizations/@eeacms/volto-tabs-block/components/templates/default/schema.js +109 -0
  48. package/src/customizations/@eeacms/volto-tabs-block/components/templates/horizontal-responsive/schema.js +109 -0
  49. package/src/customizations/volto/components/manage/Form/Form.jsx +784 -0
  50. package/src/customizations/volto/components/manage/Form/ModalForm.jsx +326 -0
  51. package/src/customizations/volto/components/manage/Sharing/Sharing.jsx +495 -0
  52. package/src/customizations/volto/components/manage/Widgets/ObjectBrowserWidget.jsx +436 -0
  53. package/src/customizations/volto/components/theme/Breadcrumbs/Breadcrumbs.jsx +62 -0
  54. package/src/customizations/volto/components/theme/Comments/Comments.jsx +487 -0
  55. package/src/customizations/volto/components/theme/Footer/Footer.jsx +90 -0
  56. package/src/customizations/volto/components/theme/Header/Header.jsx +258 -0
  57. package/src/customizations/volto/components/theme/Tags/Tags.jsx +53 -0
  58. package/src/customizations/volto/components/theme/Unauthorized/Unauthorized.jsx +91 -0
  59. package/src/customizations/volto/components/theme/View/EventView.jsx +90 -0
  60. package/src/helpers/index.js +44 -0
  61. package/src/icons/content-box.svg +5 -0
  62. package/src/icons/image-narrow.svg +5 -0
  63. package/src/index.js +13 -0
  64. package/src/middleware/voltoCustom.js +37 -0
  65. package/src/policy.js +136 -0
@@ -0,0 +1,258 @@
1
+ /**
2
+ * Header component.
3
+ * @module components/theme/Header/Header
4
+ */
5
+
6
+ import React from 'react';
7
+ import { Dropdown, Image } from 'semantic-ui-react';
8
+ import { connect, useDispatch, useSelector } from 'react-redux';
9
+
10
+ import { withRouter } from 'react-router-dom';
11
+ import { UniversalLink } from '@plone/volto/components';
12
+ import {
13
+ getBaseUrl,
14
+ hasApiExpander,
15
+ flattenToAppURL,
16
+ } from '@plone/volto/helpers';
17
+ import { getNavigation } from '@plone/volto/actions';
18
+ import { Header, Logo } from '@eeacms/volto-eea-design-system/ui';
19
+ import { usePrevious } from '@eeacms/volto-eea-design-system/helpers';
20
+ import { find } from 'lodash';
21
+ import globeIcon from '@eeacms/volto-eea-design-system/../theme/themes/eea/assets/images/Header/global-line.svg';
22
+ import eeaFlag from '@eeacms/volto-eea-design-system/../theme/themes/eea/assets/images/Header/eea.png';
23
+
24
+ import config from '@plone/volto/registry';
25
+ import { compose } from 'recompose';
26
+ import { BodyClass } from '@plone/volto/helpers';
27
+
28
+ import cx from 'classnames';
29
+
30
+ function removeTrailingSlash(path) {
31
+ return path.replace(/\/+$/, '');
32
+ }
33
+
34
+ /**
35
+ * EEA Specific Header component.
36
+ */
37
+ const EEAHeader = ({ pathname, token, items, history, subsite }) => {
38
+ const currentLang = useSelector((state) => state.intl.locale);
39
+ const translations = useSelector(
40
+ (state) => state.content.data?.['@components']?.translations?.items,
41
+ );
42
+
43
+ const router_pathname = useSelector((state) => {
44
+ return removeTrailingSlash(state.router?.location?.pathname) || '';
45
+ });
46
+
47
+ const isSubsite = subsite?.['@type'] === 'Subsite';
48
+
49
+ const isHomePageInverse = useSelector((state) => {
50
+ const layout = state.content?.data?.layout;
51
+ const has_home_layout =
52
+ layout === 'homepage_inverse_view' ||
53
+ (__CLIENT__ && document.body.classList.contains('homepage-inverse'));
54
+ return (
55
+ has_home_layout &&
56
+ (pathname === router_pathname || router_pathname.endsWith('/edit'))
57
+ );
58
+ });
59
+
60
+ const { eea } = config.settings;
61
+ const headerOpts = eea.headerOpts || {};
62
+ const { logo, logoWhite } = headerOpts || {};
63
+ const width = useSelector((state) => state.screen?.width);
64
+ const dispatch = useDispatch();
65
+ const previousToken = usePrevious(token);
66
+ const [language, setLanguage] = React.useState(
67
+ currentLang || eea.defaultLanguage,
68
+ );
69
+
70
+ React.useEffect(() => {
71
+ const { settings } = config;
72
+ const base_url = getBaseUrl(pathname);
73
+ if (!hasApiExpander('navigation', base_url)) {
74
+ dispatch(getNavigation(base_url, settings.navDepth));
75
+ }
76
+ }, [pathname, dispatch]);
77
+
78
+ React.useEffect(() => {
79
+ if (token !== previousToken) {
80
+ const { settings } = config;
81
+ const base = getBaseUrl(pathname);
82
+ if (!hasApiExpander('navigation', base)) {
83
+ dispatch(getNavigation(base, settings.navDepth));
84
+ }
85
+ }
86
+ }, [token, dispatch, pathname, previousToken]);
87
+
88
+ return (
89
+ <Header menuItems={items}>
90
+ {isHomePageInverse && <BodyClass className="homepage" />}
91
+ <Header.TopHeader>
92
+ <Header.TopItem className="official-union">
93
+ <Image src={eeaFlag} alt="eea flag"></Image>
94
+ <Header.TopDropdownMenu
95
+ text="An official website of the European Union | How do you know?"
96
+ tabletText="EEA information systems"
97
+ mobileText=" "
98
+ icon="chevron down"
99
+ aria-label="dropdown"
100
+ className=""
101
+ viewportWidth={width}
102
+ >
103
+ <div
104
+ className="content"
105
+ role="menu"
106
+ tabIndex="0"
107
+ onClick={(evt) => evt.stopPropagation()}
108
+ onKeyDown={(evt) => evt.stopPropagation()}
109
+ >
110
+ <p>
111
+ All official European Union website addresses are in the{' '}
112
+ <b>europa.eu</b> domain.
113
+ </p>
114
+ <a
115
+ href="https://europa.eu/european-union/contact/institutions-bodies_en"
116
+ target="_blank"
117
+ rel="noreferrer"
118
+ role="option"
119
+ aria-selected="false"
120
+ >
121
+ See all EU institutions and bodies
122
+ </a>
123
+ </div>
124
+ </Header.TopDropdownMenu>
125
+ </Header.TopItem>
126
+
127
+ {!!headerOpts.partnerLinks && (
128
+ <Header.TopItem>
129
+ <Header.TopDropdownMenu
130
+ id="theme-sites"
131
+ text={headerOpts.partnerLinks.title}
132
+ viewportWidth={width}
133
+ >
134
+ <div className="wrapper">
135
+ {headerOpts.partnerLinks.links.map((item, index) => (
136
+ <Dropdown.Item key={index}>
137
+ <a
138
+ href={item.href}
139
+ className="site"
140
+ target="_blank"
141
+ rel="noreferrer"
142
+ >
143
+ {item.title}
144
+ </a>
145
+ </Dropdown.Item>
146
+ ))}
147
+ </div>
148
+ </Header.TopDropdownMenu>
149
+ </Header.TopItem>
150
+ )}
151
+
152
+ {config.settings.isMultilingual && (
153
+ <Header.TopDropdownMenu
154
+ id="language-switcher"
155
+ className="item"
156
+ text={`${language.toUpperCase()}`}
157
+ mobileText={`${language.toUpperCase()}`}
158
+ icon={
159
+ <Image src={globeIcon} alt="language dropdown globe icon"></Image>
160
+ }
161
+ viewportWidth={width}
162
+ >
163
+ <ul
164
+ className="wrapper language-list"
165
+ role="listbox"
166
+ aria-label="language switcher"
167
+ >
168
+ {eea.languages.map((item, index) => (
169
+ <Dropdown.Item
170
+ as="li"
171
+ key={index}
172
+ text={
173
+ <span>
174
+ {item.name}
175
+ <span className="country-code">
176
+ {item.code.toUpperCase()}
177
+ </span>
178
+ </span>
179
+ }
180
+ onClick={() => {
181
+ const translation = find(translations, {
182
+ language: item.code,
183
+ });
184
+ const to = translation
185
+ ? flattenToAppURL(translation['@id'])
186
+ : `/${item.code}`;
187
+ setLanguage(item.code);
188
+ history.push(to);
189
+ }}
190
+ ></Dropdown.Item>
191
+ ))}
192
+ </ul>
193
+ </Header.TopDropdownMenu>
194
+ )}
195
+ </Header.TopHeader>
196
+ <Header.Main
197
+ pathname={pathname}
198
+ inverted={isHomePageInverse ? true : false}
199
+ transparency={isHomePageInverse ? true : false}
200
+ logo={
201
+ <div {...(isSubsite ? { className: 'logo-wrapper' } : {})}>
202
+ <Logo
203
+ src={isHomePageInverse ? logoWhite : logo}
204
+ title={eea.websiteTitle}
205
+ alt={eea.organisationName}
206
+ url={eea.logoTargetUrl}
207
+ />
208
+
209
+ {!!subsite && subsite.title && (
210
+ <UniversalLink item={subsite} className="subsite-logo">
211
+ {subsite.title}
212
+ </UniversalLink>
213
+ )}
214
+ </div>
215
+ }
216
+ menuItems={items}
217
+ renderGlobalMenuItem={(item, { onClick }) => (
218
+ <a
219
+ href={item.url || '/'}
220
+ title={item.title}
221
+ onClick={(e) => {
222
+ e.preventDefault();
223
+ onClick(e, item);
224
+ }}
225
+ >
226
+ {item.title}
227
+ </a>
228
+ )}
229
+ renderMenuItem={(item, options, props) => (
230
+ <UniversalLink
231
+ href={item.url || '/'}
232
+ title={item.title}
233
+ {...(options || {})}
234
+ className={cx(options?.className, {
235
+ active: item.url === router_pathname,
236
+ })}
237
+ >
238
+ {props?.iconPosition !== 'right' && props?.children}
239
+ <span>{item.title}</span>
240
+ {props?.iconPosition === 'right' && props?.children}
241
+ </UniversalLink>
242
+ )}
243
+ ></Header.Main>
244
+ </Header>
245
+ );
246
+ };
247
+
248
+ export default compose(
249
+ withRouter,
250
+ connect(
251
+ (state) => ({
252
+ token: state.userSession.token,
253
+ items: state.navigation.items,
254
+ subsite: state.content.data?.['@components']?.subsite,
255
+ }),
256
+ { getNavigation },
257
+ ),
258
+ )(EEAHeader);
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Tags component.
3
+ * @module components/theme/Tags/Tags
4
+ */
5
+
6
+ import React from 'react';
7
+ import PropTypes from 'prop-types';
8
+ import TagList from '@eeacms/volto-eea-design-system/ui/TagList/TagList';
9
+ import Tag from '@eeacms/volto-eea-design-system/ui/Tag/Tag';
10
+ import { Container } from 'semantic-ui-react';
11
+
12
+ /**
13
+ * Tags component class.
14
+ * @function Tags
15
+ * @param {array} tags Array of tags.
16
+ * @returns {string} Markup of the component.
17
+ */
18
+ const Tags = ({ tags }) =>
19
+ tags && tags.length > 0 ? (
20
+ <Container className="eea">
21
+ <TagList className="right">
22
+ <TagList.Content>
23
+ {tags.map((tag) => (
24
+ <Tag href={`http://search.apps.eea.europa.eu/?q=${tag}`} key={tag}>
25
+ {tag}
26
+ </Tag>
27
+ ))}
28
+ </TagList.Content>
29
+ </TagList>
30
+ </Container>
31
+ ) : (
32
+ ''
33
+ );
34
+
35
+ /**
36
+ * Property types.
37
+ * @property {Object} propTypes Property types.
38
+ * @static
39
+ */
40
+ Tags.propTypes = {
41
+ tags: PropTypes.arrayOf(PropTypes.string),
42
+ };
43
+
44
+ /**
45
+ * Default properties.
46
+ * @property {Object} defaultProps Default properties.
47
+ * @static
48
+ */
49
+ Tags.defaultProps = {
50
+ tags: null,
51
+ };
52
+
53
+ export default Tags;
@@ -0,0 +1,91 @@
1
+ /**
2
+ * @module components/theme/Unauthorized/Unauthorized
3
+ */
4
+
5
+ import React, { useEffect } from 'react';
6
+ import { useLocation, Link, useHistory } from 'react-router-dom';
7
+ import { getBaseUrl } from '@plone/volto/helpers';
8
+ import { Container, Button } from 'semantic-ui-react';
9
+
10
+ import { FormattedMessage } from 'react-intl';
11
+
12
+ import { withServerErrorCode } from '@plone/volto/helpers/Utils/Utils';
13
+
14
+ /**
15
+ * unauthorized function.
16
+ * @function Unauthorized
17
+ * @returns {string} Markup of the unauthorized page.
18
+ */
19
+
20
+ const Unauthorized = () => {
21
+ const location = useLocation();
22
+ const pathname = location.pathname;
23
+ const base_pathname = getBaseUrl(pathname);
24
+ const login = `${base_pathname}/login`;
25
+ const history = useHistory();
26
+ const [countdown, setCountdown] = React.useState(5);
27
+
28
+ useEffect(() => {
29
+ const login_with_return = login + `?return_url=${pathname}`;
30
+ const timer = setTimeout(() => {
31
+ return history.push(login_with_return);
32
+ }, 5000);
33
+ return () => clearTimeout(timer);
34
+ }, [history, login, pathname]);
35
+
36
+ useEffect(() => {
37
+ const timer = setTimeout(() => {
38
+ if (countdown > 0) {
39
+ setCountdown(countdown - 1);
40
+ } else {
41
+ clearTimeout(timer);
42
+ }
43
+ }, 1000);
44
+ // Clear timeout if the component is unmounted
45
+ return () => clearTimeout(timer);
46
+ }, [countdown]);
47
+
48
+ return (
49
+ <Container className="view-wrapper">
50
+ <h1>
51
+ <FormattedMessage id="Unauthorized" defaultMessage="Unauthorized" />
52
+ </h1>
53
+ <h3>
54
+ <FormattedMessage
55
+ id="Forbidden, you will be redirected to the login screen in "
56
+ defaultMessage="Forbidden, you will be redirected to the login screen in "
57
+ />
58
+ <span id="redirect-countdown">{countdown}</span>.
59
+ </h3>
60
+
61
+ <p className="description">
62
+ <FormattedMessage id="Click" defaultMessage="Click" />{' '}
63
+ <Link
64
+ className={'ui mini compact button my-half unauthorized-buttons'}
65
+ to={login}
66
+ >
67
+ <FormattedMessage id="Log in" defaultMessage="Log in" />
68
+ </Link>
69
+ <FormattedMessage
70
+ id="to get to login screen or click"
71
+ defaultMessage="to get to login screen or click"
72
+ />{' '}
73
+ <Button
74
+ size={'mini'}
75
+ compact
76
+ onClick={() => history.goBack()}
77
+ className={'my-half unauthorized-buttons'}
78
+ >
79
+ <FormattedMessage id="Get back" defaultMessage="Get back" />
80
+ </Button>
81
+ <FormattedMessage
82
+ id="to get to the previous location"
83
+ defaultMessage="to get to the previous location"
84
+ />
85
+ .
86
+ </p>
87
+ </Container>
88
+ );
89
+ };
90
+
91
+ export default withServerErrorCode(401)(Unauthorized);
@@ -0,0 +1,90 @@
1
+ /**
2
+ * EventView view component.
3
+ * @module components/theme/View/EventView
4
+ */
5
+
6
+ import React from 'react';
7
+ import PropTypes from 'prop-types';
8
+ import { hasBlocksData, flattenHTMLToAppURL } from '@plone/volto/helpers';
9
+ import { Image, Grid } from 'semantic-ui-react';
10
+ import RenderBlocks from '@plone/volto/components/theme/View/RenderBlocks';
11
+ import { EventDetails } from '@plone/volto/components';
12
+
13
+ const EventTextfieldView = ({ content }) => (
14
+ <React.Fragment>
15
+ {content.title && <h1 className="documentFirstHeading">{content.title}</h1>}
16
+ {content.description && (
17
+ <p className="documentDescription">{content.description}</p>
18
+ )}
19
+ {content.image && (
20
+ <Image
21
+ className="document-image"
22
+ src={content.image.scales.thumb.download}
23
+ floated="right"
24
+ />
25
+ )}
26
+ {content.text && (
27
+ <div
28
+ dangerouslySetInnerHTML={{
29
+ __html: flattenHTMLToAppURL(content.text.data),
30
+ }}
31
+ />
32
+ )}
33
+ </React.Fragment>
34
+ );
35
+
36
+ /**
37
+ * EventView view component class.
38
+ * @function EventView
39
+ * @params {object} content Content object.
40
+ * @returns {string} Markup of the component.
41
+ */
42
+ const EventView = (props) => {
43
+ const { content } = props;
44
+
45
+ return (
46
+ <div id="page-document" className="ui container viewwrapper event-view">
47
+ <Grid>
48
+ <Grid.Column mobile={12} tablet={7} computer={7}>
49
+ {hasBlocksData(content) ? (
50
+ <RenderBlocks {...props} />
51
+ ) : (
52
+ <EventTextfieldView {...props} />
53
+ )}
54
+ </Grid.Column>
55
+ <Grid.Column mobile={12} tablet={5} computer={5}>
56
+ <EventDetails content={content} />
57
+ </Grid.Column>
58
+ </Grid>
59
+ </div>
60
+ );
61
+ };
62
+
63
+ /**
64
+ * Property types.
65
+ * @property {Object} propTypes Property types.
66
+ * @static
67
+ */
68
+ EventView.propTypes = {
69
+ content: PropTypes.shape({
70
+ title: PropTypes.string,
71
+ description: PropTypes.string,
72
+ text: PropTypes.shape({
73
+ data: PropTypes.string,
74
+ }),
75
+ attendees: PropTypes.arrayOf(PropTypes.string).isRequired,
76
+ contact_email: PropTypes.string,
77
+ contact_name: PropTypes.string,
78
+ contact_phone: PropTypes.string,
79
+ end: PropTypes.string.isRequired,
80
+ event_url: PropTypes.string,
81
+ location: PropTypes.string,
82
+ open_end: PropTypes.bool,
83
+ recurrence: PropTypes.any,
84
+ start: PropTypes.string.isRequired,
85
+ subjects: PropTypes.arrayOf(PropTypes.string).isRequired,
86
+ whole_day: PropTypes.bool,
87
+ }).isRequired,
88
+ };
89
+
90
+ export default EventView;
@@ -0,0 +1,44 @@
1
+ import superagent from 'superagent';
2
+ import config from '@plone/volto/registry';
3
+ import { addHeadersFactory } from '@plone/volto/helpers/Proxy/Proxy';
4
+ import { isArray } from 'lodash';
5
+ import { serializeNodes } from '@plone/volto-slate/editor/render';
6
+
7
+ /**
8
+ * Get a resource image/file with authenticated (if token exist) API headers
9
+ * @function getBackendResourceWithAuth
10
+ * @param {Object} req Request object
11
+ * @return {string} The response with the image
12
+ */
13
+ export const getBackendResourceWithAuth = (req) =>
14
+ new Promise((resolve, reject) => {
15
+ const { settings } = config;
16
+
17
+ let apiPath = '';
18
+ if (settings.internalApiPath && __SERVER__) {
19
+ apiPath = settings.internalApiPath;
20
+ } else if (__DEVELOPMENT__ && settings.devProxyToApiPath) {
21
+ apiPath = settings.devProxyToApiPath;
22
+ } else {
23
+ apiPath = settings.apiPath;
24
+ }
25
+ const backendURL = `${apiPath}${req.path}`;
26
+ const request = superagent
27
+ .get(backendURL)
28
+ .maxResponseSize(settings.maxResponseSize)
29
+ .responseType('blob');
30
+ const authToken = req.universalCookies.get('auth_token');
31
+ if (authToken) {
32
+ request.set('Authorization', `Bearer ${authToken}`);
33
+ }
34
+ request.use(addHeadersFactory(req));
35
+ request.then(resolve).catch(reject);
36
+ });
37
+
38
+ export const createSlateParagraph = (text) => {
39
+ return isArray(text) ? text : config.settings.slate.defaultValue();
40
+ };
41
+
42
+ export const serializeText = (text) => {
43
+ return isArray(text) ? serializeNodes(text) : text;
44
+ };
@@ -0,0 +1,5 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!-- Created with Inkscape (http://www.inkscape.org/) -->
3
+ <svg width="90mm" height="90mm" version="1.1" viewBox="0 0 90 90" xmlns="http://www.w3.org/2000/svg">
4
+ <text x="44.72715" y="38.463978" fill="#000000" font-family="sans-serif" font-size="16.933px" letter-spacing="0px" stroke-width=".26458" text-align="center" text-anchor="middle" word-spacing="0px" style="line-height:1.5" xml:space="preserve"><tspan x="44.72715" y="38.463978" text-align="center">Content</tspan><tspan x="44.72715" y="63.863926" text-align="center">Box</tspan></text>
5
+ </svg>
@@ -0,0 +1,5 @@
1
+ <svg width="36" height="36" viewBox="0 0 36 36" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M10 13L11.9333 11V25L10 23H26L24.0667 25V11L26 13H10ZM26 11V18V21.5V23.5V25H10V11H26Z" fill="black"/>
3
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M7 31H29V29H7V31Z"/>
4
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M7 7H29V5H7V7Z"/>
5
+ </svg>
package/src/index.js ADDED
@@ -0,0 +1,13 @@
1
+ const applyConfig = (config) => {
2
+ config.settings.dateLocale = 'en-gb';
3
+ config.settings.isMultilingual = true;
4
+ config.settings.defaultLanguage =
5
+ config.settings.eea?.defaultLanguage || 'en';
6
+ config.settings.supportedLanguages = config.settings.eea?.languages?.map(
7
+ (item) => item.code,
8
+ ) || ['en'];
9
+
10
+ return config;
11
+ };
12
+
13
+ export default applyConfig;
@@ -0,0 +1,37 @@
1
+ import { getBackendResourceWithAuth } from '@eeacms/volto-cca-policy/helpers';
2
+
3
+ const HEADERS = [
4
+ 'Accept-Ranges',
5
+ 'Cache-Control',
6
+ 'Content-Disposition',
7
+ 'Content-Range',
8
+ 'Content-Type',
9
+ ];
10
+
11
+ function voltoCustomMiddleware(req, res, next) {
12
+ getBackendResourceWithAuth(req)
13
+ .then((resource) => {
14
+ // Just forward the headers that we need
15
+ HEADERS.forEach((header) => {
16
+ if (resource?.get?.(header)) {
17
+ res.set(header, resource.get(header));
18
+ }
19
+ });
20
+ res.status(resource.statusCode);
21
+ res.send(resource.body);
22
+ })
23
+ .catch(() => {
24
+ res.set('Content-Type', 'text/css; charset=utf-8');
25
+ res.status(200);
26
+ res.send(
27
+ '/* Override this by adding a File called voltoCustom.css to backend at portal_skins/custom/manage_main */',
28
+ );
29
+ });
30
+ }
31
+
32
+ export default function (express) {
33
+ const middleware = express.Router();
34
+ middleware.all(['**/voltoCustom.css$'], voltoCustomMiddleware);
35
+ middleware.id = 'voltoCustom.css';
36
+ return middleware;
37
+ }