@eeacms/volto-marine-policy 1.0.0

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 (154) hide show
  1. package/.coverage.babel.config.js +9 -0
  2. package/.eslintrc.js +65 -0
  3. package/.husky/pre-commit +2 -0
  4. package/.release-it.json +17 -0
  5. package/CHANGELOG.md +5 -0
  6. package/DEVELOP.md +53 -0
  7. package/DEVELOP.md.tpl +106 -0
  8. package/Jenkinsfile.tpl +416 -0
  9. package/LICENSE.md +9 -0
  10. package/Makefile.tpl +165 -0
  11. package/README.md +172 -0
  12. package/README.md.tpl +93 -0
  13. package/RELEASE.md +74 -0
  14. package/babel.config.js +17 -0
  15. package/bootstrap +41 -0
  16. package/cypress.config.js +24 -0
  17. package/docker-compose.yml +32 -0
  18. package/jest-addon.config.js +35 -0
  19. package/jest-addon.config.js.tpl +51 -0
  20. package/jest.setup.js +65 -0
  21. package/locales/de/LC_MESSAGES/volto.po +14 -0
  22. package/locales/en/LC_MESSAGES/volto.po +14 -0
  23. package/locales/it/LC_MESSAGES/volto.po +14 -0
  24. package/locales/ro/LC_MESSAGES/volto.po +14 -0
  25. package/locales/volto.pot +16 -0
  26. package/package.json +68 -0
  27. package/package.json.tpl +70 -0
  28. package/razzle.extend.js +29 -0
  29. package/src/components/Blocks/CustomBlockTemplates/customBlockTemplates.js +25 -0
  30. package/src/components/Blocks/MsfdDataExplorerBlock/Edit.jsx +29 -0
  31. package/src/components/Blocks/MsfdDataExplorerBlock/View.jsx +105 -0
  32. package/src/components/Blocks/MsfdDataExplorerBlock/index.js +23 -0
  33. package/src/components/Blocks/MsfdDataExplorerBlock/schema.jsx +30 -0
  34. package/src/components/Result/MarineMeasureItem.jsx +83 -0
  35. package/src/components/Widgets/MeasureViewWidget.jsx +233 -0
  36. package/src/components/Widgets/String.jsx +15 -0
  37. package/src/components/Widgets/TextAlign.jsx +41 -0
  38. package/src/components/Widgets/measure.css +101 -0
  39. package/src/components/index.js +15 -0
  40. package/src/components/theme/AppExtras/PrintPage/PrintPage.jsx +61 -0
  41. package/src/components/theme/AppExtras/PrintPage/css/printpage.less +29 -0
  42. package/src/components/theme/AppExtras/PrintPage/index.js +3 -0
  43. package/src/components/theme/AppExtras/ScrollToTop/ScrollToTop.jsx +61 -0
  44. package/src/components/theme/AppExtras/ScrollToTop/css/scrolltop.less +19 -0
  45. package/src/components/theme/AppExtras/ScrollToTop/index.js +3 -0
  46. package/src/components/theme/AppExtras/index.js +18 -0
  47. package/src/components/theme/DatabaseItemView/DatabaseItemView.jsx +39 -0
  48. package/src/components/theme/DatabaseItemView/style.less +87 -0
  49. package/src/components/theme/Header/HeroSection.jsx +45 -0
  50. package/src/components/theme/Header/StickyHeader.jsx +51 -0
  51. package/src/components/theme/Header/less/globals.less +18 -0
  52. package/src/components/theme/Header/less/herosection.less +64 -0
  53. package/src/components/theme/Header/less/herosection.variables +18 -0
  54. package/src/components/theme/ItemMetadata/ItemMetadata.jsx +217 -0
  55. package/src/components/theme/ItemMetadata/ItemMetadataSnippet.jsx +69 -0
  56. package/src/components/theme/ItemMetadata/ItemTitle.jsx +29 -0
  57. package/src/components/theme/MetadataListingView/MapPreview.jsx +105 -0
  58. package/src/components/theme/MetadataListingView/MetadataHeader.jsx +66 -0
  59. package/src/components/theme/MetadataListingView/MetadataListingView.jsx +36 -0
  60. package/src/components/theme/MetadataListingView/style.less +219 -0
  61. package/src/components/theme/SimpleListingView/SimpleListingView.jsx +97 -0
  62. package/src/components/theme/SimpleListingView/style.less +33 -0
  63. package/src/components/theme/Tableau/TableauDownload.jsx +86 -0
  64. package/src/components/theme/Tableau/TableauFullscreen.jsx +78 -0
  65. package/src/components/theme/Tableau/TableauShare.jsx +128 -0
  66. package/src/components/theme/View/FullwidthView.jsx +102 -0
  67. package/src/components/theme/View/HeroSectionView.jsx +125 -0
  68. package/src/constants/ActionTypes.js +12 -0
  69. package/src/constants/measureFields.js +56 -0
  70. package/src/customizations/@eeacms/volto-block-style/StyleWrapper/schema.js +217 -0
  71. package/src/customizations/@eeacms/volto-eea-design-system/ui/Header/Header.jsx +358 -0
  72. package/src/customizations/@eeacms/volto-eea-design-system/ui/Header/HeaderMenuPopUp.js +403 -0
  73. package/src/customizations/@eeacms/volto-eea-design-system/ui/Header/HeaderSearchPopUp.js +131 -0
  74. package/src/customizations/@eeacms/volto-eea-design-system/ui/Logo/Logo.jsx +32 -0
  75. package/src/customizations/@eeacms/volto-eea-design-system/ui/Logo/marine_logo.svg +63 -0
  76. package/src/customizations/volto/components/manage/Contents/ContentsBreadcrumbs.jsx +81 -0
  77. package/src/customizations/volto/components/manage/Contents/README.md +1 -0
  78. package/src/customizations/volto/components/manage/Toolbar/PersonalTools.jsx +205 -0
  79. package/src/customizations/volto/components/manage/Toolbar/Toolbar.jsx +624 -0
  80. package/src/customizations/volto/components/theme/Breadcrumbs/Breadcrumbs.jsx +49 -0
  81. package/src/customizations/volto/components/theme/Breadcrumbs/README.md +1 -0
  82. package/src/customizations/volto/components/theme/Header/Header.jsx +272 -0
  83. package/src/helpers/index.js +2 -0
  84. package/src/helpers/useCopyToClipboard.js +25 -0
  85. package/src/helpers/useOutsideClick.js +20 -0
  86. package/src/icons/arrow.svg +3 -0
  87. package/src/icons/basket.svg +3 -0
  88. package/src/icons/newspaper.svg +3 -0
  89. package/src/icons/popup.svg +3 -0
  90. package/src/icons/search.svg +3 -0
  91. package/src/icons/star-full.svg +3 -0
  92. package/src/icons/user.svg +3 -0
  93. package/src/index.js +466 -0
  94. package/src/reducers/breadcrumb/breadcrumb.js +59 -0
  95. package/src/reducers/index.js +2 -0
  96. package/src/reducers/localnavigation/localnavigation.js +69 -0
  97. package/src/search/config.js +98 -0
  98. package/src/search/facets.js +85 -0
  99. package/src/search/index.js +48 -0
  100. package/src/search/views.js +15 -0
  101. package/src/slate-styles.less +43 -0
  102. package/src/static/bise_logo.svg +1 -0
  103. package/src/static/cca_logo.svg +20 -0
  104. package/src/static/ec_logo.svg +343 -0
  105. package/src/static/ec_logo_white.svg +10 -0
  106. package/src/static/eea_logo.svg +14 -0
  107. package/src/static/footer-fishes.svg +21 -0
  108. package/src/static/forest_logo.svg +30 -0
  109. package/src/static/freshwater_logo.svg +12 -0
  110. package/src/static/marine_logo.svg +63 -0
  111. package/src/static/marine_logo_white.svg +44 -0
  112. package/src/utils.js +38 -0
  113. package/theme/assets/fonts/Poppins/Poppins-Bold.ttf +0 -0
  114. package/theme/assets/fonts/Poppins/Poppins-Bold.woff +0 -0
  115. package/theme/assets/fonts/Poppins/Poppins-Bold.woff2 +0 -0
  116. package/theme/assets/fonts/Poppins/Poppins-ExtraBold.ttf +0 -0
  117. package/theme/assets/fonts/Poppins/Poppins-Light.ttf +0 -0
  118. package/theme/assets/fonts/Poppins/Poppins-Light.woff +0 -0
  119. package/theme/assets/fonts/Poppins/Poppins-Light.woff2 +0 -0
  120. package/theme/assets/fonts/Poppins/Poppins-Regular.ttf +0 -0
  121. package/theme/assets/fonts/Poppins/Poppins-Regular.woff +0 -0
  122. package/theme/assets/fonts/Poppins/Poppins-Regular.woff2 +0 -0
  123. package/theme/assets/fonts/Poppins/Poppins-SemiBold.ttf +0 -0
  124. package/theme/assets/fonts/Poppins/Poppins-SemiBold.woff +0 -0
  125. package/theme/assets/fonts/Poppins/Poppins-SemiBold.woff2 +0 -0
  126. package/theme/assets/fonts/Roboto/Roboto-Light.ttf +0 -0
  127. package/theme/assets/fonts/Roboto/Roboto-Light.woff +0 -0
  128. package/theme/assets/fonts/Roboto/Roboto-Light.woff2 +0 -0
  129. package/theme/assets/fonts/Roboto/Roboto-Medium.ttf +0 -0
  130. package/theme/assets/fonts/Roboto/Roboto-Medium.woff +0 -0
  131. package/theme/assets/fonts/Roboto/Roboto-Medium.woff2 +0 -0
  132. package/theme/assets/fonts/Roboto/Roboto-Regular.ttf +0 -0
  133. package/theme/assets/fonts/Roboto/Roboto-Regular.woff +0 -0
  134. package/theme/assets/fonts/Roboto/Roboto-Regular.woff2 +0 -0
  135. package/theme/assets/images/Footer/ec_logo.svg +10 -0
  136. package/theme/assets/images/Header/climate-adapt-logo-1.svg +20 -0
  137. package/theme/assets/images/Header/climate-adapt-logo.svg +22 -0
  138. package/theme/assets/images/spinner.svg +1 -0
  139. package/theme/collections/table.variables +17 -0
  140. package/theme/elements/button.overrides +22 -0
  141. package/theme/extras/banner.variables +5 -0
  142. package/theme/extras/contextNavigation.overrides +60 -0
  143. package/theme/extras/contextNavigation.variables +32 -0
  144. package/theme/extras/footer.variables +6 -0
  145. package/theme/extras/header.overrides +20 -0
  146. package/theme/extras/header.variables +7 -0
  147. package/theme/extras/hero.overrides +4 -0
  148. package/theme/extras/inpageNavigation.variables +5 -0
  149. package/theme/extras/mixins.less +8 -0
  150. package/theme/globals/site.overrides +349 -0
  151. package/theme/globals/site.variables +997 -0
  152. package/theme/theme.config +136 -0
  153. package/theme/tokens/colors.less +9 -0
  154. package/theme/tokens/tokens.less +1 -0
