eea.plotly 1.5__tar.gz → 1.7__tar.gz

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 (138) hide show
  1. {eea_plotly-1.5/eea.plotly.egg-info → eea_plotly-1.7}/PKG-INFO +13 -2
  2. {eea_plotly-1.5 → eea_plotly-1.7}/docs/HISTORY.txt +11 -0
  3. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/browser/preview.py +4 -1
  4. eea_plotly-1.7/eea/plotly/browser/preview_adapter/soer_miniature.py +159 -0
  5. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/deserializer/dxcontent.py +4 -1
  6. eea_plotly-1.7/eea/plotly/io_json.py +12 -0
  7. eea_plotly-1.7/eea/plotly/version.txt +1 -0
  8. {eea_plotly-1.5 → eea_plotly-1.7/eea.plotly.egg-info}/PKG-INFO +13 -2
  9. {eea_plotly-1.5 → eea_plotly-1.7}/eea.plotly.egg-info/SOURCES.txt +1 -0
  10. {eea_plotly-1.5 → eea_plotly-1.7}/eea.plotly.egg-info/requires.txt +1 -1
  11. {eea_plotly-1.5 → eea_plotly-1.7}/setup.py +1 -1
  12. eea_plotly-1.5/eea/plotly/browser/preview_adapter/soer_miniature.py +0 -80
  13. eea_plotly-1.5/eea/plotly/version.txt +0 -1
  14. {eea_plotly-1.5 → eea_plotly-1.7}/CONTRIBUTING.md +0 -0
  15. {eea_plotly-1.5 → eea_plotly-1.7}/MANIFEST.in +0 -0
  16. {eea_plotly-1.5 → eea_plotly-1.7}/README.rst +0 -0
  17. {eea_plotly-1.5 → eea_plotly-1.7}/docs/LICENSE.GPL +0 -0
  18. {eea_plotly-1.5 → eea_plotly-1.7}/docs/LICENSE.txt +0 -0
  19. {eea_plotly-1.5 → eea_plotly-1.7}/eea/__init__.py +0 -0
  20. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/README.txt +0 -0
  21. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/__init__.py +0 -0
  22. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/behaviors.py +0 -0
  23. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/browser/__init__.py +0 -0
  24. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/browser/configure.zcml +0 -0
  25. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/browser/controlpanel.py +0 -0
  26. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/browser/preview_adapter/adapter.py +0 -0
  27. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/browser/pt/visualization_view.pt +0 -0
  28. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/configure.zcml +0 -0
  29. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/controlpanel.py +0 -0
  30. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/deserializer/blocks.py +0 -0
  31. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/deserializer/configure.zcml +0 -0
  32. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/deserializer/dxfields.py +0 -0
  33. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/interfaces.py +0 -0
  34. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/io_csv.py +0 -0
  35. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/__init__.py +0 -0
  36. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/bg/LC_MESSAGES/eea.po +0 -0
  37. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/bg/LC_MESSAGES/plone.po +0 -0
  38. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/cs/LC_MESSAGES/eea.po +0 -0
  39. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/cs/LC_MESSAGES/plone.po +0 -0
  40. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/da/LC_MESSAGES/eea.po +0 -0
  41. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/da/LC_MESSAGES/plone.po +0 -0
  42. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/de/LC_MESSAGES/eea.po +0 -0
  43. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/de/LC_MESSAGES/plone.po +0 -0
  44. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/eea.pot +0 -0
  45. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/el/LC_MESSAGES/eea.po +0 -0
  46. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/el/LC_MESSAGES/plone.po +0 -0
  47. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/en/LC_MESSAGES/eea.po +0 -0
  48. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/en/LC_MESSAGES/plone.po +0 -0
  49. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/es/LC_MESSAGES/eea.po +0 -0
  50. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/es/LC_MESSAGES/plone.po +0 -0
  51. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/et/LC_MESSAGES/eea.po +0 -0
  52. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/et/LC_MESSAGES/plone.po +0 -0
  53. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/eu/LC_MESSAGES/eea.po +0 -0
  54. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/eu/LC_MESSAGES/plone.po +0 -0
  55. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/fi/LC_MESSAGES/eea.po +0 -0
  56. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/fi/LC_MESSAGES/plone.po +0 -0
  57. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/fr/LC_MESSAGES/eea.po +0 -0
  58. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/fr/LC_MESSAGES/plone.po +0 -0
  59. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/hr/LC_MESSAGES/eea.po +0 -0
  60. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/hr/LC_MESSAGES/plone.po +0 -0
  61. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/hu/LC_MESSAGES/eea.po +0 -0
  62. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/hu/LC_MESSAGES/plone.po +0 -0
  63. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/is/LC_MESSAGES/eea.po +0 -0
  64. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/is/LC_MESSAGES/plone.po +0 -0
  65. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/it/LC_MESSAGES/eea.po +0 -0
  66. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/it/LC_MESSAGES/plone.po +0 -0
  67. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/kl/LC_MESSAGES/eea.po +0 -0
  68. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/kl/LC_MESSAGES/plone.po +0 -0
  69. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/lt/LC_MESSAGES/eea.po +0 -0
  70. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/lt/LC_MESSAGES/plone.po +0 -0
  71. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/lv/LC_MESSAGES/eea.po +0 -0
  72. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/lv/LC_MESSAGES/plone.po +0 -0
  73. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/mt/LC_MESSAGES/eea.po +0 -0
  74. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/mt/LC_MESSAGES/plone.po +0 -0
  75. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/nl/LC_MESSAGES/eea.po +0 -0
  76. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/nl/LC_MESSAGES/plone.po +0 -0
  77. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/no/LC_MESSAGES/eea.po +0 -0
  78. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/no/LC_MESSAGES/plone.po +0 -0
  79. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/pl/LC_MESSAGES/eea.po +0 -0
  80. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/pl/LC_MESSAGES/plone.po +0 -0
  81. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/plone-manual.pot +0 -0
  82. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/pt/LC_MESSAGES/eea.po +0 -0
  83. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/pt/LC_MESSAGES/plone.po +0 -0
  84. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/pt_BR/LC_MESSAGES/eea.po +0 -0
  85. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/pt_BR/LC_MESSAGES/plone.po +0 -0
  86. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/ro/LC_MESSAGES/eea.po +0 -0
  87. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/ro/LC_MESSAGES/plone.po +0 -0
  88. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/ru/LC_MESSAGES/eea.po +0 -0
  89. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/ru/LC_MESSAGES/plone.po +0 -0
  90. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/sk/LC_MESSAGES/eea.po +0 -0
  91. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/sk/LC_MESSAGES/plone.po +0 -0
  92. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/sl/LC_MESSAGES/eea.po +0 -0
  93. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/sl/LC_MESSAGES/plone.po +0 -0
  94. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/sv/LC_MESSAGES/eea.po +0 -0
  95. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/sv/LC_MESSAGES/plone.po +0 -0
  96. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/tr/LC_MESSAGES/eea.po +0 -0
  97. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/tr/LC_MESSAGES/plone.po +0 -0
  98. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/update.sh +0 -0
  99. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/zh_TW/LC_MESSAGES/eea.po +0 -0
  100. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/locales/zh_TW/LC_MESSAGES/plone.po +0 -0
  101. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/permissions.zcml +0 -0
  102. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/profiles/default/browserlayer.xml +0 -0
  103. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/profiles/default/controlpanel.json +0 -0
  104. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/profiles/default/controlpanel.xml +0 -0
  105. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/profiles/default/metadata.xml +0 -0
  106. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/profiles/default/registry.xml +0 -0
  107. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/profiles/default/rolemap.xml +0 -0
  108. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/profiles/default/types/visualization.xml +0 -0
  109. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/profiles/default/types.xml +0 -0
  110. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/profiles/uninstall/browserlayer.xml +0 -0
  111. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/profiles/uninstall/controlpanel.xml +0 -0
  112. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/profiles/uninstall/registry.xml +0 -0
  113. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/profiles.zcml +0 -0
  114. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/restapi/__init__.py +0 -0
  115. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/restapi/configure.zcml +0 -0
  116. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/restapi/controlpanel/__init__.py +0 -0
  117. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/restapi/controlpanel/configure.zcml +0 -0
  118. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/restapi/controlpanel/get.py +0 -0
  119. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/restapi/controlpanel/reset.py +0 -0
  120. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/restapi/visualization/configure.zcml +0 -0
  121. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/restapi/visualization/get.py +0 -0
  122. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/serializer/blocks.py +0 -0
  123. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/serializer/configure.zcml +0 -0
  124. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/serializer/dxfields.py +0 -0
  125. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/serializer/utils.py +0 -0
  126. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/setuphandlers.py +0 -0
  127. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/tests/__init__.py +0 -0
  128. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/tests/base.py +0 -0
  129. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/tests/test_doctests.py +0 -0
  130. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/upgrades/__init__.py +0 -0
  131. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/upgrades/configure.zcml +0 -0
  132. {eea_plotly-1.5 → eea_plotly-1.7}/eea/plotly/utils.py +0 -0
  133. {eea_plotly-1.5 → eea_plotly-1.7}/eea.plotly.egg-info/dependency_links.txt +0 -0
  134. {eea_plotly-1.5 → eea_plotly-1.7}/eea.plotly.egg-info/entry_points.txt +0 -0
  135. {eea_plotly-1.5 → eea_plotly-1.7}/eea.plotly.egg-info/namespace_packages.txt +0 -0
  136. {eea_plotly-1.5 → eea_plotly-1.7}/eea.plotly.egg-info/not-zip-safe +0 -0
  137. {eea_plotly-1.5 → eea_plotly-1.7}/eea.plotly.egg-info/top_level.txt +0 -0
  138. {eea_plotly-1.5 → eea_plotly-1.7}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eea.plotly
