@eeacms/volto-marine-policy 0.1.20

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 (150) 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/LICENSE.md +9 -0
  8. package/README.md +172 -0
  9. package/RELEASE.md +74 -0
  10. package/babel.config.js +17 -0
  11. package/bootstrap +41 -0
  12. package/cypress.config.js +24 -0
  13. package/docker-compose.yml +32 -0
  14. package/jest-addon.config.js +50 -0
  15. package/jest.setup.js +65 -0
  16. package/locales/de/LC_MESSAGES/volto.po +14 -0
  17. package/locales/en/LC_MESSAGES/volto.po +14 -0
  18. package/locales/it/LC_MESSAGES/volto.po +14 -0
  19. package/locales/ro/LC_MESSAGES/volto.po +14 -0
  20. package/locales/volto.pot +16 -0
  21. package/package.json +69 -0
  22. package/razzle.extend.js +29 -0
  23. package/src/components/Blocks/CustomBlockTemplates/customBlockTemplates.js +25 -0
  24. package/src/components/Blocks/MsfdDataExplorerBlock/Edit.jsx +29 -0
  25. package/src/components/Blocks/MsfdDataExplorerBlock/View.jsx +105 -0
  26. package/src/components/Blocks/MsfdDataExplorerBlock/index.js +23 -0
  27. package/src/components/Blocks/MsfdDataExplorerBlock/schema.jsx +30 -0
  28. package/src/components/Result/MarineMeasureItem.jsx +83 -0
  29. package/src/components/Widgets/MeasureViewWidget.jsx +233 -0
  30. package/src/components/Widgets/String.jsx +15 -0
  31. package/src/components/Widgets/TextAlign.jsx +41 -0
  32. package/src/components/Widgets/measure.css +101 -0
  33. package/src/components/index.js +15 -0
  34. package/src/components/theme/AppExtras/PrintPage/PrintPage.jsx +61 -0
  35. package/src/components/theme/AppExtras/PrintPage/css/printpage.less +29 -0
  36. package/src/components/theme/AppExtras/PrintPage/index.js +3 -0
  37. package/src/components/theme/AppExtras/ScrollToTop/ScrollToTop.jsx +61 -0
  38. package/src/components/theme/AppExtras/ScrollToTop/css/scrolltop.less +19 -0
  39. package/src/components/theme/AppExtras/ScrollToTop/index.js +3 -0
  40. package/src/components/theme/AppExtras/index.js +18 -0
  41. package/src/components/theme/DatabaseItemView/DatabaseItemView.jsx +39 -0
  42. package/src/components/theme/DatabaseItemView/style.less +87 -0
  43. package/src/components/theme/Header/HeroSection.jsx +45 -0
  44. package/src/components/theme/Header/StickyHeader.jsx +51 -0
  45. package/src/components/theme/Header/less/globals.less +18 -0
  46. package/src/components/theme/Header/less/herosection.less +64 -0
  47. package/src/components/theme/Header/less/herosection.variables +18 -0
  48. package/src/components/theme/ItemMetadata/ItemMetadata.jsx +217 -0
  49. package/src/components/theme/ItemMetadata/ItemMetadataSnippet.jsx +69 -0
  50. package/src/components/theme/ItemMetadata/ItemTitle.jsx +29 -0
  51. package/src/components/theme/MetadataListingView/MapPreview.jsx +105 -0
  52. package/src/components/theme/MetadataListingView/MetadataHeader.jsx +66 -0
  53. package/src/components/theme/MetadataListingView/MetadataListingView.jsx +36 -0
  54. package/src/components/theme/MetadataListingView/style.less +219 -0
  55. package/src/components/theme/SimpleListingView/SimpleListingView.jsx +97 -0
  56. package/src/components/theme/SimpleListingView/style.less +33 -0
  57. package/src/components/theme/Tableau/TableauDownload.jsx +86 -0
  58. package/src/components/theme/Tableau/TableauFullscreen.jsx +78 -0
  59. package/src/components/theme/Tableau/TableauShare.jsx +128 -0
  60. package/src/components/theme/View/FullwidthView.jsx +102 -0
  61. package/src/components/theme/View/HeroSectionView.jsx +125 -0
  62. package/src/constants/ActionTypes.js +12 -0
  63. package/src/constants/measureFields.js +56 -0
  64. package/src/customizations/@eeacms/volto-block-style/StyleWrapper/schema.js +217 -0
  65. package/src/customizations/@eeacms/volto-eea-design-system/ui/Header/Header.jsx +358 -0
  66. package/src/customizations/@eeacms/volto-eea-design-system/ui/Header/HeaderMenuPopUp.js +403 -0
  67. package/src/customizations/@eeacms/volto-eea-design-system/ui/Header/HeaderSearchPopUp.js +131 -0
  68. package/src/customizations/@eeacms/volto-eea-design-system/ui/Logo/Logo.jsx +32 -0
  69. package/src/customizations/@eeacms/volto-eea-design-system/ui/Logo/marine_logo.svg +63 -0
  70. package/src/customizations/volto/components/manage/Contents/ContentsBreadcrumbs.jsx +81 -0
  71. package/src/customizations/volto/components/manage/Contents/README.md +1 -0
  72. package/src/customizations/volto/components/manage/Toolbar/PersonalTools.jsx +205 -0
  73. package/src/customizations/volto/components/manage/Toolbar/Toolbar.jsx +624 -0
  74. package/src/customizations/volto/components/theme/Breadcrumbs/Breadcrumbs.jsx +49 -0
  75. package/src/customizations/volto/components/theme/Breadcrumbs/README.md +1 -0
  76. package/src/customizations/volto/components/theme/Header/Header.jsx +272 -0
  77. package/src/helpers/index.js +2 -0
  78. package/src/helpers/useCopyToClipboard.js +25 -0
  79. package/src/helpers/useOutsideClick.js +20 -0
  80. package/src/icons/arrow.svg +3 -0
  81. package/src/icons/basket.svg +3 -0
  82. package/src/icons/newspaper.svg +3 -0
  83. package/src/icons/popup.svg +3 -0
  84. package/src/icons/search.svg +3 -0
  85. package/src/icons/star-full.svg +3 -0
  86. package/src/icons/user.svg +3 -0
  87. package/src/index.js +467 -0
  88. package/src/reducers/breadcrumb/breadcrumb.js +59 -0
  89. package/src/reducers/index.js +2 -0
  90. package/src/reducers/localnavigation/localnavigation.js +69 -0
  91. package/src/search/config.js +93 -0
  92. package/src/search/facets.js +85 -0
  93. package/src/search/index.js +48 -0
  94. package/src/search/views.js +15 -0
  95. package/src/slate-styles.less +43 -0
  96. package/src/static/bise_logo.svg +1 -0
  97. package/src/static/cca_logo.svg +20 -0
  98. package/src/static/ec_logo.svg +343 -0
  99. package/src/static/ec_logo_white.svg +10 -0
  100. package/src/static/eea_logo.svg +14 -0
  101. package/src/static/footer-fishes.svg +21 -0
  102. package/src/static/forest_logo.svg +30 -0
  103. package/src/static/freshwater_logo.svg +12 -0
  104. package/src/static/marine_logo.svg +63 -0
  105. package/src/static/marine_logo_white.svg +44 -0
  106. package/src/utils.js +38 -0
  107. package/theme/assets/fonts/Poppins/Poppins-Bold.ttf +0 -0
  108. package/theme/assets/fonts/Poppins/Poppins-Bold.woff +0 -0
  109. package/theme/assets/fonts/Poppins/Poppins-Bold.woff2 +0 -0
  110. package/theme/assets/fonts/Poppins/Poppins-ExtraBold.ttf +0 -0
  111. package/theme/assets/fonts/Poppins/Poppins-Light.ttf +0 -0
  112. package/theme/assets/fonts/Poppins/Poppins-Light.woff +0 -0
  113. package/theme/assets/fonts/Poppins/Poppins-Light.woff2 +0 -0
  114. package/theme/assets/fonts/Poppins/Poppins-Regular.ttf +0 -0
  115. package/theme/assets/fonts/Poppins/Poppins-Regular.woff +0 -0
  116. package/theme/assets/fonts/Poppins/Poppins-Regular.woff2 +0 -0
  117. package/theme/assets/fonts/Poppins/Poppins-SemiBold.ttf +0 -0
  118. package/theme/assets/fonts/Poppins/Poppins-SemiBold.woff +0 -0
  119. package/theme/assets/fonts/Poppins/Poppins-SemiBold.woff2 +0 -0
  120. package/theme/assets/fonts/Roboto/Roboto-Light.ttf +0 -0
  121. package/theme/assets/fonts/Roboto/Roboto-Light.woff +0 -0
  122. package/theme/assets/fonts/Roboto/Roboto-Light.woff2 +0 -0
  123. package/theme/assets/fonts/Roboto/Roboto-Medium.ttf +0 -0
  124. package/theme/assets/fonts/Roboto/Roboto-Medium.woff +0 -0
  125. package/theme/assets/fonts/Roboto/Roboto-Medium.woff2 +0 -0
  126. package/theme/assets/fonts/Roboto/Roboto-Regular.ttf +0 -0
  127. package/theme/assets/fonts/Roboto/Roboto-Regular.woff +0 -0
  128. package/theme/assets/fonts/Roboto/Roboto-Regular.woff2 +0 -0
  129. package/theme/assets/images/Footer/ec_logo.svg +10 -0
  130. package/theme/assets/images/Header/climate-adapt-logo-1.svg +20 -0
  131. package/theme/assets/images/Header/climate-adapt-logo.svg +22 -0
  132. package/theme/assets/images/Header/wise-marine-logo-white.svg +143 -0
  133. package/theme/assets/images/Header/wise-marine-logo.svg +143 -0
  134. package/theme/assets/images/spinner.svg +1 -0
  135. package/theme/collections/table.variables +17 -0
  136. package/theme/elements/button.overrides +22 -0
  137. package/theme/extras/banner.variables +5 -0
  138. package/theme/extras/contextNavigation.overrides +60 -0
  139. package/theme/extras/contextNavigation.variables +32 -0
  140. package/theme/extras/footer.variables +6 -0
  141. package/theme/extras/header.overrides +20 -0
  142. package/theme/extras/header.variables +7 -0
  143. package/theme/extras/hero.overrides +4 -0
  144. package/theme/extras/inpageNavigation.variables +5 -0
  145. package/theme/extras/mixins.less +8 -0
  146. package/theme/globals/site.overrides +349 -0
  147. package/theme/globals/site.variables +997 -0
  148. package/theme/theme.config +136 -0
  149. package/theme/tokens/colors.less +9 -0
  150. package/theme/tokens/tokens.less +1 -0