@@ -0,0 +1,624 @@
1
+ /**
2
+ * Toolbar component.
3
+ * @module components/manage/Toolbar/Toolbar
4
+ */
5
+
6
+ import React, { Component } from 'react';
7
+ import { defineMessages, injectIntl } from 'react-intl';
8
+ import PropTypes from 'prop-types';
9
+ import jwtDecode from 'jwt-decode';
10
+ import { connect } from 'react-redux';
11
+ import { compose } from 'redux';
12
+ import { doesNodeContainClick } from 'semantic-ui-react/dist/commonjs/lib';
13
+ import { withCookies } from 'react-cookie';
14
+ import { filter, find } from 'lodash';
15
+ import cx from 'classnames';
16
+ import config from '@plone/volto/registry';
17
+
18
+ import More from '@plone/volto/components/manage/Toolbar/More';
19
+ import PersonalTools from '@plone/volto/components/manage/Toolbar/PersonalTools';
20
+ import Types from '@plone/volto/components/manage/Toolbar/Types';
21
+ import PersonalInformation from '@plone/volto/components/manage/Preferences/PersonalInformation';
22
+ import PersonalPreferences from '@plone/volto/components/manage/Preferences/PersonalPreferences';
23
+ import StandardWrapper from '@plone/volto/components/manage/Toolbar/StandardWrapper';
24
+ import {
25
+ getTypes,
26
+ listActions,
27
+ setExpandedToolbar,
28
+ unlockContent,
29
+ } from '@plone/volto/actions';
30
+ import { Icon, UniversalLink } from '@plone/volto/components';
31
+ import {
32
+ BodyClass,
33
+ getBaseUrl,
34
+ getCookieOptions,
35
+ hasApiExpander,
36
+ } from '@plone/volto/helpers';
37
+ import { Pluggable } from '@plone/volto/components/manage/Pluggable';
38
+
39
+ import penSVG from '@plone/volto/icons/pen.svg';
40
+ import unlockSVG from '@plone/volto/icons/unlock.svg';
41
+ import folderSVG from '@plone/volto/icons/folder.svg';
42
+ import addSVG from '@plone/volto/icons/add-document.svg';
43
+ import moreSVG from '@plone/volto/icons/more.svg';
44
+ import userSVG from '@plone/volto/icons/user.svg';
45
+ import backSVG from '@plone/volto/icons/back.svg';
46
+ import clearSVG from '@plone/volto/icons/clear.svg';
47
+
48
+ const messages = defineMessages({
49
+ edit: {
50
+ id: 'Edit',
51
+ defaultMessage: 'Edit',
52
+ },
53
+ contents: {
54
+ id: 'Contents',
55
+ defaultMessage: 'Contents',
56
+ },
57
+ add: {
58
+ id: 'Add',
59
+ defaultMessage: 'Add',
60
+ },
61
+ more: {
62
+ id: 'More',
63
+ defaultMessage: 'More',
64
+ },
65
+ personalTools: {
66
+ id: 'Personal tools',
67
+ defaultMessage: 'Personal tools',
68
+ },
69
+ shrinkToolbar: {
70
+ id: 'Shrink toolbar',
71
+ defaultMessage: 'Shrink toolbar',
72
+ },
73
+ personalInformation: {
74
+ id: 'Personal Information',
75
+ defaultMessage: 'Personal Information',
76
+ },
77
+ personalPreferences: {
78
+ id: 'Personal Preferences',
79
+ defaultMessage: 'Personal Preferences',
80
+ },
81
+ collection: {
82
+ id: 'Collection',
83
+ defaultMessage: 'Collection',
84
+ },
85
+ file: {
86
+ id: 'File',
87
+ defaultMessage: 'File',
88
+ },
89
+ link: {
90
+ id: 'Link',
91
+ defaultMessage: 'Link',
92
+ },
93
+ newsItem: {
94
+ id: 'News Item',
95
+ defaultMessage: 'News Item',
96
+ },
97
+ page: {
98
+ id: 'Page',
99
+ defaultMessage: 'Page',
100
+ },
101
+ back: {
102
+ id: 'Back',
103
+ defaultMessage: 'Back',
104
+ },
105
+ unlock: {
106
+ id: 'Unlock',
107
+ defaultMessage: 'Unlock',
108
+ },
109
+ });
110
+
111
+ let toolbarComponents = {
112
+ personalTools: { component: PersonalTools, wrapper: null },
113
+ more: { component: More, wrapper: null },
114
+ types: { component: Types, wrapper: null, contentAsProps: true },
115
+ profile: {
116
+ component: PersonalInformation,
117
+ wrapper: StandardWrapper,
118
+ wrapperTitle: messages.personalInformation,
119
+ hideToolbarBody: true,
120
+ },
121
+ preferences: {
122
+ component: PersonalPreferences,
123
+ wrapper: StandardWrapper,
124
+ wrapperTitle: messages.personalPreferences,
125
+ hideToolbarBody: true,
126
+ },
127
+ };
128
+
129
+ /**
130
+ * Toolbar container class.
131
+ * @class Toolbar
132
+ * @extends Component
133
+ */
134
+ class Toolbar extends Component {
135
+ /**
136
+ * Property types.
137
+ * @property {Object} propTypes Property types.
138
+ * @static
139
+ */
140
+ static propTypes = {
141
+ actions: PropTypes.shape({
142
+ object: PropTypes.arrayOf(PropTypes.object),
143
+ object_buttons: PropTypes.arrayOf(PropTypes.object),
144
+ user: PropTypes.arrayOf(PropTypes.object),
145
+ }),
146
+ token: PropTypes.string,
147
+ userId: PropTypes.string,
148
+ pathname: PropTypes.string.isRequired,
149
+ content: PropTypes.shape({
150
+ '@type': PropTypes.string,
151
+ is_folderish: PropTypes.bool,
152
+ review_state: PropTypes.string,
153
+ }),
154
+ getTypes: PropTypes.func.isRequired,
155
+ types: PropTypes.arrayOf(
156
+ PropTypes.shape({
157
+ '@id': PropTypes.string,
158
+ addable: PropTypes.bool,
159
+ title: PropTypes.string,
160
+ }),
161
+ ),
162
+ listActions: PropTypes.func.isRequired,
163
+ unlockContent: PropTypes.func,
164
+ unlockRequest: PropTypes.objectOf(PropTypes.any),
165
+ inner: PropTypes.element.isRequired,
166
+ hideDefaultViewButtons: PropTypes.bool,
167
+ };
168
+
169
+ /**
170
+ * Default properties.
171
+ * @property {Object} defaultProps Default properties.
172
+ * @static
173
+ */
174
+ static defaultProps = {
175
+ actions: null,
176
+ token: null,
177
+ userId: null,
178
+ content: null,
179
+ hideDefaultViewButtons: false,
180
+ types: [],
181
+ };
182
+
183
+ toolbarWindow = React.createRef();
184
+
185
+ constructor(props) {
186
+ super(props);
187
+ const { cookies } = props;
188
+ this.state = {
189
+ expanded: cookies.get('toolbar_expanded') !== 'false',
190
+ showMenu: false,
191
+ menuStyle: {},
192
+ menuComponents: [],
193
+ loadedComponents: [],
194
+ hideToolbarBody: false,
195
+ };
196
+ }
197
+
198
+ /**
199
+ * Component will mount
200
+ * @method componentDidMount
201
+ * @returns {undefined}
202
+ */
203
+ componentDidMount() {
204
+ // Do not trigger the actions action if the expander is present
205
+ if (!hasApiExpander('actions', getBaseUrl(this.props.pathname))) {
206
+ this.props.listActions(getBaseUrl(this.props.pathname));
207
+ }
208
+ // Do not trigger the types action if the expander is present
209
+ if (!hasApiExpander('types', getBaseUrl(this.props.pathname))) {
210
+ this.props.getTypes(getBaseUrl(this.props.pathname));
211
+ }
212
+ toolbarComponents = {
213
+ ...(config.settings
214
+ ? config.settings.additionalToolbarComponents || {}
215
+ : {}),
216
+ ...toolbarComponents,
217
+ };
218
+ this.props.setExpandedToolbar(this.state.expanded);
219
+ document.addEventListener('mousedown', this.handleClickOutside, false);
220
+ }
221
+
222
+ /**
223
+ * Component will receive props
224
+ * @method componentWillReceiveProps
225
+ * @param {Object} nextProps Next properties
226
+ * @returns {undefined}
227
+ */
228
+ UNSAFE_componentWillReceiveProps(nextProps) {
229
+ if (nextProps.pathname !== this.props.pathname) {
230
+ // Do not trigger the actions action if the expander is present
231
+ if (!hasApiExpander('actions', getBaseUrl(nextProps.pathname))) {
232
+ this.props.listActions(getBaseUrl(nextProps.pathname));
233
+ }
234
+ // Do not trigger the types action if the expander is present
235
+ if (!hasApiExpander('types', getBaseUrl(nextProps.pathname))) {
236
+ this.props.getTypes(getBaseUrl(nextProps.pathname));
237
+ }
238
+ }
239
+
240
+ // Unlock
241
+ if (this.props.unlockRequest.loading && nextProps.unlockRequest.loaded) {
242
+ this.props.listActions(getBaseUrl(nextProps.pathname));
243
+ }
244
+ }
245
+
246
+ /**
247
+ * Component will receive props
248
+ * @method componentWillUnmount
249
+ * @returns {undefined}
250
+ */
251
+ componentWillUnmount() {
252
+ document.removeEventListener('mousedown', this.handleClickOutside, false);
253
+ }
254
+
255
+ handleShrink = () => {
256
+ const { cookies } = this.props;
257
+ cookies.set('toolbar_expanded', !this.state.expanded, getCookieOptions());
258
+ this.setState(
259
+ (state) => ({ expanded: !state.expanded }),
260
+ () => this.props.setExpandedToolbar(this.state.expanded),
261
+ );
262
+ };
263
+
264
+ closeMenu = () =>
265
+ this.setState(() => ({ showMenu: false, loadedComponents: [] }));
266
+
267
+ loadComponent = (type) => {
268
+ const { loadedComponents } = this.state;
269
+ if (!this.state.loadedComponents.includes(type)) {
270
+ this.setState({
271
+ loadedComponents: [...loadedComponents, type],
272
+ hideToolbarBody: toolbarComponents[type].hideToolbarBody || false,
273
+ });
274
+ }
275
+ };
276
+
277
+ unloadComponent = () => {
278
+ this.setState((state) => ({
279
+ loadedComponents: state.loadedComponents.slice(0, -1),
280
+ hideToolbarBody:
281
+ toolbarComponents[
282
+ state.loadedComponents[state.loadedComponents.length - 2]
283
+ ].hideToolbarBody || false,
284
+ }));
285
+ };
286
+
287
+ toggleMenu = (e, selector) => {
288
+ if (this.state.showMenu) {
289
+ this.closeMenu();
290
+ return;
291
+ }
292
+ // PersonalTools always shows at bottom
293
+ if (selector === 'personalTools') {
294
+ this.setState((state) => ({
295
+ showMenu: !state.showMenu,
296
+ menuStyle: { bottom: 0 },
297
+ }));
298
+ } else if (selector === 'more') {
299
+ this.setState((state) => ({
300
+ showMenu: !state.showMenu,
301
+ menuStyle: {
302
+ overflow: 'visible',
303
+ top: 0,
304
+ },
305
+ }));
306
+ } else {
307
+ this.setState((state) => ({
308
+ showMenu: !state.showMenu,
309
+ menuStyle: { top: 0 },
310
+ }));
311
+ }
312
+ this.loadComponent(selector);
313
+ };
314
+
315
+ handleClickOutside = (e) => {
316
+ if (this.pusher && doesNodeContainClick(this.pusher, e)) return;
317
+ this.closeMenu();
318
+ };
319
+
320
+ unlock = (e) => {
321
+ this.props.unlockContent(getBaseUrl(this.props.pathname), true);
322
+ };
323
+
324
+ /**
325
+ * Render method.
326
+ * @method render
327
+ * @returns {string} Markup for the component.
328
+ */
329
+ render() {
330
+ const path = getBaseUrl(this.props.pathname);
331
+ const lock = this.props.content?.lock;
332
+ const unlockAction =
333
+ lock?.locked && lock?.stealable && lock?.creator !== this.props.userId;
334
+ const editAction =
335
+ !unlockAction && find(this.props.actions.object, { id: 'edit' });
336
+ const folderContentsAction = find(this.props.actions.object, {
337
+ id: 'folderContents',
338
+ });
339
+ const { expanded } = this.state;
340
+
341
+ return (
342
+ this.props.token && (
343
+ <>
344
+ <BodyClass
345
+ className={expanded ? 'has-toolbar' : 'has-toolbar-collapsed'}
346
+ />
347
+ <div
348
+ style={this.state.menuStyle}
349
+ className={
350
+ this.state.showMenu ? 'toolbar-content show' : 'toolbar-content'
351
+ }
352
+ ref={this.toolbarWindow}
353
+ >
354
+ {this.state.showMenu && (
355
+ // This sets the scroll locker in the body tag in mobile
356
+ <BodyClass className="has-toolbar-menu-open" />
357
+ )}
358
+ <div
359
+ className="pusher-puller"
360
+ ref={(node) => (this.pusher = node)}
361
+ style={{
362
+ transform: this.toolbarWindow.current
363
+ ? `translateX(-${
364
+ (this.state.loadedComponents.length - 1) *
365
+ this.toolbarWindow.current.getBoundingClientRect().width
366
+ }px)`
367
+ : null,
368
+ }}
369
+ >
370
+ {this.state.loadedComponents.map((component, index) =>
371
+ (() => {
372
+ const ToolbarComponent =
373
+ toolbarComponents[component].component;
374
+ const WrapperComponent = toolbarComponents[component].wrapper;
375
+ const haveActions =
376
+ toolbarComponents[component].hideToolbarBody;
377
+ const title =
378
+ toolbarComponents[component].wrapperTitle &&
379
+ this.props.intl.formatMessage(
380
+ toolbarComponents[component].wrapperTitle,
381
+ );
382
+ if (WrapperComponent) {
383
+ return (
384
+ <WrapperComponent
385
+ componentName={component}
386
+ componentTitle={title}
387
+ pathname={this.props.pathname}
388
+ loadComponent={this.loadComponent}
389
+ unloadComponent={this.unloadComponent}
390
+ componentIndex={index}
391
+ theToolbar={this.toolbarWindow}
392
+ key={`personalToolsComponent-${index}`}
393
+ closeMenu={this.closeMenu}
394
+ hasActions={haveActions}
395
+ >
396
+ <ToolbarComponent
397
+ pathname={this.props.pathname}
398
+ loadComponent={this.loadComponent}
399
+ unloadComponent={this.unloadComponent}
400
+ componentIndex={index}
401
+ theToolbar={this.toolbarWindow}
402
+ closeMenu={this.closeMenu}
403
+ isToolbarEmbedded
404
+ />
405
+ </WrapperComponent>
406
+ );
407
+ } else {
408
+ return (
409
+ <ToolbarComponent
410
+ pathname={this.props.pathname}
411
+ loadComponent={this.loadComponent}
412
+ unloadComponent={this.unloadComponent}
413
+ componentIndex={index}
414
+ theToolbar={this.toolbarWindow}
415
+ key={`personalToolsComponent-${index}`}
416
+ closeMenu={this.closeMenu}
417
+ content={
418
+ toolbarComponents[component].contentAsProps
419
+ ? this.props.content
420
+ : null
421
+ }
422
+ />
423
+ );
424
+ }
425
+ })(),
426
+ )}
427
+ </div>
428
+ </div>
429
+ <div className={this.state.expanded ? 'toolbar expanded' : 'toolbar'}>
430
+ <div className="toolbar-body">
431
+ <div className="toolbar-actions">
432
+ {this.props.hideDefaultViewButtons && this.props.inner && (
433
+ <>{this.props.inner}</>
434
+ )}
435
+ {!this.props.hideDefaultViewButtons && (
436
+ <>
437
+ {unlockAction && (
438
+ <button
439
+ aria-label={this.props.intl.formatMessage(
440
+ messages.unlock,
441
+ )}
442
+ className="unlock"
443
+ onClick={(e) => this.unlock(e)}
444
+ tabIndex={0}
445
+ >
446
+ <Icon
447
+ name={unlockSVG}
448
+ size="30px"
449
+ className="unlock"
450
+ title={this.props.intl.formatMessage(messages.unlock)}
451
+ />
452
+ </button>
453
+ )}
454
+
455
+ {editAction && (
456
+ <UniversalLink
457
+ aria-label={this.props.intl.formatMessage(
458
+ messages.edit,
459
+ )}
460
+ className="edit"
461
+ href={`${path}/edit`}
462
+ >
463
+ <Icon
464
+ name={penSVG}
465
+ size="30px"
466
+ className="circled"
467
+ title={this.props.intl.formatMessage(messages.edit)}
468
+ />
469
+ </UniversalLink>
470
+ )}
471
+ {this.props.content &&
472
+ this.props.content.is_folderish &&
473
+ folderContentsAction &&
474
+ !this.props.pathname.endsWith('/contents') && (
475
+ <UniversalLink
476
+ aria-label={this.props.intl.formatMessage(
477
+ messages.contents,
478
+ )}
479
+ href={`${path}/contents`}
480
+ >
481
+ <Icon
482
+ name={folderSVG}
483
+ size="30px"
484
+ title={this.props.intl.formatMessage(
485
+ messages.contents,
486
+ )}
487
+ />
488
+ </UniversalLink>
489
+ )}
490
+ {this.props.content &&
491
+ this.props.content.is_folderish &&
492
+ folderContentsAction &&
493
+ this.props.pathname.endsWith('/contents') && (
494
+ <UniversalLink
495
+ href={`${path}`}
496
+ aria-label={this.props.intl.formatMessage(
497
+ messages.back,
498
+ )}
499
+ >
500
+ <Icon
501
+ name={backSVG}
502
+ className="circled"
503
+ size="30px"
504
+ title={this.props.intl.formatMessage(messages.back)}
505
+ />
506
+ </UniversalLink>
507
+ )}
508
+ {this.props.content &&
509
+ ((this.props.content.is_folderish &&
510
+ this.props.types.length > 0) ||
511
+ (config.settings.isMultilingual &&
512
+ this.props.content['@components']?.translations)) && (
513
+ <button
514
+ className="add"
515
+ aria-label={this.props.intl.formatMessage(
516
+ messages.add,
517
+ )}
518
+ onClick={(e) => this.toggleMenu(e, 'types')}
519
+ tabIndex={0}
520
+ id="toolbar-add"
521
+ >
522
+ <Icon
523
+ name={addSVG}
524
+ size="30px"
525
+ title={this.props.intl.formatMessage(messages.add)}
526
+ />
527
+ </button>
528
+ )}
529
+ <div className="toolbar-button-spacer" />
530
+ <button
531
+ className="more"
532
+ aria-label={this.props.intl.formatMessage(messages.more)}
533
+ onClick={(e) => this.toggleMenu(e, 'more')}
534
+ tabIndex={0}
535
+ id="toolbar-more"
536
+ >
537
+ <Icon
538
+ className="mobile hidden"
539
+ name={moreSVG}
540
+ size="30px"
541
+ title={this.props.intl.formatMessage(messages.more)}
542
+ />
543
+ {this.state.showMenu ? (
544
+ <Icon
545
+ className="mobile only"
546
+ name={clearSVG}
547
+ size="30px"
548
+ />
549
+ ) : (
550
+ <Icon
551
+ className="mobile only"
552
+ name={moreSVG}
553
+ size="30px"
554
+ />
555
+ )}
556
+ </button>
557
+ </>
558
+ )}
559
+ <Pluggable name="main.toolbar.top" />
560
+ </div>
561
+ <div className="toolbar-bottom">
562
+ <Pluggable
563
+ name="main.toolbar.bottom"
564
+ params={{ onClickHandler: this.toggleMenu }}
565
+ />
566
+ {!this.props.hideDefaultViewButtons && (
567
+ <button
568
+ className="user"
569
+ aria-label={this.props.intl.formatMessage(
570
+ messages.personalTools,
571
+ )}
572
+ onClick={(e) => this.toggleMenu(e, 'personalTools')}
573
+ tabIndex={0}
574
+ id="toolbar-personal"
575
+ >
576
+ <Icon
577
+ name={userSVG}
578
+ size="30px"
579
+ title={this.props.intl.formatMessage(
580
+ messages.personalTools,
581
+ )}
582
+ />
583
+ </button>
584
+ )}
585
+ </div>
586
+ </div>
587
+ <div className="toolbar-handler">
588
+ <button
589
+ aria-label={this.props.intl.formatMessage(
590
+ messages.shrinkToolbar,
591
+ )}
592
+ className={cx({
593
+ [this.props.content?.review_state]: this.props.content
594
+ ?.review_state,
595
+ })}
596
+ onClick={this.handleShrink}
597
+ />
598
+ </div>
599
+ </div>
600
+ <div className="pusher" />
601
+ </>
602
+ )
603
+ );
604
+ }
605
+ }
606
+
607
+ export default compose(
608
+ injectIntl,
609
+ withCookies,
610
+ connect(
611
+ (state, props) => ({
612
+ actions: state.actions.actions,
613
+ token: state.userSession.token,
614
+ userId: state.userSession.token
615
+ ? jwtDecode(state.userSession.token).sub
616
+ : '',
617
+ content: state.content.data,
618
+ pathname: props.pathname,
619
+ types: filter(state.types.types, 'addable'),
620
+ unlockRequest: state.content.unlock,
621
+ }),
622
+ { getTypes, listActions, setExpandedToolbar, unlockContent },
623
+ ),
624
+ )(Toolbar);
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Breadcrumbs components.
3
+ * @module components/theme/Breadcrumbs/Breadcrumbs
4
+ */
5
+
6
+ import React, { useEffect } from 'react';
7
+ import { useDispatch, useSelector } from 'react-redux';
8
+
9
+ import { useLocation } from 'react-router';
10
+ import { getBaseUrl, hasApiExpander } from '@plone/volto/helpers';
11
+ import { getBreadcrumbs } from '@plone/volto/actions';
12
+
13
+ import EEABreadcrumbs from '@eeacms/volto-eea-design-system/ui/Breadcrumbs/Breadcrumbs';
14
+
15
+ const Breadcrumbs = (props) => {
16
+ const dispatch = useDispatch();
17
+ const { items = [], root = '/marine' } = useSelector(
18
+ (state) => state?.breadcrumbs,
19
+ );
20
+ // const pathname = useSelector((state) => state.location.pathname);
21
+ const location = useLocation();
22
+ const { pathname } = location;
23
+ const breadCrumbsRoot = root?.length > 0 ? root : '/marine';
24
+
25
+ const sections = items.map((item) => ({
26
+ title: item.title,
27
+ href: item.url,
28
+ key: item.title,
29
+ }));
30
+
31
+ useEffect(() => {
32
+ if (!hasApiExpander('breadcrumbs', getBaseUrl(pathname))) {
33
+ dispatch(getBreadcrumbs(getBaseUrl(pathname)));
34
+ }
35
+ }, [dispatch, pathname]);
36
+
37
+ return (
38
+ <React.Fragment>
39
+ <div id="page-header" />
40
+ <EEABreadcrumbs
41
+ pathname={pathname}
42
+ sections={sections}
43
+ root={breadCrumbsRoot}
44
+ />
45
+ </React.Fragment>
46
+ );
47
+ };
48
+
49
+ export default Breadcrumbs;
@@ -0,0 +1 @@
1
+ The only customization here is the removal of isContentRoute helper from https://github.com/eea/volto-eea-website-theme/blob/bf2707262a3d3bf4d0ab90656e69a1babe8dad54/src/customizations/volto/components/theme/Breadcrumbs/Breadcrumbs.jsx#L16