3
- Version: 1.5
3
+ Version: 1.7
4
4
  Summary: volto-plotlycharts backend support
5
5
  Home-page: https://github.com/eea/eea.plotly
6
6
  Author: European Environment Agency: IDM2 A-Team
@@ -23,7 +23,7 @@ Requires-Dist: setuptools
23
23
  Requires-Dist: plone.volto
24
24
  Requires-Dist: collective.folderishtypes
25
25
  Requires-Dist: plotly==5.24.1
26
- Requires-Dist: kaleido
26
+ Requires-Dist: kaleido==0.2.1
27
27
  Provides-Extra: test
28
28
  Requires-Dist: plone.app.testing; extra == "test"
29
29
  Dynamic: author
@@ -145,6 +145,17 @@ EEA_ - European Environment Agency (EU)
145
145
  Changelog
146
146
  =========
147
147
 
148
+ 1.7 - (2025-07-06)
149
+ ---------------------------
150
+ * Change: soer_miniature improved logic
151
+ [razvanMiu]
152
+
153
+ 1.6 - (2025-06-24)
154
+ ---------------------------
155
+ * Change: pin kaleido version to 0.2.1
156
+ * Refactor: soer_miniature adapter logic (new step functions, data trimming, axis ranges)
157
+ [razvanMiu]
158
+
148
159
  1.5 - (2025-06-05)
