@eeacms/volto-n2k 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 (233) hide show
  1. package/.coverage.babel.config.js +9 -0
  2. package/.release-it.json +17 -0
  3. package/CHANGELOG.md +155 -0
  4. package/DEVELOP.md +53 -0
  5. package/Jenkinsfile +209 -0
  6. package/LICENSE.md +9 -0
  7. package/README.md +62 -0
  8. package/bootstrap +41 -0
  9. package/cypress/fixtures/example.json +5 -0
  10. package/cypress/integration/block-basics.js +32 -0
  11. package/cypress/plugins/index.js +26 -0
  12. package/cypress/support/commands.js +315 -0
  13. package/cypress/support/index.js +53 -0
  14. package/cypress.json +12 -0
  15. package/jest-addon.config.js +36 -0
  16. package/package.json +57 -0
  17. package/src/actions.js +20 -0
  18. package/src/components/index.js +3 -0
  19. package/src/components/manage/Blocks/BodyClass/Edit.jsx +29 -0
  20. package/src/components/manage/Blocks/BodyClass/View.jsx +13 -0
  21. package/src/components/manage/Blocks/BodyClass/index.js +24 -0
  22. package/src/components/manage/Blocks/BodyClass/schema.js +19 -0
  23. package/src/components/manage/Blocks/BubbleChart/BubbleChart.jsx +101 -0
  24. package/src/components/manage/Blocks/BubbleChart/Chart.jsx +67 -0
  25. package/src/components/manage/Blocks/BubbleChart/ChartContext.jsx +3 -0
  26. package/src/components/manage/Blocks/BubbleChart/View.jsx +63 -0
  27. package/src/components/manage/Blocks/BubbleChart/index.js +17 -0
  28. package/src/components/manage/Blocks/BubbleChart/schema.js +124 -0
  29. package/src/components/manage/Blocks/BubbleChart/style.less +12 -0
  30. package/src/components/manage/Blocks/CarouselHorizontal/HorizontalView.jsx +221 -0
  31. package/src/components/manage/Blocks/CarouselHorizontal/index.js +19 -0
  32. package/src/components/manage/Blocks/CarouselHorizontal/schema.js +32 -0
  33. package/src/components/manage/Blocks/CddaShape/View.jsx +109 -0
  34. package/src/components/manage/Blocks/CddaShape/index.js +23 -0
  35. package/src/components/manage/Blocks/CddaShape/schema.js +19 -0
  36. package/src/components/manage/Blocks/CddaShape/style.less +14 -0
  37. package/src/components/manage/Blocks/ContactBlock/View.jsx +56 -0
  38. package/src/components/manage/Blocks/ContactBlock/icons/domain.svg +1 -0
  39. package/src/components/manage/Blocks/ContactBlock/icons/email.svg +1 -0
  40. package/src/components/manage/Blocks/ContactBlock/icons/location.svg +1 -0
  41. package/src/components/manage/Blocks/ContactBlock/index.js +17 -0
  42. package/src/components/manage/Blocks/ContactBlock/schema.js +57 -0
  43. package/src/components/manage/Blocks/ContactBlock/styles.less +31 -0
  44. package/src/components/manage/Blocks/ExplodedPiesChart/Pie.jsx +125 -0
  45. package/src/components/manage/Blocks/ExplodedPiesChart/View.jsx +80 -0
  46. package/src/components/manage/Blocks/ExplodedPiesChart/index.js +17 -0
  47. package/src/components/manage/Blocks/ExplodedPiesChart/schema.js +75 -0
  48. package/src/components/manage/Blocks/ExplodedPiesChart/style.less +80 -0
  49. package/src/components/manage/Blocks/ExploreHabitats/Edit.jsx +29 -0
  50. package/src/components/manage/Blocks/ExploreHabitats/View.jsx +177 -0
  51. package/src/components/manage/Blocks/ExploreHabitats/index.js +24 -0
  52. package/src/components/manage/Blocks/ExploreHabitats/schema.js +15 -0
  53. package/src/components/manage/Blocks/ExploreHabitats/style.less +15 -0
  54. package/src/components/manage/Blocks/ExploreSites/Edit.jsx +29 -0
  55. package/src/components/manage/Blocks/ExploreSites/View.jsx +175 -0
  56. package/src/components/manage/Blocks/ExploreSites/index.js +24 -0
  57. package/src/components/manage/Blocks/ExploreSites/schema.js +15 -0
  58. package/src/components/manage/Blocks/ExploreSites/style.less +15 -0
  59. package/src/components/manage/Blocks/ExploreSpecies/Edit.jsx +29 -0
  60. package/src/components/manage/Blocks/ExploreSpecies/View.jsx +177 -0
  61. package/src/components/manage/Blocks/ExploreSpecies/index.js +24 -0
  62. package/src/components/manage/Blocks/ExploreSpecies/schema.js +15 -0
  63. package/src/components/manage/Blocks/ExploreSpecies/style.less +15 -0
  64. package/src/components/manage/Blocks/HabitatClassification/View.jsx +30 -0
  65. package/src/components/manage/Blocks/HabitatClassification/index.js +17 -0
  66. package/src/components/manage/Blocks/HabitatClassification/schema.js +19 -0
  67. package/src/components/manage/Blocks/HabitatClassification/style.less +3 -0
  68. package/src/components/manage/Blocks/HabitatDistribution/View.jsx +97 -0
  69. package/src/components/manage/Blocks/HabitatDistribution/index.js +23 -0
  70. package/src/components/manage/Blocks/HabitatDistribution/schema.js +19 -0
  71. package/src/components/manage/Blocks/HabitatDistribution/style.less +5 -0
  72. package/src/components/manage/Blocks/HabitatProtectedSites/View.jsx +97 -0
  73. package/src/components/manage/Blocks/HabitatProtectedSites/index.js +23 -0
  74. package/src/components/manage/Blocks/HabitatProtectedSites/schema.js +19 -0
  75. package/src/components/manage/Blocks/HabitatProtectedSites/style.less +5 -0
  76. package/src/components/manage/Blocks/HabitatsBanner/View.jsx +39 -0
  77. package/src/components/manage/Blocks/HabitatsBanner/index.js +17 -0
  78. package/src/components/manage/Blocks/HabitatsBanner/schema.js +19 -0
  79. package/src/components/manage/Blocks/HabitatsBanner/style.less +49 -0
  80. package/src/components/manage/Blocks/ImageText/Edit.jsx +98 -0
  81. package/src/components/manage/Blocks/ImageText/View.jsx +66 -0
  82. package/src/components/manage/Blocks/ImageText/index.js +24 -0
  83. package/src/components/manage/Blocks/ImageText/schema.js +69 -0
  84. package/src/components/manage/Blocks/ImageText/styles.less +87 -0
  85. package/src/components/manage/Blocks/Landing/DefalutView.jsx +83 -0
  86. package/src/components/manage/Blocks/Landing/Edit.jsx +219 -0
  87. package/src/components/manage/Blocks/Landing/EditBlockWrapper.jsx +161 -0
  88. package/src/components/manage/Blocks/Landing/View.jsx +65 -0
  89. package/src/components/manage/Blocks/Landing/images/background.webp +0 -0
  90. package/src/components/manage/Blocks/Landing/images/coasts_and_seas.webp +0 -0
  91. package/src/components/manage/Blocks/Landing/images/forests.webp +0 -0
  92. package/src/components/manage/Blocks/Landing/images/grasslands.webp +0 -0
  93. package/src/components/manage/Blocks/Landing/images/hiker.webp +0 -0
  94. package/src/components/manage/Blocks/Landing/images/islands.webp +0 -0
  95. package/src/components/manage/Blocks/Landing/images/mountains.webp +0 -0
  96. package/src/components/manage/Blocks/Landing/images/natura2000.webp +0 -0
  97. package/src/components/manage/Blocks/Landing/images/natura2000_square.webp +0 -0
  98. package/src/components/manage/Blocks/Landing/images/peatlands.webp +0 -0
  99. package/src/components/manage/Blocks/Landing/images/people_and_nature.webp +0 -0
  100. package/src/components/manage/Blocks/Landing/images/rivers.webp +0 -0
  101. package/src/components/manage/Blocks/Landing/index.js +104 -0
  102. package/src/components/manage/Blocks/Landing/schema.js +62 -0
  103. package/src/components/manage/Blocks/Landing/style.less +174 -0
  104. package/src/components/manage/Blocks/List/View.jsx +37 -0
  105. package/src/components/manage/Blocks/List/index.js +17 -0
  106. package/src/components/manage/Blocks/List/schema.js +49 -0
  107. package/src/components/manage/Blocks/List/style.less +12 -0
  108. package/src/components/manage/Blocks/NavigationAnchors/Edit.jsx +33 -0
  109. package/src/components/manage/Blocks/NavigationAnchors/View.jsx +132 -0
  110. package/src/components/manage/Blocks/NavigationAnchors/assets/external.png +0 -0
  111. package/src/components/manage/Blocks/NavigationAnchors/index.js +23 -0
  112. package/src/components/manage/Blocks/NavigationAnchors/schema.js +76 -0
  113. package/src/components/manage/Blocks/NavigationAnchors/styles.less +104 -0
  114. package/src/components/manage/Blocks/SimpleDataTable/index.js +16 -0
  115. package/src/components/manage/Blocks/SimpleDataTable/templates/colored/View.jsx +178 -0
  116. package/src/components/manage/Blocks/SimpleDataTable/templates/colored/index.js +4 -0
  117. package/src/components/manage/Blocks/SimpleDataTable/templates/colored/schema.js +56 -0
  118. package/src/components/manage/Blocks/SimpleDataTable/templates/colored/style.less +54 -0
  119. package/src/components/manage/Blocks/SiteBanner/View.jsx +148 -0
  120. package/src/components/manage/Blocks/SiteBanner/index.js +17 -0
  121. package/src/components/manage/Blocks/SiteBanner/schema.js +19 -0
  122. package/src/components/manage/Blocks/SiteBanner/style.less +106 -0
  123. package/src/components/manage/Blocks/SiteHabitatsList/View.jsx +89 -0
  124. package/src/components/manage/Blocks/SiteHabitatsList/index.js +17 -0
  125. package/src/components/manage/Blocks/SiteHabitatsList/schema.js +19 -0
  126. package/src/components/manage/Blocks/SiteHabitatsList/style.less +70 -0
  127. package/src/components/manage/Blocks/SiteProtectedHabitats/View.jsx +47 -0
  128. package/src/components/manage/Blocks/SiteProtectedHabitats/images/background.webp +0 -0
  129. package/src/components/manage/Blocks/SiteProtectedHabitats/index.js +17 -0
  130. package/src/components/manage/Blocks/SiteProtectedHabitats/schema.js +19 -0
  131. package/src/components/manage/Blocks/SiteProtectedHabitats/style.less +90 -0
  132. package/src/components/manage/Blocks/SiteProtectedSpecies/View.jsx +55 -0
  133. package/src/components/manage/Blocks/SiteProtectedSpecies/images/background.webp +0 -0
  134. package/src/components/manage/Blocks/SiteProtectedSpecies/index.js +17 -0
  135. package/src/components/manage/Blocks/SiteProtectedSpecies/schema.js +19 -0
  136. package/src/components/manage/Blocks/SiteProtectedSpecies/style.less +90 -0
  137. package/src/components/manage/Blocks/SiteShape/View.jsx +107 -0
  138. package/src/components/manage/Blocks/SiteShape/index.js +23 -0
  139. package/src/components/manage/Blocks/SiteShape/schema.js +19 -0
  140. package/src/components/manage/Blocks/SiteShape/style.less +15 -0
  141. package/src/components/manage/Blocks/SiteSpeciesList/Filters/SortBy.jsx +52 -0
  142. package/src/components/manage/Blocks/SiteSpeciesList/Filters/SpeciesGroups.jsx +43 -0
  143. package/src/components/manage/Blocks/SiteSpeciesList/Filters/View.jsx +200 -0
  144. package/src/components/manage/Blocks/SiteSpeciesList/Filters/index.js +4 -0
  145. package/src/components/manage/Blocks/SiteSpeciesList/View.jsx +253 -0
  146. package/src/components/manage/Blocks/SiteSpeciesList/index.js +17 -0
  147. package/src/components/manage/Blocks/SiteSpeciesList/schema.js +19 -0
  148. package/src/components/manage/Blocks/SiteSpeciesList/style.less +264 -0
  149. package/src/components/manage/Blocks/SiteSpeciesList/utils.js +33 -0
  150. package/src/components/manage/Blocks/SlateLink/render.jsx +77 -0
  151. package/src/components/manage/Blocks/SlateLink/styles.less +22 -0
  152. package/src/components/manage/Blocks/SlateSVG/constants.js +1 -0
  153. package/src/components/manage/Blocks/SlateSVG/extensions.js +11 -0
  154. package/src/components/manage/Blocks/SlateSVG/index.js +47 -0
  155. package/src/components/manage/Blocks/SlateSVG/render.jsx +42 -0
  156. package/src/components/manage/Blocks/SlateSVG/schema.js +12 -0
  157. package/src/components/manage/Blocks/SlateSVG/styles.less +6 -0
  158. package/src/components/manage/Blocks/SpeciesBanner/View.jsx +109 -0
  159. package/src/components/manage/Blocks/SpeciesBanner/index.js +17 -0
  160. package/src/components/manage/Blocks/SpeciesBanner/schema.js +19 -0
  161. package/src/components/manage/Blocks/SpeciesBanner/style.less +115 -0
  162. package/src/components/manage/Blocks/SpeciesClassification/View.jsx +19 -0
  163. package/src/components/manage/Blocks/SpeciesClassification/index.js +17 -0
  164. package/src/components/manage/Blocks/SpeciesClassification/schema.js +19 -0
  165. package/src/components/manage/Blocks/SpeciesClassification/style.less +3 -0
  166. package/src/components/manage/Blocks/SpeciesDistribution/View.jsx +97 -0
  167. package/src/components/manage/Blocks/SpeciesDistribution/index.js +23 -0
  168. package/src/components/manage/Blocks/SpeciesDistribution/schema.js +19 -0
  169. package/src/components/manage/Blocks/SpeciesDistribution/style.less +5 -0
  170. package/src/components/manage/Blocks/SpeciesProtectedSites/View.jsx +97 -0
  171. package/src/components/manage/Blocks/SpeciesProtectedSites/index.js +23 -0
  172. package/src/components/manage/Blocks/SpeciesProtectedSites/schema.js +19 -0
  173. package/src/components/manage/Blocks/SpeciesProtectedSites/style.less +5 -0
  174. package/src/components/manage/Blocks/StackedBarChart/Chart.jsx +127 -0
  175. package/src/components/manage/Blocks/StackedBarChart/ChartContext.jsx +3 -0
  176. package/src/components/manage/Blocks/StackedBarChart/StackedBars.jsx +116 -0
  177. package/src/components/manage/Blocks/StackedBarChart/View.jsx +64 -0
  178. package/src/components/manage/Blocks/StackedBarChart/index.js +17 -0
  179. package/src/components/manage/Blocks/StackedBarChart/schema.js +25 -0
  180. package/src/components/manage/Blocks/StackedBarChart/style.less +37 -0
  181. package/src/components/manage/Blocks/TilesImages/Edit.jsx +32 -0
  182. package/src/components/manage/Blocks/TilesImages/View.jsx +37 -0
  183. package/src/components/manage/Blocks/TilesImages/index.js +23 -0
  184. package/src/components/manage/Blocks/TilesImages/schema.js +72 -0
  185. package/src/components/manage/Blocks/TilesImages/styles.less +57 -0
  186. package/src/components/theme/AppExtras/CopyPaste/CopyPaste.jsx +176 -0
  187. package/src/components/theme/AppExtras/CopyPaste/index.js +3 -0
  188. package/src/components/theme/AppExtras/CopyPaste/style.less +18 -0
  189. package/src/components/theme/AppExtras/MultilingualRedirector/MultilingualRedirector.jsx +35 -0
  190. package/src/components/theme/AppExtras/index.js +13 -0
  191. package/src/components/theme/Footer/Footer.jsx +209 -0
  192. package/src/components/theme/Header/Header.jsx +81 -0
  193. package/src/components/theme/LanguageSelector/LanguageSelector.jsx +79 -0
  194. package/src/components/theme/LanguageSelector/styles.less +44 -0
  195. package/src/components/theme/Navigation/Navigation.jsx +453 -0
  196. package/src/components/theme/Sitemap/Sitemap.jsx +152 -0
  197. package/src/fonts/OpenSans-Bold.ttf +0 -0
  198. package/src/fonts/OpenSans-Regular.ttf +0 -0
  199. package/src/fonts/OpenSans-Semibold.ttf +0 -0
  200. package/src/fonts/Rajdhani-Bold.ttf +0 -0
  201. package/src/fonts/Rajdhani-Regular.ttf +0 -0
  202. package/src/grid.js +78 -0
  203. package/src/helpers.js +148 -0
  204. package/src/hocs/index.js +6 -0
  205. package/src/hocs/useResizeObserver.jsx +26 -0
  206. package/src/hocs/withLocalStorage.jsx +37 -0
  207. package/src/hocs/withScreenSize.jsx +43 -0
  208. package/src/icons/home.svg +12 -0
  209. package/src/icons/info.svg +5 -0
  210. package/src/icons/n2k-logo-transparent.png +0 -0
  211. package/src/icons/n2k-logo.png +0 -0
  212. package/src/icons/natura2000.svg +142 -0
  213. package/src/icons/placeholders/Algae.png +0 -0
  214. package/src/icons/placeholders/Amphibians.png +0 -0
  215. package/src/icons/placeholders/Birds.png +0 -0
  216. package/src/icons/placeholders/Conifers.png +0 -0
  217. package/src/icons/placeholders/Fishes.png +0 -0
  218. package/src/icons/placeholders/Fungi.png +0 -0
  219. package/src/icons/placeholders/Mammals.png +0 -0
  220. package/src/icons/placeholders/Plants.png +0 -0
  221. package/src/icons/placeholders/Reptiles.png +0 -0
  222. package/src/icons/placeholders/default.png +0 -0
  223. package/src/index.js +163 -0
  224. package/src/less/globals.less +3 -0
  225. package/src/less/styles.less +691 -0
  226. package/src/less/variables.less +2 -0
  227. package/src/static/cca.svg +61 -0
  228. package/src/static/ec.png +0 -0
  229. package/src/static/eea.png +0 -0
  230. package/src/static/eu.jpg +0 -0
  231. package/src/static/forest.svg +100 -0
  232. package/src/static/wise.png +0 -0
  233. package/src/store.js +24 -0