@@ -0,0 +1,233 @@
1
+ import React, { useState } from 'react';
2
+ import { Portal } from 'react-portal';
3
+ import { fields } from '@eeacms/volto-marine-policy/constants/measureFields';
4
+ import String from './String';
5
+ import { Accordion } from 'semantic-ui-react';
6
+ import { Icon } from '@plone/volto/components';
7
+ import { BodyClass } from '@plone/volto/helpers';
8
+ import downSVG from '@plone/volto/icons/down-key.svg';
9
+ import upSVG from '@plone/volto/icons/up-key.svg';
10
+ import './measure.css';
11
+
12
+ function IsomorphicPortal({ children }) {
13
+ const [isClient, setIsClient] = React.useState();
14
+ React.useEffect(() => setIsClient(true), []);
15
+
16
+ return isClient ? (
17
+ <Portal node={document.getElementById('page-header')}>{children}</Portal>
18
+ ) : (
19
+ children
20
+ );
21
+ }
22
+
23
+ const MeasureView = (props) => {
24
+ const { origin } = props?.content;
25
+
26
+ //conditional fields shown in view based on origin of measure
27
+ const conditions = {
28
+ 'WFD (Directive 2000/60/EC)': [
29
+ 'nature_of_physical_modification',
30
+ 'effect_on_hydromorphology',
31
+ 'ecological_impacts',
32
+ ],
33
+ 'MSFD (Directive 2008/56/EC)': [
34
+ 'links_to_existing_policies',
35
+ 'ktms_it_links_to',
36
+ 'relevant_targets',
37
+ 'relevant_features_from_msfd_annex_iii',
38
+ 'msfd_spatial_scope',
39
+ ],
40
+ 'HD (Directive 92/43/EEC)': [
41
+ 'measure_purpose',
42
+ 'measure_location',
43
+ 'measure_response',
44
+ 'measure_additional_info',
45
+ 'pressure_type',
46
+ 'pressure_name',
47
+ 'ranking',
48
+ 'region',
49
+ ],
50
+ 'BD (Directive 79/409/EEC)': [
51
+ 'measure_purpose',
52
+ 'measure_location',
53
+ 'measure_response',
54
+ 'measure_additional_info',
55
+ 'pressure_type',
56
+ 'pressure_name',
57
+ 'ranking',
58
+ 'region',
59
+ ],
60
+ 'MSPD (Directive 2008/56/EC)': [
61
+ 'mspd_implementation_status',
62
+ 'shipping_tackled',
63
+ 'traffic_separation_scheme',
64
+ 'priority_areas',
65
+ 'approaching_areas',
66
+ 'precautionary_areas',
67
+ 'areas_to_be_avoided',
68
+ 'future_scenarios',
69
+ 'source',
70
+ 'authority',
71
+ 'general_view',
72
+ 'ports',
73
+ 'future_expectations',
74
+ 'safety_manner',
75
+ 'objective',
76
+ 'categories',
77
+ ],
78
+ Sectorial: ['source'],
79
+ };
80
+
81
+ // Fields that don't need to check the origin condition
82
+ const unconditionalFields = fields.filter(
83
+ (field) => !Object.values(conditions).flat().includes(field.field),
84
+ );
85
+
86
+ // Determine which fields to display in the "Further Information" section
87
+ const getConditionalFields = () => {
88
+ // If origin has no value, display all available fields
89
+ if (!origin || origin.length === 0) {
90
+ const fieldsNames = unconditionalFields.reduce(
91
+ (acc, field) => [...acc, field.field],
92
+ [],
93
+ );
94
+ return fields.filter((field) => !fieldsNames.includes(field.field));
95
+ }
96
+
97
+ // Filter fields based on origin(s)
98
+ return fields.filter((field) => {
99
+ for (let cond of origin) {
100
+ if (conditions[cond]?.includes(field.field)) {
101
+ return true;
102
+ }
103
+ }
104
+ return false;
105
+ });
106
+ };
107
+
108
+ const renderField = (field, fieldLocation) => (
109
+ <div className="measure-field">
110
+ <div className="measure-field-label">
111
+ {field.title}
112
+ {fieldLocation === 'header' && ':'}
113
+ </div>
114
+ <div className="measure-field-value">
115
+ {props.content[field.field] ? (
116
+ <String val={props?.content[field.field]} />
117
+ ) : (
118
+ 'No value'
119
+ )}
120
+ </div>
121
+ <div></div>
122
+ </div>
123
+ );
124
+
125
+ const renderFieldTable = () => (
126
+ <Accordion fluid styled>
127
+ <Accordion.Title
128
+ active={isActiveAccordion}
129
+ index={0}
130
+ onClick={handleAccordionClick}
131
+ >
132
+ <div className="further-information-section">
133
+ <h3>Further information</h3>
134
+ </div>
135
+ <Icon size="30px" name={isActiveAccordion ? upSVG : downSVG} />
136
+ </Accordion.Title>
137
+ <Accordion.Content active={isActiveAccordion}>
138
+ <div className="measure__items">
139
+ <div className="measure__item">
140
+ <div className="table-responsive">
141
+ <table>
142
+ <tbody>
143
+ {getConditionalFields().map((field, index) => (
144
+ <tr
145
+ key={`row-measure-${index}`}
146
+ id={`row-measure-${index}`}
147
+ >
148
+ <td className="measure-field-label">{field.title}</td>
149
+ <td className="measure-field-value">
150
+ {props.content[field.field] ? (
151
+ <String val={props?.content[field.field]} />
152
+ ) : (
153
+ 'No value'
154
+ )}
155
+ </td>
156
+ </tr>
157
+ ))}
158
+ </tbody>
159
+ </table>
160
+ </div>
161
+ </div>
162
+ </div>
163
+ </Accordion.Content>
164
+ </Accordion>
165
+ );
166
+
167
+ const truncateTitle = () => {
168
+ const maxLength = 90;
169
+ if (props?.content?.title?.length > maxLength) {
170
+ const trimmedTitle = props?.content?.title?.substr(0, maxLength);
171
+
172
+ return (
173
+ trimmedTitle.substr(
174
+ 0,
175
+ Math.min(trimmedTitle.length, trimmedTitle.lastIndexOf(' ')),
176
+ ) + '...'
177
+ );
178
+ }
179
+ return props?.content?.title;
180
+ };
181
+
182
+ const [isActiveAccordion, setIsAccordionActive] = useState(true);
183
+
184
+ const handleAccordionClick = () => {
185
+ setIsAccordionActive(!isActiveAccordion);
186
+ };
187
+
188
+ return (
189
+ <div id="page-document" className="view-view-spmeasure ui container">
190
+ <div>
191
+ <React.Fragment>
192
+ <BodyClass className="custom-page-header" />
193
+ <IsomorphicPortal>
194
+ <div className="measure-header content-box">
195
+ <div className="measure-header-content">
196
+ <h1 className="measure-title">
197
+ <String val={truncateTitle()} />
198
+ </h1>
199
+ <div className="measure-field">
200
+ <div className="measure-field-label">Code:</div>
201
+ <div className="measure-field-value">
202
+ <String val={props?.content?.code} />
203
+ </div>
204
+ </div>
205
+ {unconditionalFields
206
+ .slice(0, 2)
207
+ .map((field) => renderField(field, 'header'))}
208
+ </div>
209
+ </div>
210
+ </IsomorphicPortal>
211
+ </React.Fragment>
212
+
213
+ <div className="measure-form">
214
+ <div className="measure-field measure-name">
215
+ <div className="measure-field-label">Measure name</div>
216
+ <div className="measure-field-value">
217
+ <String val={props?.content?.title} />
218
+ </div>
219
+ </div>
220
+
221
+ <div className="unconditional-fields">
222
+ {unconditionalFields.slice(2).map(renderField)}
223
+ </div>
224
+
225
+ {/* Further Information Section */}
226
+ {renderFieldTable()}
227
+ </div>
228
+ </div>
229
+ </div>
230
+ );
231
+ };
232
+
233
+ export default MeasureView;
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+
3
+ const String = ({ val }) => {
4
+ return typeof val === 'string'
5
+ ? val
6
+ : Array.isArray(val)
7
+ ? val.map((item, i) => (
8
+ <span key={i} className="array-string-item">
9
+ <String val={item} key={i} />
10
+ </span>
11
+ ))
12
+ : `${val}`;
13
+ };
14
+
15
+ export default String;
@@ -0,0 +1,41 @@
1
+ import React from 'react';
2
+ import { Button } from 'semantic-ui-react';
3
+ import { FormFieldWrapper, Icon } from '@plone/volto/components';
4
+
5
+ import alignLeftSVG from '@plone/volto/icons/align-left.svg';
6
+ import alignRightSVG from '@plone/volto/icons/align-right.svg';
7
+ import alignJustifySVG from '@plone/volto/icons/align-justify.svg';
8
+ import alignCenterSVG from '@plone/volto/icons/align-center.svg';
9
+
10
+ const VALUE_MAP = [
11
+ ['left', alignLeftSVG],
12
+ ['right', alignRightSVG],
13
+ ['center', alignCenterSVG],
14
+ ['justify', alignJustifySVG],
15
+ ];
16
+
17
+ export default (props) => {
18
+ const { value, onChange, id } = props;
19
+ return (
20
+ <FormFieldWrapper {...props}>
21
+ <div className="align-tools">
22
+ {VALUE_MAP.map(([name, icon], index) => (
23
+ <Button.Group key={`button-group-${name}-${index}`}>
24
+ <Button
25
+ icon
26
+ basic
27
+ compact
28
+ active={value === name}
29
+ aria-label={name}
30
+ onClick={() => {
31
+ onChange(id, name);
32
+ }}
33
+ >
34
+ <Icon name={icon} size="24px" />
35
+ </Button>
36
+ </Button.Group>
37
+ ))}
38
+ </div>
39
+ </FormFieldWrapper>
40
+ );
41
+ };
@@ -0,0 +1,101 @@
1
+ .contenttype-spmeasure .breadcrumbs {
2
+ /* background-color: #004b7f !important; */
3
+ margin-bottom: 1rem !important;
4
+ }
5
+
6
+ /* .contenttype-spmeasure .breadcrumbs .section,
7
+ .contenttype-spmeasure .breadcrumbs .section.active,
8
+ .contenttype-spmeasure .breadcrumbs i {
9
+ color: white !important;
10
+ } */
11
+
12
+ .contenttype-spmeasure .content-area {
13
+ padding-top: 0 !important;
14
+ margin-top: 0 !important;
15
+ }
16
+
17
+ .view-view-spmeasure,
18
+ .measure-form .ui.accordion .content {
19
+ background-color: white;
20
+ }
21
+
22
+ .measure-header {
23
+ z-index: 1;
24
+ background-color: #004b7f !important;
25
+ color: #fff !important;
26
+ }
27
+
28
+ .measure-header:before {
29
+ width: 100vw !important;
30
+ }
31
+
32
+ .measure-header-content {
33
+ display: flex;
34
+ flex-direction: column;
35
+ padding: 30px 0;
36
+ gap: 7px;
37
+ }
38
+
39
+ .measure-title {
40
+ margin-bottom: 0;
41
+ }
42
+
43
+ .unconditional-fields .measure-field,
44
+ .measure-name {
45
+ display: flex;
46
+ flex-direction: column;
47
+ margin-bottom: 10px;
48
+ gap: 5px;
49
+ }
50
+
51
+ .measure-header .measure-field {
52
+ display: flex;
53
+ flex-wrap: wrap;
54
+ gap: 5px;
55
+ }
56
+
57
+ .measure-field-label {
58
+ font-weight: bold;
59
+ }
60
+
61
+ .measure-form .ui.accordion .title {
62
+ width: calc(100% - 15px);
63
+ border-bottom: 1px solid #e6e7e8 !important;
64
+ font-weight: bold;
65
+ }
66
+
67
+ .measure-form .ui.accordion .title svg {
68
+ margin-right: 10%;
69
+ }
70
+
71
+ .measure-form .ui.accordion > * {
72
+ padding-left: 0 !important;
73
+ }
74
+
75
+ .measure__items table {
76
+ width: 100%;
77
+ border: 1px solid #c1c1c1;
78
+ border-collapse: collapse;
79
+ table-layout: fixed;
80
+ }
81
+
82
+ .measure__items tr {
83
+ border: 1px solid #c1c1c1;
84
+ margin-bottom: -12px;
85
+ }
86
+
87
+ .measure__items td {
88
+ padding: 10px 20px;
89
+ border: 1px solid #c1c1c1;
90
+ vertical-align: top;
91
+ }
92
+
93
+ .measure__items .measure-field-label {
94
+ width: 35%;
95
+ background-color: #f9f9f9;
96
+ font-weight: normal;
97
+ }
98
+
99
+ .measure__items .measure-field-value {
100
+ width: 65%;
101
+ }
@@ -0,0 +1,15 @@
1
+ export HeroSection from './theme/Header/HeroSection';
2
+ export StickyHeader from './theme/Header/StickyHeader';
3
+ export HeroSectionView from './theme/View/HeroSectionView';
4
+ export FullwidthView from './theme/View/FullwidthView';
5
+ export MetadataListingView from './theme/MetadataListingView/MetadataListingView';
6
+ export ItemMetadata from './theme/ItemMetadata/ItemMetadata';
7
+ export ItemTitle from './theme/ItemMetadata/ItemTitle';
8
+ export MetadataHeader from './theme/MetadataListingView/MetadataHeader';
9
+ export DatabaseItemView from './theme/DatabaseItemView/DatabaseItemView';
10
+ export SimpleListingView from './theme/SimpleListingView/SimpleListingView';
11
+ export TableauDownload from './theme/Tableau/TableauDownload';
12
+ export TableauShare from './theme/Tableau/TableauShare';
13
+ export TableauFullscreen from './theme/Tableau/TableauFullscreen';
14
+ export ItemMetadataSnippet from './theme/ItemMetadata/ItemMetadataSnippet';
15
+ export MapPreview from './theme/MetadataListingView/MapPreview';
@@ -0,0 +1,61 @@
1
+ import React from 'react';
2
+ import { Portal } from 'react-portal';
3
+ import { compose } from 'redux';
4
+ import { connect } from 'react-redux';
5
+ import { defineMessages, useIntl } from 'react-intl';
6
+ import { Button } from 'semantic-ui-react';
7
+ import { BodyClass, isCmsUi } from '@plone/volto/helpers';
8
+ import { Icon } from '@plone/volto/components';
9
+ import printerSVG from '@plone/volto/icons/printer.svg';
10
+
11
+ import './css/printpage.less';
12
+
13
+ const messages = defineMessages({
14
+ printPageTitle: {
15
+ id: 'Print page',
16
+ defaultMessage: 'Print page',
17
+ },
18
+ });
19
+
20
+ const PrintPage = (props) => {
21
+ const { pathname } = props;
22
+ const intl = useIntl();
23
+ const cmsView = isCmsUi(pathname);
24
+
25
+ const printPage = () => {
26
+ document.getElementById('main').classList.add('print');
27
+ setTimeout(() => {
28
+ window.print();
29
+ }, 1000);
30
+ window.onafterprint = () =>
31
+ document.getElementById('main').classList.remove('print');
32
+ };
33
+
34
+ return (
35
+ <>
36
+ {!cmsView && (
37
+ <Portal node={__CLIENT__ && document.querySelector('.content-area')}>
38
+ <BodyClass className="has-print-button" />
39
+ <div className="ui container">
40
+ <div className="print-button">
41
+ <Button
42
+ basic
43
+ icon
44
+ title={intl.formatMessage(messages.printPageTitle)}
45
+ onClick={printPage}
46
+ >
47
+ <Icon name={printerSVG} size="30px" />
48
+ </Button>
49
+ </div>
50
+ </div>
51
+ </Portal>
52
+ )}
53
+ </>
54
+ );
55
+ };
56
+
57
+ export default compose(
58
+ connect((state, props) => ({
59
+ pathname: state.router.location.pathname,
60
+ })),
61
+ )(PrintPage);
@@ -0,0 +1,29 @@
1
+ @type: 'extra';
2
+ @element: 'custom';
3
+
4
+ @import (multiple, reference, optional) '../../theme.config';
5
+
6
+ .has-print-button {
7
+ .ui.basic.segment.content-area {
8
+ display: flex;
9
+ flex: none;
10
+ flex-direction: column-reverse;
11
+ }
12
+ }
13
+
14
+ .print-button {
15
+ display: flex;
16
+ justify-content: flex-end;
17
+ margin-bottom: 1rem;
18
+
19
+ .ui.basic.button {
20
+ color: #888 !important;
21
+ }
22
+ }
23
+
24
+ body.view-editview,
25
+ body.homepage-view {
26
+ .print-button {
27
+ display: none;
28
+ }
29
+ }
@@ -0,0 +1,3 @@
1
+ import PrintPage from './PrintPage';
2
+
3
+ export default PrintPage;
@@ -0,0 +1,61 @@
1
+ /**
2
+ * ScrollToTop component.
3
+ * @module components/ScrollToTop/ScrollToTop
4
+ */
5
+
6
+ import React, { useState, useEffect } from 'react';
7
+ import { defineMessages, useIntl } from 'react-intl';
8
+ import { Button, Icon } from 'semantic-ui-react';
9
+
10
+ import './css/scrolltop.less';
11
+
12
+ const messages = defineMessages({
13
+ scrollToTop: {
14
+ id: 'Scroll to top',
15
+ defaultMessage: 'Scroll to top',
16
+ },
17
+ });
18
+
19
+ const ScrollToTop = () => {
20
+ const intl = useIntl();
21
+ const [isVisible, setIsVisible] = useState(false);
22
+
23
+ useEffect(() => {
24
+ window.addEventListener('scroll', toggleVisibility);
25
+ return () => {
26
+ window.removeEventListener('scroll', toggleVisibility);
27
+ };
28
+ }, []);
29
+
30
+ const toggleVisibility = () => {
31
+ if (window.pageYOffset > 300) {
32
+ setIsVisible(true);
33
+ } else {
34
+ setIsVisible(false);
35
+ }
36
+ };
37
+
38
+ const scrollToTop = () => {
39
+ window.scrollTo({
40
+ top: 0,
41
+ behavior: 'smooth',
42
+ });
43
+ };
44
+ return (
45
+ <>
46
+ {isVisible && (
47
+ <div className="scroll-to-top">
48
+ <Button
49
+ icon
50
+ title={intl.formatMessage(messages.scrollToTop)}
51
+ onClick={scrollToTop}
52
+ >
53
+ <Icon name="arrow up" />
54
+ </Button>
55
+ </div>
56
+ )}
57
+ </>
58
+ );
59
+ };
60
+
61
+ export default ScrollToTop;
@@ -0,0 +1,19 @@
1
+ @type: 'extra';
2
+ @element: 'custom';
3
+
4
+ @import (multiple, reference, optional) '../../theme.config';
5
+
6
+ .scroll-to-top {
7
+ position: fixed;
8
+ right: 20px;
9
+ bottom: 20px;
10
+
11
+ button {
12
+ background-color: @secondaryColor !important;
13
+ color: @primaryColor !important;
14
+
15
+ &:hover {
16
+ opacity: 0.8;
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,3 @@
1
+ import ScrollToTop from './ScrollToTop';
2
+
3
+ export default ScrollToTop;
@@ -0,0 +1,18 @@
1
+ import ScrollToTop from './ScrollToTop';
2
+ // import PrintPage from './PrintPage';
3
+
4
+ export default (config) => {
5
+ config.settings.appExtras = [
6
+ ...(config.settings.appExtras || []),
7
+ {
8
+ match: '',
9
+ component: ScrollToTop,
10
+ },
11
+ // {
12
+ // match: '',
13
+ // component: PrintPage,
14
+ // },
15
+ ];
16
+
17
+ return config;
18
+ };
@@ -0,0 +1,39 @@
1
+ import React from 'react';
2
+ import { BodyClass } from '@plone/volto/helpers';
3
+ import {
4
+ ItemMetadataSnippet,
5
+ ItemMetadata,
6
+ } from '@eeacms/volto-marine-policy/components';
7
+ import { formatItemType } from '@eeacms/volto-marine-policy/utils';
8
+
9
+ import './style.less';
10
+
11
+ const DatabaseItemView = (props) => {
12
+ const { content } = props;
13
+
14
+ return (
15
+ <>
16
+ <BodyClass className="database-item-view" />
17
+ <div id="page-document" className="ui container">
18
+ <div>
19
+ <div className="metadata-header">
20
+ {content['@type'] && (
21
+ <h3 className="item-type">{formatItemType(content['@type'])}</h3>
22
+ )}
23
+ <h1>{content.title}</h1>
24
+
25
+ <ItemMetadataSnippet {...props} item={content} />
26
+ </div>
27
+ </div>
28
+ <ItemMetadata
29
+ {...props}
30
+ item={content}
31
+ map_preview={true}
32
+ item_view={true}
33
+ />
34
+ </div>
35
+ </>
36
+ );
37
+ };
38
+
39
+ export default DatabaseItemView;