149
160
  ---------------------------
150
161
  * Change: soer_miniature: hide xaxis ticklabels if no data
@@ -1,6 +1,17 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ 1.7 - (2025-07-06)
5
+ ---------------------------
6
+ * Change: soer_miniature improved logic
7
+ [razvanMiu]
8
+
9
+ 1.6 - (2025-06-24)
10
+ ---------------------------
11
+ * Change: pin kaleido version to 0.2.1
12
+ * Refactor: soer_miniature adapter logic (new step functions, data trimming, axis ranges)
13
+ [razvanMiu]
14
+
4
15
  1.5 - (2025-06-05)
5
16
  ---------------------------
6
17
  * Change: soer_miniature: hide xaxis ticklabels if no data
@@ -9,6 +9,7 @@ from zope.publisher.interfaces import IPublishTraverse
9
9
  from Products.Five.browser import BrowserView
10
10
  from eea.plotly.controlpanel import IPlotlySettings
11
11
  from eea.plotly.utils import sanitizeVisualization
12
+ from eea.plotly.io_json import JSONEncoder
12
13
 
13
14
  from .preview_adapter.adapter import get_preview_adapter
14
15
 
@@ -74,7 +75,9 @@ class PlotlyPreview(BrowserView):
74
75
 
75
76
  get_preview_adapter(self, self.name)
76
77
 
77
- fig = pio.from_json(json.dumps(self.visualization), skip_invalid=True)
78
+ fig = pio.from_json(
79
+ json.dumps(self.visualization, cls=JSONEncoder),
80
+ skip_invalid=True)
78
81
 
