datastake-daf 0.6.826 → 0.6.827
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 +1228 -1195
- package/dist/pages/index.js +77 -58
- package/dist/style/datastake/mapbox-gl.css +330 -0
- package/package.json +1 -1
- package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CommunityParticipation/JobsTimeline/index.jsx +32 -9
- package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CycleIndicators/HealthAndSafety/helper.js +48 -43
- package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CycleIndicators/HealthAndSafety/index.jsx +17 -5
- package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CycleOutcomes/PlantingActivitiesTimeline.jsx +12 -5
package/dist/pages/index.js
CHANGED
|
@@ -55413,14 +55413,19 @@ const PlantingActivitiesTimeline = ({
|
|
|
55413
55413
|
const dataToProcess = !activitiesTimelineChart || !Array.isArray(activitiesTimelineChart) || activitiesTimelineChart.length === 0 ? [] : activitiesTimelineChart;
|
|
55414
55414
|
|
|
55415
55415
|
// Process data without cumulative calculation (for activities timeline)
|
|
55416
|
-
|
|
55416
|
+
const processedData = processChartDateData({
|
|
55417
55417
|
mainData: dataToProcess,
|
|
55418
55418
|
isCumulative: false,
|
|
55419
55419
|
valueField: 'count'
|
|
55420
55420
|
});
|
|
55421
|
-
}, [activitiesTimelineChart, processChartDateData]);
|
|
55422
55421
|
|
|
55423
|
-
|
|
55422
|
+
// Remove trailing periods with 0 jobs (optional: remove all zero if you prefer)
|
|
55423
|
+
let lastNonZeroIndex = processedData.length - 1;
|
|
55424
|
+
while (lastNonZeroIndex >= 0 && (processedData[lastNonZeroIndex].jobs || 0) === 0) {
|
|
55425
|
+
lastNonZeroIndex--;
|
|
55426
|
+
}
|
|
55427
|
+
return processedData.slice(0, lastNonZeroIndex + 1);
|
|
55428
|
+
}, [activitiesTimelineChart, processChartDateData]);
|
|
55424
55429
|
const maxActivitiesYValue = React.useMemo(() => {
|
|
55425
55430
|
if (!activitiesTimelineData || activitiesTimelineData.length === 0) {
|
|
55426
55431
|
return 100;
|
|
@@ -55765,6 +55770,29 @@ const CyclePartners = ({
|
|
|
55765
55770
|
});
|
|
55766
55771
|
};
|
|
55767
55772
|
|
|
55773
|
+
// Custom tooltip labels per field/value
|
|
55774
|
+
const FIELD_TOOLTIP_LABELS = {
|
|
55775
|
+
aidKitAccessible: {
|
|
55776
|
+
compliant: "Available",
|
|
55777
|
+
notCompliant: "Not available",
|
|
55778
|
+
empty: "No data"
|
|
55779
|
+
},
|
|
55780
|
+
hsTrainingConfirmation: {
|
|
55781
|
+
compliant: "Training delivered",
|
|
55782
|
+
notCompliant: "No training",
|
|
55783
|
+
empty: "No data"
|
|
55784
|
+
},
|
|
55785
|
+
duosFormed: {
|
|
55786
|
+
compliant: "Duos formed",
|
|
55787
|
+
notCompliant: "Not implemented",
|
|
55788
|
+
empty: "No data"
|
|
55789
|
+
},
|
|
55790
|
+
presenceOfChildren: {
|
|
55791
|
+
compliant: "None reported",
|
|
55792
|
+
notCompliant: "Children present",
|
|
55793
|
+
empty: "No data"
|
|
55794
|
+
}
|
|
55795
|
+
};
|
|
55768
55796
|
const HEALTH_SAFETY_COLORS = {
|
|
55769
55797
|
compliant: '#016C6E',
|
|
55770
55798
|
notCompliant: '#F97066',
|
|
@@ -55776,12 +55804,6 @@ const getIndicatorType$1 = value => {
|
|
|
55776
55804
|
if (value === null || value === undefined) return "empty";
|
|
55777
55805
|
return "empty";
|
|
55778
55806
|
};
|
|
55779
|
-
|
|
55780
|
-
/**
|
|
55781
|
-
* Gets health and safety distribution data from activity data
|
|
55782
|
-
* @param {Object} activityData - Activity data object
|
|
55783
|
-
* @returns {Object} Distribution object with compliant, notCompliant, and empty counts
|
|
55784
|
-
*/
|
|
55785
55807
|
const getHealthAndSafetyDistributionData = activityData => {
|
|
55786
55808
|
// Define health and safety indicator fields
|
|
55787
55809
|
const indicators = [{
|
|
@@ -55817,53 +55839,26 @@ const getHealthAndSafetyDistributionData = activityData => {
|
|
|
55817
55839
|
});
|
|
55818
55840
|
return distribution;
|
|
55819
55841
|
};
|
|
55820
|
-
|
|
55821
|
-
/**
|
|
55822
|
-
* Checks if the health and safety distribution data is empty
|
|
55823
|
-
* @param {Object} healthAndSafetyDistributionData - Distribution object
|
|
55824
|
-
* @returns {boolean} True if all values are 0 or empty
|
|
55825
|
-
*/
|
|
55826
55842
|
const isHealthAndSafetyDistributionEmpty = healthAndSafetyDistributionData => {
|
|
55827
55843
|
return Object.values(healthAndSafetyDistributionData).every(val => !val || val === 0);
|
|
55828
55844
|
};
|
|
55829
|
-
|
|
55830
|
-
|
|
55831
|
-
* Calculates pie chart data from health and safety distribution
|
|
55832
|
-
* @param {Object} healthAndSafetyDistributionData - Distribution object
|
|
55833
|
-
* @param {Function} t - Translation function
|
|
55834
|
-
* @returns {Array} Array of pie chart data points with value, percent, color, label, and key
|
|
55835
|
-
*/
|
|
55836
|
-
const calculateHealthAndSafetyPieData = (healthAndSafetyDistributionData, t) => {
|
|
55837
|
-
const total = Object.values(healthAndSafetyDistributionData).reduce((all, val) => all + (val || 0), 0);
|
|
55845
|
+
const calculateHealthAndSafetyPieData = (data, t, selectedField) => {
|
|
55846
|
+
const total = Object.values(data).reduce((a, v) => a + (v || 0), 0);
|
|
55838
55847
|
const labels = {
|
|
55839
55848
|
compliant: t("Available"),
|
|
55840
55849
|
notCompliant: t("Not available"),
|
|
55841
55850
|
empty: t("Not answered")
|
|
55842
55851
|
};
|
|
55843
|
-
return Object.keys(
|
|
55844
|
-
|
|
55845
|
-
|
|
55846
|
-
|
|
55847
|
-
|
|
55848
|
-
|
|
55849
|
-
|
|
55850
|
-
|
|
55851
|
-
};
|
|
55852
|
-
});
|
|
55852
|
+
return Object.keys(data).map(key => ({
|
|
55853
|
+
value: data[key] || 0,
|
|
55854
|
+
percent: total > 0 ? (data[key] || 0) / total : 0,
|
|
55855
|
+
color: HEALTH_SAFETY_COLORS[key] || '#D9D9D9',
|
|
55856
|
+
label: labels[key] || key,
|
|
55857
|
+
key,
|
|
55858
|
+
keyOfField: selectedField // <-- ADD THIS
|
|
55859
|
+
}));
|
|
55853
55860
|
};
|
|
55854
|
-
|
|
55855
|
-
/**
|
|
55856
|
-
* Generates tooltip content for health and safety pie chart
|
|
55857
|
-
* Shows all statuses with their percentages
|
|
55858
|
-
* @param {Object} item - The pie chart item being hovered (not used, but kept for compatibility)
|
|
55859
|
-
* @param {boolean} isEmpty - Whether the distribution is empty
|
|
55860
|
-
* @param {Object} healthAndSafetyDistributionData - Distribution object
|
|
55861
|
-
* @param {Function} t - Translation function
|
|
55862
|
-
* @param {Function} renderTooltipJsx - Function to render tooltip JSX
|
|
55863
|
-
* @param {string} tooltipTitle - Title to display in the tooltip (defaults to "Health and Safety")
|
|
55864
|
-
* @returns {JSX.Element|null} Tooltip content or null
|
|
55865
|
-
*/
|
|
55866
|
-
const getHealthAndSafetyTooltipChildren = (item, isEmpty, healthAndSafetyDistributionData, t, renderTooltipJsx, tooltipTitle = "Health and Safety") => {
|
|
55861
|
+
const getHealthAndSafetyTooltipChildren = (item, isEmpty, healthAndSafetyDistributionData, t, renderTooltipJsx, tooltipTitle = "Health and Safety", selectedField) => {
|
|
55867
55862
|
// If empty or no data, return null to display nothing
|
|
55868
55863
|
if (isEmpty || !Object.keys(healthAndSafetyDistributionData).length) {
|
|
55869
55864
|
return null;
|
|
@@ -55876,10 +55871,10 @@ const getHealthAndSafetyTooltipChildren = (item, isEmpty, healthAndSafetyDistrib
|
|
|
55876
55871
|
if (total === 0) {
|
|
55877
55872
|
return null;
|
|
55878
55873
|
}
|
|
55879
|
-
const labels = {
|
|
55874
|
+
const labels = FIELD_TOOLTIP_LABELS[item?.keyOfField] || {
|
|
55880
55875
|
compliant: t("Available"),
|
|
55881
55876
|
notCompliant: t("Not available"),
|
|
55882
|
-
empty: t("
|
|
55877
|
+
empty: t("No data")
|
|
55883
55878
|
};
|
|
55884
55879
|
|
|
55885
55880
|
// Filter items with values > 0
|
|
@@ -55962,7 +55957,6 @@ const HealthAndSafety = ({
|
|
|
55962
55957
|
getData: customGetData
|
|
55963
55958
|
});
|
|
55964
55959
|
|
|
55965
|
-
// Process the fetched pie chart data
|
|
55966
55960
|
// The API returns data in format: [{count: 1, [field]: "null"}, {count: 1, [field]: "no"}, {count: 1, [field]: "yes"}]
|
|
55967
55961
|
const healthAndSafetyDistributionData = React.useMemo(() => {
|
|
55968
55962
|
if (!pieChartData) return {
|
|
@@ -56003,7 +55997,7 @@ const HealthAndSafety = ({
|
|
|
56003
55997
|
return getHealthAndSafetyDistributionData(pieChartData);
|
|
56004
55998
|
}, [pieChartData, selectedField]);
|
|
56005
55999
|
const isEmpty = React.useMemo(() => isHealthAndSafetyDistributionEmpty(healthAndSafetyDistributionData), [healthAndSafetyDistributionData]);
|
|
56006
|
-
const pieData = React.useMemo(() => calculateHealthAndSafetyPieData(healthAndSafetyDistributionData, t), [healthAndSafetyDistributionData, t]);
|
|
56000
|
+
const pieData = React.useMemo(() => calculateHealthAndSafetyPieData(healthAndSafetyDistributionData, t, selectedField), [healthAndSafetyDistributionData, t, selectedField]);
|
|
56007
56001
|
|
|
56008
56002
|
// Get the label for the selected field to use as tooltip title
|
|
56009
56003
|
const selectedFieldLabel = React.useMemo(() => {
|
|
@@ -56017,9 +56011,10 @@ const HealthAndSafety = ({
|
|
|
56017
56011
|
return /*#__PURE__*/jsxRuntime.jsx(Widget, {
|
|
56018
56012
|
loading: loading || pieChartLoading,
|
|
56019
56013
|
title: /*#__PURE__*/jsxRuntime.jsx("div", {
|
|
56020
|
-
children: t("Health
|
|
56014
|
+
children: t("Operational Health & Safety")
|
|
56021
56015
|
}),
|
|
56022
|
-
className: "with-border-header h-w-btn-header
|
|
56016
|
+
className: "with-border-header h-w-btn-header",
|
|
56017
|
+
description: t("Across all activities in this cycle."),
|
|
56023
56018
|
addedHeader: /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
56024
56019
|
children: [/*#__PURE__*/jsxRuntime.jsx("div", {
|
|
56025
56020
|
className: "flex-1"
|
|
@@ -56338,17 +56333,41 @@ const JobsTimeline = ({
|
|
|
56338
56333
|
defaultFilter: 'monthly'
|
|
56339
56334
|
});
|
|
56340
56335
|
const jobsData = Array.isArray(dayJobsTimeline) ? dayJobsTimeline : dayJobsTimeline?.jobsTimeline || dayJobsTimeline?.jobs || dayJobsTimeline?.timeline || [];
|
|
56336
|
+
|
|
56337
|
+
// const jobsTimelineData = useMemo(() => {
|
|
56338
|
+
// // Always process data, even if empty, to generate default date range for x-axis
|
|
56339
|
+
// const dataToProcess = (!jobsData || !Array.isArray(jobsData) || jobsData.length === 0)
|
|
56340
|
+
// ? []
|
|
56341
|
+
// : jobsData;
|
|
56342
|
+
|
|
56343
|
+
// // Process data without cumulative calculation (for jobs timeline)
|
|
56344
|
+
// // Try to find value in total, count, jobs, or value fields
|
|
56345
|
+
// return processChartDateData({
|
|
56346
|
+
// mainData: dataToProcess,
|
|
56347
|
+
// isCumulative: false,
|
|
56348
|
+
// valueField: 'total', // Will fallback to count/jobs/value if total doesn't exist
|
|
56349
|
+
// });
|
|
56350
|
+
// }, [jobsData, processChartDateData]);
|
|
56351
|
+
|
|
56341
56352
|
const jobsTimelineData = React.useMemo(() => {
|
|
56342
|
-
//
|
|
56353
|
+
// Prepare data first
|
|
56343
56354
|
const dataToProcess = !jobsData || !Array.isArray(jobsData) || jobsData.length === 0 ? [] : jobsData;
|
|
56344
56355
|
|
|
56345
|
-
// Process data without cumulative calculation
|
|
56346
|
-
|
|
56347
|
-
return processChartDateData({
|
|
56356
|
+
// Process data without cumulative calculation
|
|
56357
|
+
const processedData = processChartDateData({
|
|
56348
56358
|
mainData: dataToProcess,
|
|
56349
56359
|
isCumulative: false,
|
|
56350
|
-
valueField: 'total' //
|
|
56360
|
+
valueField: 'total' // fallback handled inside processChartDateData
|
|
56351
56361
|
});
|
|
56362
|
+
|
|
56363
|
+
// Find last index with jobs > 0
|
|
56364
|
+
let lastNonZeroIndex = processedData.length - 1;
|
|
56365
|
+
while (lastNonZeroIndex >= 0 && (processedData[lastNonZeroIndex].jobs || 0) === 0) {
|
|
56366
|
+
lastNonZeroIndex--;
|
|
56367
|
+
}
|
|
56368
|
+
|
|
56369
|
+
// Slice up to last period with data
|
|
56370
|
+
return processedData.slice(0, lastNonZeroIndex + 1);
|
|
56352
56371
|
}, [jobsData, processChartDateData]);
|
|
56353
56372
|
const maxYValue = React.useMemo(() => {
|
|
56354
56373
|
if (!jobsTimelineData || jobsTimelineData.length === 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
|
@@ -20,21 +20,44 @@ const JobsTimeline = ({
|
|
|
20
20
|
? dayJobsTimeline
|
|
21
21
|
: (dayJobsTimeline?.jobsTimeline || dayJobsTimeline?.jobs || dayJobsTimeline?.timeline || []);
|
|
22
22
|
|
|
23
|
+
// const jobsTimelineData = useMemo(() => {
|
|
24
|
+
// // Always process data, even if empty, to generate default date range for x-axis
|
|
25
|
+
// const dataToProcess = (!jobsData || !Array.isArray(jobsData) || jobsData.length === 0)
|
|
26
|
+
// ? []
|
|
27
|
+
// : jobsData;
|
|
28
|
+
|
|
29
|
+
// // Process data without cumulative calculation (for jobs timeline)
|
|
30
|
+
// // Try to find value in total, count, jobs, or value fields
|
|
31
|
+
// return processChartDateData({
|
|
32
|
+
// mainData: dataToProcess,
|
|
33
|
+
// isCumulative: false,
|
|
34
|
+
// valueField: 'total', // Will fallback to count/jobs/value if total doesn't exist
|
|
35
|
+
// });
|
|
36
|
+
// }, [jobsData, processChartDateData]);
|
|
37
|
+
|
|
23
38
|
const jobsTimelineData = useMemo(() => {
|
|
24
|
-
//
|
|
25
|
-
const dataToProcess = (!jobsData || !Array.isArray(jobsData) || jobsData.length === 0)
|
|
26
|
-
? []
|
|
39
|
+
// Prepare data first
|
|
40
|
+
const dataToProcess = (!jobsData || !Array.isArray(jobsData) || jobsData.length === 0)
|
|
41
|
+
? []
|
|
27
42
|
: jobsData;
|
|
28
|
-
|
|
29
|
-
// Process data without cumulative calculation
|
|
30
|
-
|
|
31
|
-
return processChartDateData({
|
|
43
|
+
|
|
44
|
+
// Process data without cumulative calculation
|
|
45
|
+
const processedData = processChartDateData({
|
|
32
46
|
mainData: dataToProcess,
|
|
33
47
|
isCumulative: false,
|
|
34
|
-
valueField: 'total', //
|
|
48
|
+
valueField: 'total', // fallback handled inside processChartDateData
|
|
35
49
|
});
|
|
50
|
+
|
|
51
|
+
// Find last index with jobs > 0
|
|
52
|
+
let lastNonZeroIndex = processedData.length - 1;
|
|
53
|
+
while (lastNonZeroIndex >= 0 && (processedData[lastNonZeroIndex].jobs || 0) === 0) {
|
|
54
|
+
lastNonZeroIndex--;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Slice up to last period with data
|
|
58
|
+
return processedData.slice(0, lastNonZeroIndex + 1);
|
|
36
59
|
}, [jobsData, processChartDateData]);
|
|
37
|
-
|
|
60
|
+
|
|
38
61
|
const maxYValue = useMemo(() => {
|
|
39
62
|
if (!jobsTimelineData || jobsTimelineData.length === 0) {
|
|
40
63
|
return 100;
|