@@ -0,0 +1,23 @@
1
+ import SpeciesProtectedSitesView from './View';
2
+ import getSchema from './schema';
3
+
4
+ export function getSpeciesProtectedSitesURL(code_2000) {
5
+ return encodeURI(
6
+ `https://bio.discomap.eea.europa.eu/arcgis/rest/services/ProtectedSites/EUNIS_Website_Dyna_WM/MapServer/5/query?f=json&where=SPECIESCODE LIKE '%${code_2000.toUpperCase()}%'&returnGeometry=true&spatialRel=esriSpatialRelIntersects&outFields=SPECIESCODE,SITECODE,HABITATCODE,OBJECTID&outSR=102100`,
7
+ );
8
+ }
9
+
10
+ export default (config) => {
11
+ config.blocks.blocksConfig.custom_connected_block = {
12
+ ...config.blocks.blocksConfig.custom_connected_block,
13
+ blocks: {
14
+ ...config.blocks.blocksConfig.custom_connected_block.blocks,
15
+ species_protected_sites: {
16
+ view: SpeciesProtectedSitesView,
17
+ getSchema: getSchema,
18
+ title: 'Species protected sites map',
19
+ },
20
+ },
21
+ };
22
+ return config;
23
+ };
@@ -0,0 +1,19 @@
1
+ const getSchema = (props) => {
2
+ return {
3
+ title: 'Species protected sites map',
4
+
5
+ fieldsets: [
6
+ {
7
+ id: 'default',
8
+ title: 'Default',
9
+ fields: [],
10
+ },
11
+ ],
12
+
13
+ properties: {},
14
+
15
+ required: [],
16
+ };
17
+ };
18
+
19
+ export default getSchema;
@@ -0,0 +1,5 @@
1
+ .species-protected-sites {
2
+ display: flex;
3
+ justify-content: center;
4
+ margin-bottom: 0;
5
+ }
@@ -0,0 +1,127 @@
1
+ import React, { useState, useEffect, useRef } from 'react';
2
+ import {
3
+ axisBottom,
4
+ axisLeft,
5
+ format,
6
+ select,
7
+ scaleBand,
8
+ scaleLinear,
9
+ } from 'd3';
10
+ import cx from 'classnames';
11
+ import ChartContext from './ChartContext';
12
+
13
+ /**
14
+ * example:
15
+ * <Chart width="100%" height="400px">
16
+ * <Bars />
17
+ * <Legend />
18
+ * </Chart>
19
+ */
20
+
21
+ function Chart(props) {
22
+ const [scales, setScales] = useState();
23
+ const [popup, setPopup] = useState();
24
+ const chartWrapper = useRef();
25
+ const svgRef = useRef();
26
+ const popupRef = useRef();
27
+ const {
28
+ margin = { top: 20, right: 30, bottom: 70, left: 40 },
29
+ xDomain = [],
30
+ yDomain = [],
31
+ } = props;
32
+
33
+ useEffect(() => {
34
+ // dispose();
35
+ if (xDomain.length && yDomain.length) {
36
+ makeAxis();
37
+ }
38
+ /* eslint-disable-next-line */
39
+ }, [JSON.stringify(xDomain), JSON.stringify(yDomain)]);
40
+
41
+ // const dispose = () => {
42
+ // const svg = select(svgRef.current);
43
+ // svg.selectAll('*').remove();
44
+ // };
45
+
46
+ const makeAxis = () => {
47
+ const svg = select(svgRef.current);
48
+ // Scales
49
+ const xScale = scaleBand()
50
+ .domain([...xDomain])
51
+ .range([margin.left, props.width - margin.right])
52
+ .padding(0.25);
53
+ const yScale = scaleLinear()
54
+ .domain(yDomain)
55
+ .rangeRound([props.height - margin.bottom, margin.top]);
56
+
57
+ // Axes
58
+ svg
59
+ .select('.x-axis')
60
+ .attr('transform', `translate(0, ${props.height - margin.bottom})`)
61
+ .call(axisBottom(xScale).tickPadding(6).tickSize(0))
62
+ .call((g) => g.selectAll('.domain').remove());
63
+ svg
64
+ .select('.y-axis')
65
+ .attr('transform', `translate(${margin.left}, 0)`)
66
+ .call(
67
+ axisLeft(yScale).tickSize(0).tickPadding(3).tickFormat(format('.0%')),
68
+ )
69
+ .call((g) => g.selectAll('.domain').remove())
70
+ .call((g) =>
71
+ g
72
+ .selectAll('.tick line')
73
+ .attr('x2', props.width - margin.left - margin.right)
74
+ .attr('stroke-opacity', 0.1),
75
+ );
76
+ setScales({
77
+ xScale,
78
+ yScale,
79
+ });
80
+ };
81
+
82
+ return (
83
+ <ChartContext.Provider
84
+ value={{
85
+ element: svgRef.current,
86
+ popupElement: popupRef.current,
87
+ height: props.height,
88
+ width: props.width,
89
+ margin,
90
+ scales,
91
+ popup,
92
+ setPopup,
93
+ }}
94
+ >
95
+ <div ref={chartWrapper} className="chart-wrapper">
96
+ <svg
97
+ viewBox={`0 0 ${props.width} ${props.height}`}
98
+ preserveAspectRatio="xMinYMin meet"
99
+ ref={svgRef}
100
+ >
101
+ <g className="x-axis" />
102
+ <g className="y-axis" />
103
+ {props.children}
104
+ </svg>
105
+ <div
106
+ style={
107
+ popup
108
+ ? {
109
+ top: popup.clientY - 20,
110
+ left: popup.clientX,
111
+ }
112
+ : {}
113
+ }
114
+ className={cx(
115
+ 'chart-popup ui top center popup',
116
+ popup?.content ? 'visible' : {},
117
+ )}
118
+ ref={popupRef}
119
+ >
120
+ <div className="content">{popup ? popup.content : ''}</div>
121
+ </div>
122
+ </div>
123
+ </ChartContext.Provider>
124
+ );
125
+ }
126
+
127
+ export default Chart;
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ const ChartContext = new React.createContext();
3
+ export default ChartContext;
@@ -0,0 +1,116 @@
1
+ import React from 'react';
2
+ import { scaleOrdinal, schemeSpectral, stack } from 'd3';
3
+ import cx from 'classnames';
4
+ import { adjustBrightness } from '@eeacms/volto-n2k/helpers';
5
+ import ChartContext from './ChartContext';
6
+
7
+ const getSerieData = (serie) => {
8
+ return Object.keys(serie)
9
+ .filter((key) => !['index', 'key'].includes(key))
10
+ .map((key) => serie[key]);
11
+ };
12
+
13
+ function StackedBars(props) {
14
+ const {
15
+ element,
16
+ height,
17
+ width,
18
+ margin,
19
+ scales,
20
+ popup,
21
+ setPopup,
22
+ } = React.useContext(ChartContext);
23
+ const { data = {}, keys = [], hoverText = '{}' } = props;
24
+
25
+ if (!keys?.length || !scales?.xScale || !scales?.yScale) {
26
+ return <></>;
27
+ }
28
+
29
+ const series = stack()
30
+ .keys(keys)(data)
31
+ .map((d) => {
32
+ d.forEach((v) => (v.key = d.key));
33
+ return d;
34
+ });
35
+ const color = scaleOrdinal()
36
+ .domain(series.map((d) => d.key))
37
+ .range(
38
+ ['#70AD47', '#ED7D31', '#FF3F3F', '#AFABAB'] ||
39
+ schemeSpectral[series.length],
40
+ )
41
+ .unknown('#ccc');
42
+
43
+ return (
44
+ <React.Fragment>
45
+ {series?.map((serie, serieIndex) => {
46
+ return (
47
+ <g key={serie.key} className={cx('serie', serie.key)}>
48
+ {getSerieData(serie).map((rect, rectIndex) => {
49
+ return (
50
+ <rect
51
+ key={`${serie.key}_${serieIndex}_${rectIndex}`}
52
+ className={cx(rect.key)}
53
+ fill={
54
+ popup?.id === `${serieIndex}_${rectIndex}_${rect.key}`
55
+ ? adjustBrightness(color(serie.key), -20)
56
+ : color(serie.key)
57
+ }
58
+ x={scales.xScale(rect.data.x)}
59
+ y={scales.yScale(rect[1])}
60
+ height={scales.yScale(rect[0]) - scales.yScale(rect[1]) || 0}
61
+ width={scales.xScale.bandwidth()}
62
+ onFocus={() => {}}
63
+ onBlur={() => {}}
64
+ onMouseMoveCapture={(event) => {
65
+ const elementPosition = element.parentNode.getBoundingClientRect();
66
+ setPopup({
67
+ id: `${serieIndex}_${rectIndex}_${rect.key}`,
68
+ clientX: event.clientX - elementPosition.x,
69
+ clientY: event.clientY - elementPosition.y,
70
+ content: (
71
+ <>
72
+ <p>
73
+ {hoverText.replace(
74
+ '{}',
75
+ rect.data[rect.key] * rect.data.total,
76
+ )}
77
+ </p>
78
+ </>
79
+ ),
80
+ });
81
+ }}
82
+ onMouseOut={() => {
83
+ setPopup(null);
84
+ }}
85
+ />
86
+ );
87
+ })}
88
+ </g>
89
+ );
90
+ })}
91
+ <foreignObject
92
+ width={width - margin.left - margin.right}
93
+ height="12px"
94
+ position="relative"
95
+ x={margin.left}
96
+ y={height - 40}
97
+ >
98
+ <div className="legend-wrapper" xmlns="http://www.w3.org/1999/xhtml">
99
+ {series?.map((serie, serieIndex) => (
100
+ <div
101
+ key={`legend_${serie.key}`}
102
+ className={cx('legend', serie.key)}
103
+ >
104
+ <span
105
+ className={'square'}
106
+ style={{ background: color(serie.key) }}
107
+ />
108
+ <p>{serie.key}</p>
109
+ </div>
110
+ ))}
111
+ </div>
112
+ </foreignObject>
113
+ </React.Fragment>
114
+ );
115
+ }
116
+ export default StackedBars;
@@ -0,0 +1,64 @@
1
+ import React from 'react';
2
+ import Chart from './Chart';
3
+ import StackedBars from './StackedBars';
4
+
5
+ import './style.less';
6
+
7
+ const View = (props) => {
8
+ const [xValues, setXValues] = React.useState([]);
9
+ const [yValues, setYValues] = React.useState({});
10
+ const [yLabels, setYLabels] = React.useState([]);
11
+ const {
12
+ x_label_key = 'country_code',
13
+ y_label_key = 'assessment',
14
+ y_value_key = 'quantity',
15
+ } = props;
16
+ const data = props.provider_data || {};
17
+
18
+ React.useEffect(() => {
19
+ if (!(data[x_label_key]?.length && data[y_label_key]?.length)) return;
20
+ const yValues = {};
21
+ const total = {};
22
+
23
+ data[x_label_key].forEach((x, index) => {
24
+ if (!total[x]) total[x] = 0;
25
+ total[x] += data[y_value_key][index];
26
+ });
27
+
28
+ data[x_label_key].forEach((x, index) => {
29
+ const y = data[y_label_key][index];
30
+ if (!yValues[x]) {
31
+ yValues[x] = {
32
+ x,
33
+ total: total[x],
34
+ };
35
+ }
36
+ yValues[x][y] = data[y_value_key][index] / total[x];
37
+ });
38
+
39
+ setXValues([...new Set(data[x_label_key])]);
40
+ setYValues(yValues);
41
+ setYLabels([...new Set(data[y_label_key])]);
42
+ /* eslint-disable-next-line */
43
+ }, [x_label_key, y_label_key, y_value_key, data]);
44
+
45
+ return (
46
+ <React.Fragment>
47
+ <div className="stacked-bar-chart">
48
+ <Chart
49
+ width={800}
50
+ height={400}
51
+ xDomain={xValues.sort()}
52
+ yDomain={[0, 1]}
53
+ >
54
+ <StackedBars
55
+ data={Object.keys(yValues).map((label) => yValues[label])}
56
+ hoverText={props.data.hoverText}
57
+ keys={yLabels}
58
+ />
59
+ </Chart>
60
+ </div>
61
+ </React.Fragment>
62
+ );
63
+ };
64
+ export default View;
@@ -0,0 +1,17 @@
1
+ import StackedBarChart from './View';
2
+ import getSchema from './schema';
3
+
4
+ export default (config) => {
5
+ config.blocks.blocksConfig.custom_connected_block = {
6
+ ...config.blocks.blocksConfig.custom_connected_block,
7
+ blocks: {
8
+ ...config.blocks.blocksConfig.custom_connected_block.blocks,
9
+ stacked_bar_chart: {
10
+ view: StackedBarChart,
11
+ getSchema: getSchema,
12
+ title: 'Stacked bar chart',
13
+ },
14
+ },
15
+ };
16
+ return config;
17
+ };
@@ -0,0 +1,25 @@
1
+ const getSchema = (props) => {
2
+ return {
3
+ title: 'Stacked bars chart',
4
+
5
+ fieldsets: [
6
+ {
7
+ id: 'default',
8
+ title: 'Default',
9
+ fields: ['hoverText'],
10
+ },
11
+ ],
12
+
13
+ properties: {
14
+ hoverText: {
15
+ title: 'Hover text',
16
+ description: "Add '{}' for bar quantity value, ex: '{} Forests'",
17
+ widget: 'textarea',
18
+ },
19
+ },
20
+
21
+ required: [],
22
+ };
23
+ };
24
+
25
+ export default getSchema;
@@ -0,0 +1,37 @@
1
+ .chart-wrapper {
2
+ position: relative;
3
+ display: flex;
4
+ padding: 0;
5
+ margin: 0;
6
+
7
+ .chart-popup {
8
+ position: absolute;
9
+ width: fit-content;
10
+ transform: translate(-50%, calc(-50% - 1rem)) !important;
11
+ }
12
+
13
+ svg {
14
+ // width: 100%;
15
+
16
+ .legend-wrapper {
17
+ display: flex;
18
+ justify-content: center;
19
+
20
+ .legend {
21
+ display: flex;
22
+
23
+ p {
24
+ margin-right: 1rem;
25
+ font-size: 12px;
26
+ line-height: 12px;
27
+ }
28
+
29
+ .square {
30
+ width: 12px;
31
+ height: 12px;
32
+ margin-right: 0.5rem;
33
+ }
34
+ }
35
+ }
36
+ }
37
+ }
@@ -0,0 +1,32 @@
1
+ import React from 'react';
2
+ import { SidebarPortal } from '@plone/volto/components';
3
+ import InlineForm from '@plone/volto/components/manage/Form/InlineForm';
4
+ import TilesImagesView from './View';
5
+ import getSchema from './schema';
6
+ import './styles.less';
7
+
8
+ const Edit = (props) => {
9
+ const { selected = false } = props;
10
+ const schema = getSchema();
11
+
12
+ return (
13
+ <>
14
+ <TilesImagesView {...props} mode="edit" />
15
+ <SidebarPortal selected={selected}>
16
+ <InlineForm
17
+ schema={schema}
18
+ title={schema.title}
19
+ onChangeField={(id, value) => {
20
+ props.onChangeBlock(props.block, {
21
+ ...props.data,
22
+ [id]: value,
23
+ });
24
+ }}
25
+ formData={props.data}
26
+ />
27
+ </SidebarPortal>
28
+ </>
29
+ );
30
+ };
31
+
32
+ export default Edit;
@@ -0,0 +1,37 @@
1
+ import React from 'react';
2
+ import { UniversalLink } from '@plone/volto/components';
3
+ import cx from 'classnames';
4
+ import './styles.less';
5
+
6
+ const View = (props) => {
7
+ const { data = {}, mode = 'view' } = props;
8
+ const images = data.images || [];
9
+
10
+ return (
11
+ <div className={cx('tiles-images', mode, data.theme || 'light')}>
12
+ {mode === 'edit' && !images.length ? <p>Tiles images block</p> : ''}
13
+ {images.map((image) => (
14
+ <p
15
+ className={cx('p-image', {
16
+ 'with-border': data.hasBorder ?? true,
17
+ 'rounded-border': data.rounded ?? true,
18
+ })}
19
+ >
20
+ <UniversalLink href={image.link || '#'} title={image.title}>
21
+ <img
22
+ src={`${image.image}/@@images/image/mini`}
23
+ alt={image.title}
24
+ style={
25
+ data.size
26
+ ? { width: `${data.size}px`, height: `${data.size}px` }
27
+ : {}
28
+ }
29
+ />
30
+ </UniversalLink>
31
+ </p>
32
+ ))}
33
+ </div>
34
+ );
35
+ };
36
+
37
+ export default View;
@@ -0,0 +1,23 @@
1
+ import TilesImagesEdit from './Edit';
2
+ import TilesImagesView from './View';
3
+ import worldSVG from '@plone/volto/icons/world.svg';
4
+
5
+ export default (config) => {
6
+ config.blocks.blocksConfig.tiles_images = {
7
+ id: 'tiles_images',
8
+ title: 'Tiles images',
9
+ icon: worldSVG,
10
+ group: 'natura_2000',
11
+ edit: TilesImagesEdit,
12
+ view: TilesImagesView,
13
+ restricted: false,
14
+ mostUsed: false,
15
+ sidebarTab: 1,
16
+ blocks: {},
17
+ security: {
18
+ addPermission: [],
19
+ view: [],
20
+ },
21
+ };
22
+ return config;
23
+ };
@@ -0,0 +1,72 @@
1
+ const imageSchema = {
2
+ title: 'Image',
3
+ fieldsets: [
4
+ {
5
+ id: 'default',
6
+ title: 'Default',
7
+ fields: ['image', 'link', 'title'],
8
+ },
9
+ ],
10
+ properties: {
11
+ image: {
12
+ title: 'image',
13
+ widget: 'object_by_path',
14
+ },
15
+ link: {
16
+ title: 'link',
17
+ widget: 'object_by_path',
18
+ },
19
+ title: {
20
+ title: 'Title',
21
+ },
22
+ },
23
+ required: ['url', 'title'],
24
+ };
25
+
26
+ export default () => ({
27
+ title: 'Tiles images',
28
+ fieldsets: [
29
+ {
30
+ id: 'default',
31
+ title: 'Default',
32
+ fields: ['theme', 'images'],
33
+ },
34
+ {
35
+ id: 'advanced',
36
+ title: 'Advanced',
37
+ fields: ['size', 'hasBorder', 'rounded'],
38
+ },
39
+ ],
40
+ properties: {
41
+ size: {
42
+ title: 'Tiles size',
43
+ type: 'number',
44
+ },
45
+ hasBorder: {
46
+ title: 'With border',
47
+ type: 'boolean',
48
+ default: true,
49
+ },
50
+ rounded: {
51
+ title: 'Rounded',
52
+ type: 'boolean',
53
+ default: true,
54
+ },
55
+ theme: {
56
+ title: 'Theme',
57
+ type: 'array',
58
+ choices: [
59
+ ['light', 'Light'],
60
+ ['grey', 'Grey'],
61
+ ['dark', 'Dark'],
62
+ ],
63
+ default: 'light',
64
+ },
65
+ images: {
66
+ title: 'Images',
67
+ widget: 'object_list_inline',
68
+ schema: imageSchema,
69
+ },
70
+ },
71
+ required: [],
72
+ });
@@ -0,0 +1,57 @@
1
+ .tiles-images {
2
+ display: flex;
3
+ flex-flow: row;
4
+ margin-bottom: 1rem;
5
+
6
+ &:not(.edit) {
7
+ margin-left: -0.5rem;
8
+ }
9
+
10
+ &.light {
11
+ .p-image.with-border img {
12
+ border: 1px solid #fff;
13
+ }
14
+ }
15
+
16
+ &.grey {
17
+ .p-image.with-border img {
18
+ border: 1px solid #c9c9c9;
19
+ }
20
+ }
21
+
22
+ &.dark {
23
+ .p-image.with-border img {
24
+ border: 1px solid #000;
25
+ }
26
+ }
27
+
28
+ .p-image {
29
+ margin-bottom: 0 !important;
30
+
31
+ a {
32
+ display: block;
33
+ }
34
+
35
+ img {
36
+ width: 130px;
37
+ height: 130px;
38
+ padding: 6px;
39
+
40
+ &:hover {
41
+ opacity: 0.9;
42
+ }
43
+ }
44
+ }
45
+
46
+ .p-image.rounded-border {
47
+ border-radius: 50%;
48
+
49
+ img {
50
+ border-radius: 50%;
51
+ }
52
+ }
53
+
54
+ .p-image.with-border {
55
+ margin: 0 0.5rem;
56
+ }
57
+ }