79
82
  if "template" not in self.visualization["layout"]:
80
83
  fig.update_layout(template=None)
@@ -0,0 +1,159 @@
1
+ """ SOER miniature theme for Plotly visualizations. """
2
+ import math
3
+
4
+ SOER_TRACES_COUNT = 5
5
+
6
+
7
+ def nice_step(vmin, vmax, target_ticks=5):
8
+ """Calculate a 'nice' step size for axis ticks, similar to Plotly/D3."""
9
+ span = abs(vmax - vmin)
10
+ if span == 0:
11
+ return 1 # fallback
12
+
13
+ raw_step = span / max(target_ticks - 1, 1)
14
+ magnitude = 10 ** math.floor(math.log10(raw_step))
15
+ residual = raw_step / magnitude
16
+
17
+ if residual <= 1:
18
+ nice_multiplier = 1
19
+ elif residual <= 2:
20
+ nice_multiplier = 2
21
+ elif residual <= 2.5:
22
+ nice_multiplier = 2.5
23
+ elif residual <= 5:
24
+ nice_multiplier = 5
25
+ else:
26
+ nice_multiplier = 10
27
+
28
+ return nice_multiplier * magnitude
29
+
30
+
31
+ def exact_step(vmin, vmax, target_ticks=5):
32
+ """Get the exact step size to have target_ticks between vmin and vmax."""
33
+ if target_ticks < 2:
34
+ raise ValueError("target_ticks must be at least 2 to define a range.")
35
+ return abs(vmax - vmin) / (target_ticks - 1)
36
+
37
+
38
+ def getMin(arr):
39
+ """ Get minimum value from array """
40
+ return min(float(v) for v in arr if v is not None)
41
+
42
+
43
+ def getMax(arr):
44
+ """ Get maximum value from array """
45
+ return max(float(v) for v in arr if v is not None)
46
+
47
+
48
+ def serialize(context):
49
+ """ Serialize the context for SOER miniature theme"""
50
+ if context.visualization is None:
51
+ return False
52
+
53
+ data = context.visualization["data"]
54
+ layout = context.visualization["layout"]
55
+
56
+ if len(data) < SOER_TRACES_COUNT:
57
+ layout["xaxis"]["showticklabels"] = False
58
+ return False
59
+
60
+ min_year = float("inf")
61
+ max_year = float("-inf")
62
+ first_val = None
63
+ new_x = []
64
+ new_y = []
65
+ new_text = []
66
+
67
+ if data[0].get("x") is not None and data[0].get("y") is not None:
68
+ x_len = len(data[0].get("x") or [])
69
+ y_len = len(data[0].get("y") or [])
70
+ text_len = len(data[0].get("text") or [])
71
+
72
+ for index, val in enumerate(data[0]["y"]):
73
+ if val and not first_val:
74
+ first_val = val
75
+ if not first_val:
76
+ continue
77
+ year = data[0]["x"][index] if index < x_len else None
78
+ text = data[0]["text"][index] if index < text_len else None
79
+ new_x.append(year)
80
+ new_y.append(val)
81
+ new_text.append(text)
82
+ if val and year > max_year:
83
+ max_year = year
84
+ if val and year < min_year:
85
+ min_year = year
86
+
87
+ data[0]["x"] = new_x
88
+ data[0]["y"] = new_y
89
+ data[0]["text"] = new_text
90
+ y_len = len(data[0]["y"])
91
+ y4_len = len(data[4].get("y") or [])
92
+
93
+ if y4_len >= y_len:
94
+ data[4]["x"] = new_x
95
+ data[4]["y"] = data[4]["y"][y4_len - y_len:y4_len + 1]
96
+ elif data[4].get("x") is None or data[4].get("y") is None:
97
+ data[4] = {
98
+ "type": "scatter",
99
+ "x": new_x,
100
+ "y": [None] * len(new_y),
101
+ "visible": True,
102
+ "marker": {
103
+ "color": "rgba(0, 0, 0, 1)",
104
+ "line": {
105
+ "color": "rgba(0, 0, 0, 1)"
106
+ }
107
+ }
108
+ }
109
+ data[4]["y"][len(data[4]["y"]) - 1] = new_y[-1]
110
+
111
+ layout["xaxis"]["tickmode"] = "array"
112
+ layout["xaxis"]["tickvals"] = [min_year, max_year, 2030]
113
+ layout["xaxis"]["range"] = [
114
+ min_year - 2, 2032]
115
+ layout["xaxis"]["autorange"] = True
116
+
117
+ y_values = (
118
+ (data[0].get("y") or []) +
119
+ (data[1].get("y") or []) +
120
+ (data[4].get("y") or [])
121
+ )
122
+
123
+ if y_values:
124
+ top = (
125
+ layout.get("margin", {}).get("t") or
126
+ layout.get("template", {}).get("margin", {}).get("t")
127
+ ) or 0
128
+ min_y = getMin(y_values)
129
+ max_y = getMax(y_values)
130
+
131
+ min_y = min_y if min_y < 0 else 0
132
+ max_y = max_y if max_y > 0 else 0
133
+
134
+ nticks = max(int((context.height - top) / 100), 2)
135
+
136
+ step = exact_step(min_y, max_y, nticks)
137
+
138
+ layout["yaxis"]["tickmode"] = "linear"
139
+ layout["yaxis"]["nticks"] = nticks
140
+ layout["yaxis"]["tick0"] = min_y - step
141
+ layout["yaxis"]["dtick"] = step
142
+
143
+ layout["yaxis"]["range"] = [
144
+ min_y - step, max_y + 2 * step]
145
+ layout["yaxis"]["autorange"] = False
146
+
147
+ if "text" in data[0]:
148
+ data[0]["text"] = [
149
+ (t if t is None else " " + str(t))
150
+ for t in data[0]["text"]]
151
+
152
+ data[1]["x"] = None
153
+ data[1]["y"] = None
154
+ data[2]["x"] = None
155
+ data[2]["y"] = None
156
+ data[3]["x"] = None
157
+ data[3]["y"] = None
158
+
159
+ return True
@@ -12,6 +12,7 @@ from zope.event import notify
12
12
  from zope.lifecycleevent import Attributes, ObjectModifiedEvent
