datastake-daf 0.6.817 → 0.6.818
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.
- package/dist/components/index.js +54 -10
- package/dist/pages/index.js +222 -58
- package/dist/style/datastake/mapbox-gl.css +330 -0
- package/package.json +1 -1
- package/public/Vegetation/damage-from-insects-default.svg +1 -0
- package/public/Vegetation/dry-or-dead-default.svg +1 -0
- package/public/Vegetation/healthy-default.svg +1 -0
- package/public/Vegetation/yellowing.svg +1 -0
- package/src/@daf/core/components/Charts/RadarChart/index.jsx +53 -2
- package/src/@daf/core/components/Charts/style.js +1 -1
- package/src/@daf/core/components/Dashboard/Widget/VegetationWidget/index.jsx +0 -4
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/BiodiversityHabitat/ObservedFauna.jsx +6 -11
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/BiodiversityHabitat/index.jsx +4 -2
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/MangroveGrowth/PlantedSpecies.jsx +25 -10
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/MangroveGrowth/SeedlingsHeight.jsx +10 -13
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/MangroveGrowth/VegetationHealth.jsx +19 -4
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/SoilWaterProfile/SoilType.jsx +22 -10
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/SoilWaterProfile/WaterQuality.jsx +26 -10
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/chartHelpers.js +74 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
/* Isolated Mapbox GL CSS - Scoped to prevent Leaflet conflicts */
|
|
2
|
+
|
|
3
|
+
/* Mapbox GL Core Styles - Scoped with .mapbox-gl-scope */
|
|
4
|
+
.mapbox-gl-scope .mapboxgl-map {
|
|
5
|
+
font: 12px/20px Helvetica Neue, Arial, Helvetica, sans-serif;
|
|
6
|
+
overflow: hidden;
|
|
7
|
+
position: relative;
|
|
8
|
+
-webkit-tap-highlight-color: rgb(0 0 0/0);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.mapbox-gl-scope .mapboxgl-canvas {
|
|
12
|
+
left: 0;
|
|
13
|
+
position: absolute;
|
|
14
|
+
top: 0;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.mapbox-gl-scope .mapboxgl-map:-webkit-full-screen {
|
|
18
|
+
height: 100%;
|
|
19
|
+
width: 100%;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.mapbox-gl-scope .mapboxgl-canary {
|
|
23
|
+
background-color: salmon;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.mapbox-gl-scope .mapboxgl-canvas-container.mapboxgl-interactive,
|
|
27
|
+
.mapbox-gl-scope .mapboxgl-ctrl-group button.mapboxgl-ctrl-compass {
|
|
28
|
+
cursor: grab;
|
|
29
|
+
-webkit-user-select: none;
|
|
30
|
+
user-select: none;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.mapbox-gl-scope .mapboxgl-canvas-container.mapboxgl-interactive.mapboxgl-track-pointer {
|
|
34
|
+
cursor: pointer;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.mapbox-gl-scope .mapboxgl-canvas-container.mapboxgl-interactive:active,
|
|
38
|
+
.mapbox-gl-scope .mapboxgl-ctrl-group button.mapboxgl-ctrl-compass:active {
|
|
39
|
+
cursor: grabbing;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.mapbox-gl-scope .mapboxgl-canvas-container.mapboxgl-touch-zoom-rotate,
|
|
43
|
+
.mapbox-gl-scope .mapboxgl-canvas-container.mapboxgl-touch-zoom-rotate .mapboxgl-canvas {
|
|
44
|
+
touch-action: pan-x pan-y;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.mapbox-gl-scope .mapboxgl-canvas-container.mapboxgl-touch-drag-pan,
|
|
48
|
+
.mapbox-gl-scope .mapboxgl-canvas-container.mapboxgl-touch-drag-pan .mapboxgl-canvas {
|
|
49
|
+
touch-action: pinch-zoom;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.mapbox-gl-scope .mapboxgl-canvas-container.mapboxgl-touch-zoom-rotate.mapboxgl-touch-drag-pan,
|
|
53
|
+
.mapbox-gl-scope .mapboxgl-canvas-container.mapboxgl-touch-zoom-rotate.mapboxgl-touch-drag-pan .mapboxgl-canvas {
|
|
54
|
+
touch-action: none;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* Control positioning */
|
|
58
|
+
.mapbox-gl-scope .mapboxgl-ctrl-bottom,
|
|
59
|
+
.mapbox-gl-scope .mapboxgl-ctrl-bottom-left,
|
|
60
|
+
.mapbox-gl-scope .mapboxgl-ctrl-bottom-right,
|
|
61
|
+
.mapbox-gl-scope .mapboxgl-ctrl-left,
|
|
62
|
+
.mapbox-gl-scope .mapboxgl-ctrl-right,
|
|
63
|
+
.mapbox-gl-scope .mapboxgl-ctrl-top,
|
|
64
|
+
.mapbox-gl-scope .mapboxgl-ctrl-top-left,
|
|
65
|
+
.mapbox-gl-scope .mapboxgl-ctrl-top-right {
|
|
66
|
+
pointer-events: none;
|
|
67
|
+
position: absolute;
|
|
68
|
+
z-index: 2;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.mapbox-gl-scope .mapboxgl-ctrl-top-left {
|
|
72
|
+
left: 0;
|
|
73
|
+
top: 0;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.mapbox-gl-scope .mapboxgl-ctrl-top {
|
|
77
|
+
left: 50%;
|
|
78
|
+
top: 0;
|
|
79
|
+
transform: translateX(-50%);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.mapbox-gl-scope .mapboxgl-ctrl-top-right {
|
|
83
|
+
right: 0;
|
|
84
|
+
top: 0;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.mapbox-gl-scope .mapboxgl-ctrl-right {
|
|
88
|
+
right: 0;
|
|
89
|
+
top: 50%;
|
|
90
|
+
transform: translateY(-50%);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.mapbox-gl-scope .mapboxgl-ctrl-bottom-right {
|
|
94
|
+
bottom: 0;
|
|
95
|
+
right: 0;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.mapbox-gl-scope .mapboxgl-ctrl-bottom {
|
|
99
|
+
bottom: 0;
|
|
100
|
+
left: 50%;
|
|
101
|
+
transform: translateX(-50%);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.mapbox-gl-scope .mapboxgl-ctrl-bottom-left {
|
|
105
|
+
bottom: 0;
|
|
106
|
+
left: 0;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.mapbox-gl-scope .mapboxgl-ctrl-left {
|
|
110
|
+
left: 0;
|
|
111
|
+
top: 50%;
|
|
112
|
+
transform: translateY(-50%);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.mapbox-gl-scope .mapboxgl-ctrl {
|
|
116
|
+
clear: both;
|
|
117
|
+
pointer-events: auto;
|
|
118
|
+
transform: translate(0);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.mapbox-gl-scope .mapboxgl-ctrl-top-left .mapboxgl-ctrl {
|
|
122
|
+
float: left;
|
|
123
|
+
margin: 10px 0 0 10px;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.mapbox-gl-scope .mapboxgl-ctrl-top .mapboxgl-ctrl {
|
|
127
|
+
float: left;
|
|
128
|
+
margin: 10px 0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.mapbox-gl-scope .mapboxgl-ctrl-top-right .mapboxgl-ctrl {
|
|
132
|
+
float: right;
|
|
133
|
+
margin: 10px 10px 0 0;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.mapbox-gl-scope .mapboxgl-ctrl-bottom-right .mapboxgl-ctrl,
|
|
137
|
+
.mapbox-gl-scope .mapboxgl-ctrl-right .mapboxgl-ctrl {
|
|
138
|
+
float: right;
|
|
139
|
+
margin: 0 10px 10px 0;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.mapbox-gl-scope .mapboxgl-ctrl-bottom .mapboxgl-ctrl {
|
|
143
|
+
float: left;
|
|
144
|
+
margin: 10px 0;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.mapbox-gl-scope .mapboxgl-ctrl-bottom-left .mapboxgl-ctrl,
|
|
148
|
+
.mapbox-gl-scope .mapboxgl-ctrl-left .mapboxgl-ctrl {
|
|
149
|
+
float: left;
|
|
150
|
+
margin: 0 0 10px 10px;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/* Control group styling */
|
|
154
|
+
.mapbox-gl-scope .mapboxgl-ctrl-group {
|
|
155
|
+
background: #fff;
|
|
156
|
+
border-radius: 4px;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.mapbox-gl-scope .mapboxgl-ctrl-group:not(:empty) {
|
|
160
|
+
box-shadow: 0 0 0 2px #0000001a;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.mapbox-gl-scope .mapboxgl-ctrl-group button {
|
|
164
|
+
background-color: initial;
|
|
165
|
+
border: 0;
|
|
166
|
+
box-sizing: border-box;
|
|
167
|
+
cursor: pointer;
|
|
168
|
+
display: block;
|
|
169
|
+
height: 29px;
|
|
170
|
+
outline: none;
|
|
171
|
+
overflow: hidden;
|
|
172
|
+
padding: 0;
|
|
173
|
+
width: 29px;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.mapbox-gl-scope .mapboxgl-ctrl-group button+button {
|
|
177
|
+
border-top: 1px solid #ddd;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.mapbox-gl-scope .mapboxgl-ctrl button .mapboxgl-ctrl-icon {
|
|
181
|
+
background-position: 50%;
|
|
182
|
+
background-repeat: no-repeat;
|
|
183
|
+
display: block;
|
|
184
|
+
height: 100%;
|
|
185
|
+
width: 100%;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.mapbox-gl-scope .mapboxgl-ctrl-attrib-button:focus,
|
|
189
|
+
.mapbox-gl-scope .mapboxgl-ctrl-group button:focus {
|
|
190
|
+
box-shadow: 0 0 2px 2px #0096ff;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.mapbox-gl-scope .mapboxgl-ctrl button:disabled {
|
|
194
|
+
cursor: not-allowed;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.mapbox-gl-scope .mapboxgl-ctrl button:disabled .mapboxgl-ctrl-icon {
|
|
198
|
+
opacity: .25;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.mapbox-gl-scope .mapboxgl-ctrl-group button:first-child {
|
|
202
|
+
border-radius: 4px 4px 0 0;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.mapbox-gl-scope .mapboxgl-ctrl-group button:last-child {
|
|
206
|
+
border-radius: 0 0 4px 4px;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.mapbox-gl-scope .mapboxgl-ctrl-group button:only-child {
|
|
210
|
+
border-radius: inherit;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.mapbox-gl-scope .mapboxgl-ctrl button:not(:disabled):hover {
|
|
214
|
+
background-color: #0000000d;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/* Marker styles */
|
|
218
|
+
.mapbox-gl-scope .mapboxgl-marker {
|
|
219
|
+
position: absolute;
|
|
220
|
+
z-index: 1;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.mapbox-gl-scope .mapboxgl-marker svg {
|
|
224
|
+
display: block;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/* Popup styles */
|
|
228
|
+
.mapbox-gl-scope .mapboxgl-popup {
|
|
229
|
+
position: absolute;
|
|
230
|
+
text-align: center;
|
|
231
|
+
margin-bottom: 20px;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.mapbox-gl-scope .mapboxgl-popup-content-wrapper {
|
|
235
|
+
padding: 1px;
|
|
236
|
+
text-align: left;
|
|
237
|
+
border-radius: 12px;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.mapbox-gl-scope .mapboxgl-popup-content {
|
|
241
|
+
margin: 13px 24px 13px 20px;
|
|
242
|
+
line-height: 1.3;
|
|
243
|
+
font-size: 13px;
|
|
244
|
+
min-height: 1px;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.mapbox-gl-scope .mapboxgl-popup-content p {
|
|
248
|
+
margin: 17px 0;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.mapbox-gl-scope .mapboxgl-popup-tip-container {
|
|
252
|
+
width: 40px;
|
|
253
|
+
height: 20px;
|
|
254
|
+
position: absolute;
|
|
255
|
+
left: 50%;
|
|
256
|
+
margin-top: -1px;
|
|
257
|
+
margin-left: -20px;
|
|
258
|
+
overflow: hidden;
|
|
259
|
+
pointer-events: none;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.mapbox-gl-scope .mapboxgl-popup-tip {
|
|
263
|
+
width: 17px;
|
|
264
|
+
height: 17px;
|
|
265
|
+
padding: 1px;
|
|
266
|
+
margin: -10px auto 0;
|
|
267
|
+
pointer-events: auto;
|
|
268
|
+
-webkit-transform: rotate(45deg);
|
|
269
|
+
-moz-transform: rotate(45deg);
|
|
270
|
+
-ms-transform: rotate(45deg);
|
|
271
|
+
transform: rotate(45deg);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.mapbox-gl-scope .mapboxgl-popup-content-wrapper,
|
|
275
|
+
.mapbox-gl-scope .mapboxgl-popup-tip {
|
|
276
|
+
background: white;
|
|
277
|
+
color: #333;
|
|
278
|
+
box-shadow: 0 3px 14px rgba(0, 0, 0, 0.4);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.mapbox-gl-scope .mapboxgl-popup-close-button {
|
|
282
|
+
position: absolute;
|
|
283
|
+
top: 0;
|
|
284
|
+
right: 0;
|
|
285
|
+
border: none;
|
|
286
|
+
text-align: center;
|
|
287
|
+
width: 24px;
|
|
288
|
+
height: 24px;
|
|
289
|
+
font: 16px/24px Tahoma, Verdana, sans-serif;
|
|
290
|
+
color: #757575;
|
|
291
|
+
text-decoration: none;
|
|
292
|
+
background: transparent;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.mapbox-gl-scope .mapboxgl-popup-close-button:hover,
|
|
296
|
+
.mapbox-gl-scope .mapboxgl-popup-close-button:focus {
|
|
297
|
+
color: #585858;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/* Attribution */
|
|
301
|
+
.mapbox-gl-scope .mapboxgl-ctrl-attribution {
|
|
302
|
+
background: #fff;
|
|
303
|
+
background: rgba(255, 255, 255, 0.8);
|
|
304
|
+
margin: 0;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
.mapbox-gl-scope .mapboxgl-ctrl-attribution,
|
|
308
|
+
.mapbox-gl-scope .mapboxgl-ctrl-scale-line {
|
|
309
|
+
padding: 0 5px;
|
|
310
|
+
color: #333;
|
|
311
|
+
line-height: 1.4;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
.mapbox-gl-scope .mapboxgl-ctrl-attribution a {
|
|
315
|
+
text-decoration: none;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
.mapbox-gl-scope .mapboxgl-ctrl-attribution a:hover,
|
|
319
|
+
.mapbox-gl-scope .mapboxgl-ctrl-attribution a:focus {
|
|
320
|
+
text-decoration: underline;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/* Hide attribution by default */
|
|
324
|
+
.mapbox-gl-scope .mapboxgl-ctrl-attribution {
|
|
325
|
+
display: none !important;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
.mapbox-gl-scope .mapboxgl-ctrl-logo {
|
|
329
|
+
display: none !important;
|
|
330
|
+
}
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useRef, useEffect } from "react";
|
|
1
|
+
import React, { useRef, useEffect, useCallback } from "react";
|
|
2
2
|
import { Radar } from "@antv/g2plot";
|
|
3
3
|
import { theme } from "antd";
|
|
4
4
|
import { renderTooltip } from "../../../../utils/tooltip";
|
|
@@ -39,6 +39,46 @@ const RadarChart = ({
|
|
|
39
39
|
legendStyle
|
|
40
40
|
} = useLegendConfig({legendConfig, isPdf});
|
|
41
41
|
|
|
42
|
+
// Helper function to wrap long text labels to multiple lines
|
|
43
|
+
// Ensures text is never hidden - wraps to multiple lines if needed
|
|
44
|
+
const wrapLabel = useCallback((text, maxLength = 10) => {
|
|
45
|
+
if (!text) {
|
|
46
|
+
return '';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const formattedText = formattedXAxis(text);
|
|
50
|
+
|
|
51
|
+
// If text is short enough, return as is
|
|
52
|
+
if (formattedText.length <= maxLength) {
|
|
53
|
+
return formattedText;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Split by spaces to find word boundaries
|
|
57
|
+
const words = formattedText.split(' ');
|
|
58
|
+
const lines = [];
|
|
59
|
+
let currentLine = '';
|
|
60
|
+
|
|
61
|
+
words.forEach((word, index) => {
|
|
62
|
+
// If adding this word would exceed maxLength, start a new line
|
|
63
|
+
if (currentLine && (currentLine + ' ' + word).length > maxLength) {
|
|
64
|
+
if (currentLine) {
|
|
65
|
+
lines.push(currentLine);
|
|
66
|
+
}
|
|
67
|
+
currentLine = word;
|
|
68
|
+
} else {
|
|
69
|
+
currentLine = currentLine ? currentLine + ' ' + word : word;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// If it's the last word, add it to lines
|
|
73
|
+
if (index === words.length - 1 && currentLine) {
|
|
74
|
+
lines.push(currentLine);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Ensure we always return something - never empty
|
|
79
|
+
return lines.length > 0 ? lines.join('\n') : formattedText;
|
|
80
|
+
}, [formattedXAxis]);
|
|
81
|
+
|
|
42
82
|
useEffect(() => {
|
|
43
83
|
if (!containerRef.current) {
|
|
44
84
|
return;
|
|
@@ -59,9 +99,19 @@ const RadarChart = ({
|
|
|
59
99
|
}
|
|
60
100
|
: { showCrosshairs: false, showMarkers: true, ...tooltipConfig },
|
|
61
101
|
color: color || token.colorPrimary7,
|
|
102
|
+
// Increased padding to ensure labels are never clipped
|
|
103
|
+
padding: [50, 50, 50, 50],
|
|
62
104
|
xAxis: {
|
|
63
105
|
label: {
|
|
64
|
-
formatter:
|
|
106
|
+
formatter: (text) => wrapLabel(text, 10),
|
|
107
|
+
offset: 15,
|
|
108
|
+
autoRotate: false,
|
|
109
|
+
autoHide: false, // Never hide labels
|
|
110
|
+
autoEllipsis: false, // Never truncate with ellipsis
|
|
111
|
+
style: {
|
|
112
|
+
fontSize: 12,
|
|
113
|
+
fill: '#666',
|
|
114
|
+
},
|
|
65
115
|
},
|
|
66
116
|
line: null,
|
|
67
117
|
tickLine: null,
|
|
@@ -129,6 +179,7 @@ const RadarChart = ({
|
|
|
129
179
|
formattedXAxis,
|
|
130
180
|
score,
|
|
131
181
|
token.colorPrimary7,
|
|
182
|
+
wrapLabel,
|
|
132
183
|
rest,
|
|
133
184
|
]);
|
|
134
185
|
|
|
@@ -2,7 +2,7 @@ import styled from "styled-components";
|
|
|
2
2
|
|
|
3
3
|
const Container = styled.div`
|
|
4
4
|
height: ${props => props.height || '300px'};
|
|
5
|
-
width: ${props => props.isPdf ? (props.width ? props.width : '1000px') : 'calc(100% - 48px)'};
|
|
5
|
+
width: ${props => props.isPdf ? (props.width ? props.width : '1000px') : 'calc(100% - 48px)'};
|
|
6
6
|
`;
|
|
7
7
|
|
|
8
8
|
export default Container;
|
|
@@ -16,16 +16,12 @@ export default function VegetationWidget({
|
|
|
16
16
|
}) {
|
|
17
17
|
let vegetationConfig = getVegetationConfig();
|
|
18
18
|
|
|
19
|
-
// Get all VEGETATION_KEYS values before filtering (needed for mapping check)
|
|
20
19
|
const allVegetationKeys = vegetationConfig.map(item => item.key);
|
|
21
20
|
|
|
22
|
-
// Filter to show only specific keys if filterKeys is provided
|
|
23
21
|
if (filterKeys && Array.isArray(filterKeys)) {
|
|
24
22
|
vegetationConfig = vegetationConfig.filter(item => filterKeys.includes(item.key));
|
|
25
23
|
}
|
|
26
24
|
|
|
27
|
-
// Map growthObservations to VEGETATION_KEYS
|
|
28
|
-
// Handle both formats: growthObservations keys (e.g., "yellowing_leaves") and VEGETATION_KEYS (e.g., "yellowing")
|
|
29
25
|
const mappedGrowthObservations = Array.isArray(growthObservations)
|
|
30
26
|
? growthObservations
|
|
31
27
|
.map(obs => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useMemo } from 'react';
|
|
2
2
|
import { Widget, BarChart } from '../../../../../../../../src/index.js';
|
|
3
|
-
import {
|
|
3
|
+
import { calculateNaturalAxisConfig, mergeDefaultCategories } from '../chartHelpers.js';
|
|
4
4
|
|
|
5
5
|
const ObservedFauna = ({
|
|
6
6
|
observedFaunaChart,
|
|
@@ -32,16 +32,11 @@ const ObservedFauna = ({
|
|
|
32
32
|
}, [observedFaunaChart, options]);
|
|
33
33
|
|
|
34
34
|
const xAxisConfig = useMemo(() => {
|
|
35
|
-
|
|
36
|
-
chartData
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
min: 0,
|
|
41
|
-
max: 10,
|
|
42
|
-
tickMethod: () => [0, 2, 4, 6, 8, 10]
|
|
43
|
-
}
|
|
44
|
-
);
|
|
35
|
+
const maxValue = chartData && chartData.length > 0
|
|
36
|
+
? Math.max(...chartData.map(item => Number(item?.value) || 0))
|
|
37
|
+
: 0;
|
|
38
|
+
|
|
39
|
+
return calculateNaturalAxisConfig(maxValue);
|
|
45
40
|
}, [chartData]);
|
|
46
41
|
|
|
47
42
|
return (
|
|
@@ -83,8 +83,8 @@ const BiodiversityHabitat = ({
|
|
|
83
83
|
t={t}
|
|
84
84
|
/>
|
|
85
85
|
|
|
86
|
-
<div style={{ display: "flex", gap: "24px" }}>
|
|
87
|
-
<section style={{ flex: 1 }}>
|
|
86
|
+
<div style={{ display: "flex", gap: "24px", flexWrap: "wrap" }}>
|
|
87
|
+
<section style={{ flex: 1, minWidth: "300px" }}>
|
|
88
88
|
<ObservedFauna
|
|
89
89
|
observedFaunaChart={observedFauna}
|
|
90
90
|
t={t}
|
|
@@ -92,11 +92,13 @@ const BiodiversityHabitat = ({
|
|
|
92
92
|
/>
|
|
93
93
|
</section>
|
|
94
94
|
|
|
95
|
+
<section style={{ flex: 1, minWidth: "300px" }}>
|
|
95
96
|
<InvasiveSpecies
|
|
96
97
|
invasiveSpeciesChart={invasiveSpecies}
|
|
97
98
|
t={t}
|
|
98
99
|
options={options}
|
|
99
100
|
/>
|
|
101
|
+
</section>
|
|
100
102
|
|
|
101
103
|
</div>
|
|
102
104
|
</Widget>
|
|
@@ -2,7 +2,14 @@ import React, { useMemo, useCallback } from 'react';
|
|
|
2
2
|
import { Widget, PieChart } from '../../../../../../../../src/index.js';
|
|
3
3
|
import { renderTooltipJsx } from '../../../../../../utils/tooltip.js';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
// Color mapping for planted species
|
|
6
|
+
const PLANTED_SPECIES_COLORS = {
|
|
7
|
+
rhyzophora_mangle: '#016C6E',
|
|
8
|
+
rhyzophora: '#00AEB1',
|
|
9
|
+
rhyzophora_sp: '#A0EBEC',
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const DEFAULT_COLOR = '#9E9E9E';
|
|
6
13
|
|
|
7
14
|
const PlantedSpecies = ({
|
|
8
15
|
plantedSpeciesChart,
|
|
@@ -27,7 +34,7 @@ const PlantedSpecies = ({
|
|
|
27
34
|
return data.map((item, index) => ({
|
|
28
35
|
value: Number(item?.count) || 0,
|
|
29
36
|
percent: total > 0 ? (Number(item?.count) || 0) / total : 0,
|
|
30
|
-
color:
|
|
37
|
+
color: PLANTED_SPECIES_COLORS[item?.name] || DEFAULT_COLOR,
|
|
31
38
|
label: optionsMap[item?.name] || item?.name || '',
|
|
32
39
|
key: item?.name || `item-${index}`,
|
|
33
40
|
}));
|
|
@@ -44,18 +51,26 @@ const PlantedSpecies = ({
|
|
|
44
51
|
return null;
|
|
45
52
|
}
|
|
46
53
|
|
|
54
|
+
// Calculate total from all items
|
|
55
|
+
const total = pieData.reduce((sum, dataItem) => sum + (dataItem.value || 0), 0);
|
|
56
|
+
|
|
57
|
+
// Show all items in the tooltip, sorted by value (descending)
|
|
58
|
+
const allItems = pieData
|
|
59
|
+
.filter(dataItem => dataItem.value > 0)
|
|
60
|
+
.sort((a, b) => b.value - a.value)
|
|
61
|
+
.map(dataItem => ({
|
|
62
|
+
color: dataItem.color,
|
|
63
|
+
label: dataItem.label || '',
|
|
64
|
+
value: dataItem.value || 0,
|
|
65
|
+
}));
|
|
66
|
+
|
|
47
67
|
return renderTooltipJsx({
|
|
48
68
|
title: t("Planted Species"),
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
color: item.color,
|
|
52
|
-
label: item.label || '',
|
|
53
|
-
value: item.value || 0,
|
|
54
|
-
},
|
|
55
|
-
],
|
|
69
|
+
subTitle: total.toLocaleString(),
|
|
70
|
+
items: allItems,
|
|
56
71
|
});
|
|
57
72
|
},
|
|
58
|
-
[t, isEmpty]
|
|
73
|
+
[t, isEmpty, pieData]
|
|
59
74
|
);
|
|
60
75
|
|
|
61
76
|
return (
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useMemo } from 'react';
|
|
2
2
|
import { Widget, ColumnChart } from '../../../../../../../../src/index.js';
|
|
3
|
-
import {
|
|
3
|
+
import { calculateNaturalAxisConfig, mergeDefaultCategories } from '../chartHelpers.js';
|
|
4
4
|
|
|
5
5
|
// Default height ranges to always display
|
|
6
6
|
const DEFAULT_HEIGHT_RANGES = [
|
|
@@ -26,16 +26,13 @@ const SeedlingsHeight = ({
|
|
|
26
26
|
}, [seedlingsHeightChart]);
|
|
27
27
|
|
|
28
28
|
const yAxisConfig = useMemo(() => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
tickMethod: () => [0, 5, 10, 15, 20]
|
|
37
|
-
}
|
|
38
|
-
);
|
|
29
|
+
// Calculate max value from data
|
|
30
|
+
const maxValue = chartData && chartData.length > 0
|
|
31
|
+
? Math.max(...chartData.map(item => Number(item?.value) || 0))
|
|
32
|
+
: 0;
|
|
33
|
+
|
|
34
|
+
// Use the helper function to calculate natural number axis configuration
|
|
35
|
+
return calculateNaturalAxisConfig(maxValue);
|
|
39
36
|
}, [chartData]);
|
|
40
37
|
|
|
41
38
|
return (
|
|
@@ -58,10 +55,10 @@ const SeedlingsHeight = ({
|
|
|
58
55
|
const item = data[0]?.data || data[0];
|
|
59
56
|
return {
|
|
60
57
|
title: t("Seedlings Height"),
|
|
61
|
-
subTitle: title,
|
|
62
58
|
items: [
|
|
63
59
|
{
|
|
64
|
-
|
|
60
|
+
color: "#016C6E",
|
|
61
|
+
label: title,
|
|
65
62
|
value: item?.value || 0,
|
|
66
63
|
},
|
|
67
64
|
],
|
|
@@ -2,7 +2,22 @@ import React, { useMemo, useCallback } from 'react';
|
|
|
2
2
|
import { Widget, PieChart } from '../../../../../../../../src/index.js';
|
|
3
3
|
import { renderTooltipJsx } from '../../../../../../utils/tooltip.js';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
// Color mapping for vegetation health conditions
|
|
6
|
+
const VEGETATION_HEALTH_COLORS = {
|
|
7
|
+
healthy_leaves: '#6AD99E',
|
|
8
|
+
white_spots: '#E8F0F0',
|
|
9
|
+
yellowing_leaves: '#CDC14F',
|
|
10
|
+
black_spots: '#2E3131',
|
|
11
|
+
reddish_spots: '#CB2525',
|
|
12
|
+
leaf_mosaic: '#B59E76',
|
|
13
|
+
spider_webs: '#F8F6EF',
|
|
14
|
+
damage_from_insects: '#DE8954',
|
|
15
|
+
dry_dead_leaves: '#767870',
|
|
16
|
+
no_leaves: '#F97066',
|
|
17
|
+
other: '#BDBDBD',
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const DEFAULT_COLOR = '#9E9E9E';
|
|
6
21
|
|
|
7
22
|
const VegetationHealth = ({
|
|
8
23
|
vegetationHealthChart,
|
|
@@ -26,15 +41,15 @@ const VegetationHealth = ({
|
|
|
26
41
|
return data.map((item, index) => ({
|
|
27
42
|
value: Number(item?.count) || 0,
|
|
28
43
|
percent: total > 0 ? (Number(item?.count) || 0) / total : 0,
|
|
29
|
-
color:
|
|
44
|
+
color: VEGETATION_HEALTH_COLORS[item?.name] || DEFAULT_COLOR,
|
|
30
45
|
label: optionsMap[item?.name] || item?.name || '',
|
|
31
46
|
key: item?.name || `item-${index}`,
|
|
32
47
|
}));
|
|
33
48
|
}, [vegetationHealthChart, optionsMap]);
|
|
34
49
|
|
|
35
50
|
const isEmpty = useMemo(() => {
|
|
36
|
-
return !vegetationHealthChart || vegetationHealthChart.length === 0 ||
|
|
37
|
-
|
|
51
|
+
return !vegetationHealthChart || vegetationHealthChart.length === 0 ||
|
|
52
|
+
vegetationHealthChart.every(item => !item?.count || Number(item.count) === 0);
|
|
38
53
|
}, [vegetationHealthChart]);
|
|
39
54
|
|
|
40
55
|
const getTooltipChildren = useCallback(
|