13
13
  from eea.plotly.behaviors import IPlotlyVisualization
14
14
  from eea.plotly.io_csv import CsvWriter
15
+ from eea.plotly.io_json import JSONEncoder
15
16
 
16
17
 
17
18
  @implementer(IDeserializeFromJson)
@@ -99,7 +100,9 @@ class DeserializeVisualizationFromJson(DeserializeFromJson):
99
100
  "data": self.context.visualization.get("data", []),
100
101
  "layout": self.context.visualization.get("layout", {}),
101
102
  "frames": self.context.visualization.get("frames", [])
102
- }),
103
+ },
104
+ cls=JSONEncoder
105
+ ),
103
106
  skip_invalid=True
104
107
  )
105
108
 
@@ -0,0 +1,12 @@
1
+ """JSON encoder that handles Decimal values."""
2
+ import decimal
3
+ import json
4
+
5
+
6
+ class JSONEncoder(json.JSONEncoder):
7
+ """JSON encoder that handles Decimal values."""
8
+
9
+ def default(self, o):
10
+ if isinstance(o, decimal.Decimal):
11
+ return str(o)
12
+ return super().default(o)
@@ -0,0 +1 @@
1
+ 1.7
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eea.plotly
3
- Version: 1.5
3
+ Version: 1.7
4
4
  Summary: volto-plotlycharts backend support
5
5
  Home-page: https://github.com/eea/eea.plotly
6
6
  Author: European Environment Agency: IDM2 A-Team
@@ -23,7 +23,7 @@ Requires-Dist: setuptools
23
23
  Requires-Dist: plone.volto
24
24
  Requires-Dist: collective.folderishtypes
25
25
  Requires-Dist: plotly==5.24.1
26
- Requires-Dist: kaleido
26
+ Requires-Dist: kaleido==0.2.1
27
27
  Provides-Extra: test
28
28
  Requires-Dist: plone.app.testing; extra == "test"
29
29
  Dynamic: author
@@ -145,6 +145,17 @@ EEA_ - European Environment Agency (EU)
145
145
  Changelog
146
146
  =========
147
147
 
148
+ 1.7 - (2025-07-06)
149
+ ---------------------------
150
+ * Change: soer_miniature improved logic
151
+ [razvanMiu]
152
+
153
+ 1.6 - (2025-06-24)
154
+ ---------------------------
155
+ * Change: pin kaleido version to 0.2.1
156
+ * Refactor: soer_miniature adapter logic (new step functions, data trimming, axis ranges)
157
+ [razvanMiu]
158
+
148
159
  1.5 - (2025-06-05)
149
160
  ---------------------------
150
161
  * Change: soer_miniature: hide xaxis ticklabels if no data
@@ -21,6 +21,7 @@ eea/plotly/configure.zcml
21
21
  eea/plotly/controlpanel.py
22
22
  eea/plotly/interfaces.py
23
23
  eea/plotly/io_csv.py
24
+ eea/plotly/io_json.py
24
25
  eea/plotly/permissions.zcml
25
26
  eea/plotly/profiles.zcml
26
27
  eea/plotly/setuphandlers.py
@@ -2,7 +2,7 @@ setuptools
2
2
  plone.volto
3
3
  collective.folderishtypes
4
4
  plotly==5.24.1
5
- kaleido
5
+ kaleido==0.2.1
6
6
 
7
7
  [test]
8
8
  plone.app.testing
@@ -46,7 +46,7 @@ setup(
46
46
  # -*- Extra requirements: -*-
47
47
  "collective.folderishtypes",
48
48
  'plotly==5.24.1',
49
- 'kaleido',
49
+ 'kaleido==0.2.1',
50
50
  ],
51
51
  extras_require={
52
52
  'test': [
@@ -1,80 +0,0 @@
1
- """ SOER miniature theme for Plotly visualizations. """
2
- import math
3
-
4
-
5
- def nice_step(vmin, vmax, target_ticks=5):
6
- """ Calculate a 'nice' step size for the axis ticks. """
7
- span = abs(vmax - vmin)
8
- if span == 0:
9
- return 1 # arbitrary fallback
10
-
11
- # Initial guess for raw step size
12
- raw_step = span / target_ticks
13
-
14
- # Determine the power of 10
15
- magnitude = 10 ** math.floor(math.log10(raw_step))
16
- residual = raw_step / magnitude
17
-
18
- # Choose a nice multiplier
19
- if residual < 1.5:
20
- nice_multiplier = 1
21
- elif residual < 3:
22
- nice_multiplier = 2
23
- elif residual < 7:
24
- nice_multiplier = 5
25
- else:
26
- nice_multiplier = 10
27
-
28
- return nice_multiplier * magnitude
29
-
30
-
31
- def getMin(arr):
32
- """ Get minimum value from array """
33
- return min(float(v) for v in arr if v is not None)
34
-
35
-
36
- def getMax(arr):
37
- """ Get maximum value from array """
38
- return max(float(v) for v in arr if v is not None)
39
-
40
-
41
- def serialize(context):
42
- """ Serialize the context for SOER miniature theme"""
43
-
44
- # Solve x axis range
45
- if context.visualization is None or len(context.visualization["data"]) < 2:
46
- context.visualization["layout"]["xaxis"]["showticklabels"] = False
47
- return False
48
-
49
- years = context.visualization["data"][0].get("x", [])
50
- tickvals = context.visualization["layout"]["xaxis"].get("tickvals", [])
51
-
52
- if tickvals and years:
53
- min_year = getMin(tickvals)
54
- max_year = getMax(years)
55
-
56
- context.visualization["layout"]["xaxis"]["range"] = [
57
- min_year - 2, max_year + 2]
58
- context.visualization["layout"]["xaxis"]["autorange"] = False
59
-
60
- # Solve y axis range
61
-
62
- y_values = context.visualization["data"][0].get(
63
- "y", []) + context.visualization["data"][1].get("y", [])
64
-
65
- if y_values:
66
- min_y = getMin(y_values)
67
- max_y = getMax(y_values)
68
-
69
- step = nice_step(min_y, max_y, 10)
70
-
71
- context.visualization["layout"]["yaxis"]["range"] = [
72
- min_y - step, max_y + step]
73
- context.visualization["layout"]["yaxis"]["autorange"] = False
74
-
75
- if "text" in context.visualization["data"][0]:
76
- context.visualization["data"][0]["text"] = [
77
- (t if t is None else " " + str(t))
78
- for t in context.visualization["data"][0]["text"]]
79
-
80
- return True
@@ -1 +0,0 @@
1
- 1.5
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes