datastake-daf 0.6.766 → 0.6.767
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 +174 -106
- package/dist/pages/index.js +102 -31
- package/dist/utils/index.js +16 -1
- package/package.json +4 -1
- package/src/@daf/core/components/Dashboard/Map/ChainIcon/Markers/StakeholderMarker.js +1 -1
- package/src/@daf/core/components/Dashboard/Map/ChainIcon/index.js +1 -2
- package/src/@daf/core/components/Dashboard/Map/StakeholderIcon/index.js +3 -0
- package/src/@daf/core/components/Dashboard/Map/hook.js +31 -1
- package/src/@daf/core/components/Graphs/TradeRelationship/index.jsx +49 -11
- package/src/@daf/core/components/Graphs/components/BaseGraph.jsx +8 -4
- package/src/@daf/core/components/Screens/TableScreen/TableWithTabsAndCreate/create.jsx +106 -0
- package/src/@daf/core/components/Screens/TableScreen/TableWithTabsAndCreate/index.jsx +115 -0
- package/src/@daf/hooks/useMapHelper.js +5 -0
- package/src/@daf/pages/Dashboards/SupplyChain/components/SupplyChainMap/index.js +5 -2
- package/src/@daf/pages/Events/helper.js +0 -1
- package/src/@daf/pages/Locations/MineSite/columns.js +1 -1
- package/src/@daf/pages/Summary/Operator/components/TradeRelationships/index.js +5 -1
- package/src/constants/locales/en/translation.js +5 -0
- package/src/constants/locales/fr/translation.js +5 -0
package/dist/pages/index.js
CHANGED
|
@@ -7934,7 +7934,12 @@ const defaultMapConfig = {
|
|
|
7934
7934
|
maxZoom: 18,
|
|
7935
7935
|
preferCanvas: true,
|
|
7936
7936
|
zoomControl: false,
|
|
7937
|
-
maxBounds: maxBounds
|
|
7937
|
+
maxBounds: maxBounds,
|
|
7938
|
+
zoomSnap: 0.5,
|
|
7939
|
+
zoomDelta: 0.5,
|
|
7940
|
+
wheelPxPerZoomLevel: 150,
|
|
7941
|
+
zoomAnimation: true,
|
|
7942
|
+
zoomAnimationThreshold: 10
|
|
7938
7943
|
};
|
|
7939
7944
|
const filterValidGPS = data => {
|
|
7940
7945
|
const latCheck = lat => lat > -90 || lat < 90;
|
|
@@ -8809,7 +8814,7 @@ function StakeholderIcon$1({
|
|
|
8809
8814
|
onClickLink(data);
|
|
8810
8815
|
}
|
|
8811
8816
|
}),
|
|
8812
|
-
getPopupContainer: () => document.getElementById(
|
|
8817
|
+
getPopupContainer: () => document.getElementById("map"),
|
|
8813
8818
|
children: /*#__PURE__*/jsxRuntime.jsx(StakeholderMarker, {
|
|
8814
8819
|
className: `${data.type} ${isSelected ? "selected" : selectedMarkersId.length > 0 ? "unselected" : ""}
|
|
8815
8820
|
${isSmall ? "small" : isMedium ? "medium" : "large"}
|
|
@@ -9012,8 +9017,7 @@ function LocationIcon({
|
|
|
9012
9017
|
// isHovering
|
|
9013
9018
|
// }
|
|
9014
9019
|
,
|
|
9015
|
-
|
|
9016
|
-
getPopupContainer: () => document.getElementById(i),
|
|
9020
|
+
getPopupContainer: () => document.getElementById("map"),
|
|
9017
9021
|
children: /*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
9018
9022
|
style: {
|
|
9019
9023
|
position: "relative",
|
|
@@ -9114,6 +9118,7 @@ function StakeholderIcon({
|
|
|
9114
9118
|
link,
|
|
9115
9119
|
onClickLink: () => onClickLink(marker)
|
|
9116
9120
|
}),
|
|
9121
|
+
getPopupContainer: () => document.getElementById("map"),
|
|
9117
9122
|
children: /*#__PURE__*/jsxRuntime.jsx("div", {
|
|
9118
9123
|
style: {
|
|
9119
9124
|
position: "absolute",
|
|
@@ -9155,6 +9160,7 @@ function StakeholderIcon({
|
|
|
9155
9160
|
link,
|
|
9156
9161
|
onClickLink: () => onClickLink(marker)
|
|
9157
9162
|
}),
|
|
9163
|
+
getPopupContainer: () => document.getElementById("map"),
|
|
9158
9164
|
children: /*#__PURE__*/jsxRuntime.jsx("div", {
|
|
9159
9165
|
style: {
|
|
9160
9166
|
position: "absolute",
|
|
@@ -9190,6 +9196,7 @@ function StakeholderIcon({
|
|
|
9190
9196
|
link,
|
|
9191
9197
|
onClickLink: () => onClickLink(marker)
|
|
9192
9198
|
}),
|
|
9199
|
+
getPopupContainer: () => document.getElementById("map"),
|
|
9193
9200
|
children: /*#__PURE__*/jsxRuntime.jsx(Style$c
|
|
9194
9201
|
// onClick={toggleOpen}
|
|
9195
9202
|
, {
|
|
@@ -9913,7 +9920,13 @@ const useMap = ({
|
|
|
9913
9920
|
if (mapRef) {
|
|
9914
9921
|
L__namespace.control.scale().addTo(mapRef);
|
|
9915
9922
|
L__namespace.tileLayer(TILE_LAYER_URL, {
|
|
9916
|
-
access_token: MAP_TOKEN
|
|
9923
|
+
access_token: MAP_TOKEN,
|
|
9924
|
+
keepBuffer: 4,
|
|
9925
|
+
updateWhenZooming: false,
|
|
9926
|
+
updateInterval: 200,
|
|
9927
|
+
maxNativeZoom: 18,
|
|
9928
|
+
tileSize: 256,
|
|
9929
|
+
fadeAnimation: true
|
|
9917
9930
|
}).addTo(mapRef);
|
|
9918
9931
|
}
|
|
9919
9932
|
}, [mapRef]);
|
|
@@ -9977,6 +9990,23 @@ const useMap = ({
|
|
|
9977
9990
|
mapRef.setView([marker.coordinates[0], marker.coordinates[1]], getZoom(mapRef));
|
|
9978
9991
|
}
|
|
9979
9992
|
}, [activeMarker, mapRef]);
|
|
9993
|
+
React.useEffect(() => {
|
|
9994
|
+
if (mapRef && type === "chain") {
|
|
9995
|
+
const handleMapClick = e => {
|
|
9996
|
+
const clickedElement = e.originalEvent.target;
|
|
9997
|
+
const isMarkerClick = clickedElement.closest('.marker-chain') || clickedElement.closest('.leaflet-marker-icon');
|
|
9998
|
+
if (!isMarkerClick && selectedMarkersId.length > 0) {
|
|
9999
|
+
setSelectedMarkersId([]);
|
|
10000
|
+
openPopupIdRef.current = null;
|
|
10001
|
+
setMarkerWithPopup(null);
|
|
10002
|
+
}
|
|
10003
|
+
};
|
|
10004
|
+
mapRef.on('click', handleMapClick);
|
|
10005
|
+
return () => {
|
|
10006
|
+
mapRef.off('click', handleMapClick);
|
|
10007
|
+
};
|
|
10008
|
+
}
|
|
10009
|
+
}, [mapRef, type, selectedMarkersId]);
|
|
9980
10010
|
return {
|
|
9981
10011
|
container,
|
|
9982
10012
|
activeMarker,
|
|
@@ -10469,6 +10499,7 @@ function SupplyChainMap({
|
|
|
10469
10499
|
} = useWidgetFetch({
|
|
10470
10500
|
config: defaultConfig
|
|
10471
10501
|
});
|
|
10502
|
+
console.log('data', data);
|
|
10472
10503
|
return /*#__PURE__*/jsxRuntime.jsx(Widget, {
|
|
10473
10504
|
title: t("Supply Chain Map"),
|
|
10474
10505
|
loading: loading,
|
|
@@ -10478,11 +10509,11 @@ function SupplyChainMap({
|
|
|
10478
10509
|
data: Array.isArray(data) && data.length > 0 ? data : [],
|
|
10479
10510
|
renderTooltip: data => {
|
|
10480
10511
|
const productsText = data?.products?.[0];
|
|
10481
|
-
const minerals = options?.
|
|
10512
|
+
const minerals = options?.mineralOptions || [];
|
|
10482
10513
|
const participants = data?.stakeholders?.map(stakeholder => stakeholder.name);
|
|
10483
10514
|
return [{
|
|
10484
10515
|
label: t("Products"),
|
|
10485
|
-
value:
|
|
10516
|
+
value: findOptions(productsText, minerals) || productsText || "-",
|
|
10486
10517
|
...(productsText && {
|
|
10487
10518
|
tag: getTagColor(productsText)
|
|
10488
10519
|
})
|
|
@@ -11639,17 +11670,23 @@ const BaseGraph = /*#__PURE__*/React.forwardRef(function BaseGraph({
|
|
|
11639
11670
|
}
|
|
11640
11671
|
return result;
|
|
11641
11672
|
}, [nodes.length, mandatoryNodesToFit?.length, mandatoryNodesToFit]);
|
|
11673
|
+
|
|
11674
|
+
// In BaseGraph.jsx, replace the useEffect with:
|
|
11642
11675
|
React.useEffect(() => {
|
|
11643
11676
|
if (nodesToFit.length === 0) return;
|
|
11644
|
-
|
|
11677
|
+
|
|
11678
|
+
// Use setTimeout instead of requestAnimationFrame to ensure nodes are rendered
|
|
11679
|
+
const timer = setTimeout(() => {
|
|
11645
11680
|
fitView({
|
|
11646
11681
|
padding: 0.4,
|
|
11647
11682
|
nodes: [...nodesToFit],
|
|
11648
11683
|
// duration: withDuration ? 300 : undefined,
|
|
11649
11684
|
maxZoom: 0.9
|
|
11650
11685
|
});
|
|
11651
|
-
});
|
|
11652
|
-
|
|
11686
|
+
}, 100); // Small delay to ensure nodes are rendered
|
|
11687
|
+
|
|
11688
|
+
return () => clearTimeout(timer);
|
|
11689
|
+
}, [nodesToFit.length, nodesToFit.map(n => `${n.id}-${n.width}-${n.height}`).join(','), withDuration]);
|
|
11653
11690
|
return /*#__PURE__*/jsxRuntime.jsx(ComponentWithFocus, {
|
|
11654
11691
|
children: /*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
11655
11692
|
style: {
|
|
@@ -11678,8 +11715,9 @@ const BaseGraph = /*#__PURE__*/React.forwardRef(function BaseGraph({
|
|
|
11678
11715
|
fitView: true // zoom out on default
|
|
11679
11716
|
,
|
|
11680
11717
|
fitViewOptions: {
|
|
11681
|
-
padding: 0.2
|
|
11682
|
-
//
|
|
11718
|
+
padding: 0.2,
|
|
11719
|
+
//zoom out on default
|
|
11720
|
+
duration: withDuration ? 300 : undefined
|
|
11683
11721
|
},
|
|
11684
11722
|
...props,
|
|
11685
11723
|
children: !isPdf && /*#__PURE__*/jsxRuntime.jsxs(react.Controls, {
|
|
@@ -32912,10 +32950,6 @@ const WorkersTable = ({
|
|
|
32912
32950
|
};
|
|
32913
32951
|
|
|
32914
32952
|
const getEventCategoryBySubject = (eventCategoryObject, subject, isSingular = false) => {
|
|
32915
|
-
console.log({
|
|
32916
|
-
eventCategoryObject,
|
|
32917
|
-
subject
|
|
32918
|
-
});
|
|
32919
32953
|
if (!eventCategoryObject || typeof eventCategoryObject !== 'object') {
|
|
32920
32954
|
return null;
|
|
32921
32955
|
}
|
|
@@ -34363,7 +34397,7 @@ const getColumns$2 = ({
|
|
|
34363
34397
|
className: "daf-default-cell"
|
|
34364
34398
|
});
|
|
34365
34399
|
}
|
|
34366
|
-
const operators = all?.operator?.map(operator => operator?.
|
|
34400
|
+
const operators = all?.operator?.map(operator => operator?.locationClient?.name)?.filter(Boolean);
|
|
34367
34401
|
return operators && operators.length > 0 ? /*#__PURE__*/jsxRuntime.jsx(MoreOptions, {
|
|
34368
34402
|
data: operators || [],
|
|
34369
34403
|
toolTipPlacement: operators?.length < 2 ? "topLeft" : "top"
|
|
@@ -37557,7 +37591,8 @@ function TradeRelationship({
|
|
|
37557
37591
|
filtersConfig,
|
|
37558
37592
|
onFilterChange = () => {},
|
|
37559
37593
|
renderTooltipItems = () => [],
|
|
37560
|
-
getTotal = () => 0
|
|
37594
|
+
getTotal = () => 0,
|
|
37595
|
+
onRenderComplete = () => {}
|
|
37561
37596
|
}) {
|
|
37562
37597
|
const reactFlowWrapper = React.useRef(null);
|
|
37563
37598
|
const [nodes, setNodes] = react.useNodesState([]);
|
|
@@ -37570,6 +37605,23 @@ function TradeRelationship({
|
|
|
37570
37605
|
const [activeNode, setActiveNode] = React.useState(null);
|
|
37571
37606
|
// const [initCenter, setInitCenter] = useState(true);
|
|
37572
37607
|
const [associatedNodes, setAssociatedNodes] = React.useState(null);
|
|
37608
|
+
const isFullyRenderedRef = React.useRef(false);
|
|
37609
|
+
const [isFullyRendered, setIsFullyRendered] = React.useState(false);
|
|
37610
|
+
React.useEffect(() => {
|
|
37611
|
+
isFullyRenderedRef.current = false;
|
|
37612
|
+
setIsFullyRendered(false);
|
|
37613
|
+
setActiveNode(null);
|
|
37614
|
+
}, [data]);
|
|
37615
|
+
React.useEffect(() => {
|
|
37616
|
+
if (nodes.length > 0 && edges.length > 0 && !isFullyRenderedRef.current) {
|
|
37617
|
+
const timeoutId = setTimeout(() => {
|
|
37618
|
+
isFullyRenderedRef.current = true;
|
|
37619
|
+
setIsFullyRendered(true);
|
|
37620
|
+
onRenderComplete(true);
|
|
37621
|
+
}, 200);
|
|
37622
|
+
return () => clearTimeout(timeoutId);
|
|
37623
|
+
}
|
|
37624
|
+
}, [nodes.length, edges.length, associatedNodes]);
|
|
37573
37625
|
React.useEffect(() => {
|
|
37574
37626
|
setActiveNode(null);
|
|
37575
37627
|
}, [data]);
|
|
@@ -37609,7 +37661,7 @@ function TradeRelationship({
|
|
|
37609
37661
|
return;
|
|
37610
37662
|
}
|
|
37611
37663
|
const _nodes = [{
|
|
37612
|
-
id: data.id,
|
|
37664
|
+
id: data.id?.toString(),
|
|
37613
37665
|
type: "expandedNode",
|
|
37614
37666
|
position: {
|
|
37615
37667
|
x: xInit,
|
|
@@ -37621,10 +37673,10 @@ function TradeRelationship({
|
|
|
37621
37673
|
if (isBilateral) {
|
|
37622
37674
|
(data.sources || []).forEach(source => {
|
|
37623
37675
|
const hasPrev = false;
|
|
37624
|
-
|
|
37676
|
+
const edge = {
|
|
37625
37677
|
id: `e-${data.id}-${source}`,
|
|
37626
|
-
source: source,
|
|
37627
|
-
type: "
|
|
37678
|
+
source: source?.toString(),
|
|
37679
|
+
type: "defaultEdge",
|
|
37628
37680
|
target: data?.id?.toString(),
|
|
37629
37681
|
sourceHandle: "left",
|
|
37630
37682
|
targetHandle: "right",
|
|
@@ -37638,7 +37690,8 @@ function TradeRelationship({
|
|
|
37638
37690
|
tooltipTitle,
|
|
37639
37691
|
moreLeft: false
|
|
37640
37692
|
}
|
|
37641
|
-
}
|
|
37693
|
+
};
|
|
37694
|
+
_edges.push(edge);
|
|
37642
37695
|
});
|
|
37643
37696
|
}
|
|
37644
37697
|
const mapChildren = ({
|
|
@@ -37679,7 +37732,7 @@ function TradeRelationship({
|
|
|
37679
37732
|
(ch.sources || []).forEach(source => {
|
|
37680
37733
|
const hasPrev = _prevNodes.find(p => p.id === source);
|
|
37681
37734
|
const isCustom = !hasPrev ? true : prevChildren.includes(source) ? false : true;
|
|
37682
|
-
|
|
37735
|
+
const edge = {
|
|
37683
37736
|
id: `e-${ch.id}-${source}`,
|
|
37684
37737
|
source: hasPrev ? source : ch?.id?.toString(),
|
|
37685
37738
|
type: isCustom ? "verticalPath" : "defaultEdge",
|
|
@@ -37697,7 +37750,8 @@ function TradeRelationship({
|
|
|
37697
37750
|
tooltipTitle,
|
|
37698
37751
|
moreLeft: prevChildren.length > children.length
|
|
37699
37752
|
}
|
|
37700
|
-
}
|
|
37753
|
+
};
|
|
37754
|
+
_edges.push(edge);
|
|
37701
37755
|
if (isCustom) {
|
|
37702
37756
|
customIndex += 1;
|
|
37703
37757
|
}
|
|
@@ -37736,11 +37790,24 @@ function TradeRelationship({
|
|
|
37736
37790
|
prevChildren: !isBilateral ? [data.id] : [],
|
|
37737
37791
|
maxHeight: 0
|
|
37738
37792
|
});
|
|
37793
|
+
|
|
37794
|
+
// Check for potential ID mismatches
|
|
37795
|
+
const nodeIds = _nodes.map(n => n.id);
|
|
37796
|
+
_edges.filter(e => {
|
|
37797
|
+
const sourceExists = nodeIds.includes(e.source);
|
|
37798
|
+
const targetExists = nodeIds.includes(e.target);
|
|
37799
|
+
return !sourceExists || !targetExists;
|
|
37800
|
+
});
|
|
37801
|
+
|
|
37802
|
+
// Set nodes first
|
|
37739
37803
|
setNodes(_nodes);
|
|
37740
|
-
|
|
37741
|
-
|
|
37804
|
+
const timeoutId = setTimeout(() => {
|
|
37805
|
+
setEdges(_edges);
|
|
37806
|
+
}, 100); // 100ms is imperceptible to users but ensures React Flow is ready
|
|
37742
37807
|
|
|
37743
|
-
|
|
37808
|
+
// Cleanup to prevent memory leaks if component unmounts quickly
|
|
37809
|
+
return () => clearTimeout(timeoutId);
|
|
37810
|
+
}, [data, activeNode]);
|
|
37744
37811
|
React.useEffect(() => {
|
|
37745
37812
|
if (activeNode) {
|
|
37746
37813
|
let _associatedNodesRight = [activeNode];
|
|
@@ -37806,7 +37873,7 @@ function TradeRelationship({
|
|
|
37806
37873
|
});
|
|
37807
37874
|
},
|
|
37808
37875
|
ref: reactFlowWrapper
|
|
37809
|
-
});
|
|
37876
|
+
}, JSON.stringify(nodes) + JSON.stringify(edges));
|
|
37810
37877
|
}
|
|
37811
37878
|
var TradeRelationship$1 = withProvider(TradeRelationship);
|
|
37812
37879
|
|
|
@@ -37821,6 +37888,7 @@ const TradeRelationships = ({
|
|
|
37821
37888
|
APP
|
|
37822
37889
|
}) => {
|
|
37823
37890
|
const [filters, setFilters] = React.useState({});
|
|
37891
|
+
const [isFullyRendered, setIsFullyRendered] = React.useState(true);
|
|
37824
37892
|
const onFilterChange = filters => {
|
|
37825
37893
|
setFilters(p => ({
|
|
37826
37894
|
...p,
|
|
@@ -37869,7 +37937,7 @@ const TradeRelationships = ({
|
|
|
37869
37937
|
return /*#__PURE__*/jsxRuntime.jsx(Widget, {
|
|
37870
37938
|
title: t("Trade Relationships"),
|
|
37871
37939
|
className: "flex flex-1 with-border-header no-p-body",
|
|
37872
|
-
loading: loading,
|
|
37940
|
+
loading: loading || isFullyRendered,
|
|
37873
37941
|
children: /*#__PURE__*/jsxRuntime.jsx("div", {
|
|
37874
37942
|
className: "flex flex-1 flex-column justify-content-center",
|
|
37875
37943
|
children: /*#__PURE__*/jsxRuntime.jsx("div", {
|
|
@@ -37892,7 +37960,10 @@ const TradeRelationships = ({
|
|
|
37892
37960
|
minZoom: 0.4,
|
|
37893
37961
|
tooltipTitle: "Trade",
|
|
37894
37962
|
filtersConfig: filterConfig,
|
|
37895
|
-
onFilterChange: onFilterChange
|
|
37963
|
+
onFilterChange: onFilterChange,
|
|
37964
|
+
onRenderComplete: data => {
|
|
37965
|
+
setIsFullyRendered(!data);
|
|
37966
|
+
}
|
|
37896
37967
|
})
|
|
37897
37968
|
})
|
|
37898
37969
|
})
|
package/dist/utils/index.js
CHANGED
|
@@ -7085,7 +7085,12 @@ const defaultMapConfig = {
|
|
|
7085
7085
|
maxZoom: 18,
|
|
7086
7086
|
preferCanvas: true,
|
|
7087
7087
|
zoomControl: false,
|
|
7088
|
-
maxBounds: maxBounds
|
|
7088
|
+
maxBounds: maxBounds,
|
|
7089
|
+
zoomSnap: 0.5,
|
|
7090
|
+
zoomDelta: 0.5,
|
|
7091
|
+
wheelPxPerZoomLevel: 150,
|
|
7092
|
+
zoomAnimation: true,
|
|
7093
|
+
zoomAnimationThreshold: 10
|
|
7089
7094
|
};
|
|
7090
7095
|
|
|
7091
7096
|
styled__default["default"].div`
|
|
@@ -7724,6 +7729,11 @@ function getRedirectPath(user, fallback = '', app, isDatastake) {
|
|
|
7724
7729
|
}
|
|
7725
7730
|
|
|
7726
7731
|
const en = {
|
|
7732
|
+
"accounts": "Accounts",
|
|
7733
|
+
"users": "Users",
|
|
7734
|
+
"subjects": "Subjects",
|
|
7735
|
+
"active-users": "Active Users",
|
|
7736
|
+
"total-data-points": "Total Data Points",
|
|
7727
7737
|
"Identified Customers": "Identified Customers",
|
|
7728
7738
|
"Identified Suppliers": "Identified Suppliers",
|
|
7729
7739
|
"Associated Mine Sites": "Associated Mine Sites",
|
|
@@ -9037,6 +9047,11 @@ const en = {
|
|
|
9037
9047
|
};
|
|
9038
9048
|
|
|
9039
9049
|
const fr = {
|
|
9050
|
+
"accounts": "Comptes",
|
|
9051
|
+
"users": "Utilisateurs",
|
|
9052
|
+
"subjects": "Sujets",
|
|
9053
|
+
"active-users": "Utilisateurs Actifs",
|
|
9054
|
+
"total-data-points": "Total Points de Données",
|
|
9040
9055
|
"Identified Customers": "Clients identifiés",
|
|
9041
9056
|
"Identified Suppliers": "Fournisseurs identifiés",
|
|
9042
9057
|
"Associated Mine Sites": "Sites miniers associés",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "datastake-daf",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.767",
|
|
4
4
|
"dependencies": {
|
|
5
5
|
"@ant-design/icons": "^5.2.5",
|
|
6
6
|
"@antv/g2": "^5.1.1",
|
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
"buffer": "^6.0.3",
|
|
16
16
|
"countries-list": "^2.6.1",
|
|
17
17
|
"country-city-location": "^1.0.13",
|
|
18
|
+
"d3-selection": "^3.0.0",
|
|
19
|
+
"d3-transition": "^3.0.1",
|
|
20
|
+
"d3-zoom": "^3.0.0",
|
|
18
21
|
"dayjs": "^1.11.12",
|
|
19
22
|
"deepmerge": "^4.3.1",
|
|
20
23
|
"docx": "^9.5.1",
|
|
@@ -234,7 +234,7 @@ export default function StakeholderIcon({
|
|
|
234
234
|
onClickLink(data);
|
|
235
235
|
},
|
|
236
236
|
})}
|
|
237
|
-
getPopupContainer={() => document.getElementById(
|
|
237
|
+
getPopupContainer={() => document.getElementById("map")}
|
|
238
238
|
>
|
|
239
239
|
<StakeholderMarker
|
|
240
240
|
className={`${data.type} ${
|
|
@@ -213,8 +213,7 @@ export default function LocationIcon({
|
|
|
213
213
|
// (!openPopupIdRef.current || openPopupIdRef.current === data.datastakeId) &&
|
|
214
214
|
// isHovering
|
|
215
215
|
// }
|
|
216
|
-
|
|
217
|
-
getPopupContainer={() => document.getElementById(i)}
|
|
216
|
+
getPopupContainer={() => document.getElementById("map")}
|
|
218
217
|
>
|
|
219
218
|
<div style={{ position: "relative", display: "inline-block" }}>
|
|
220
219
|
{(isSelected || selectedMarkersId.length === 0) && (
|
|
@@ -42,6 +42,7 @@ export default function StakeholderIcon({
|
|
|
42
42
|
link,
|
|
43
43
|
onClickLink: () => onClickLink(marker),
|
|
44
44
|
})}
|
|
45
|
+
getPopupContainer={() => document.getElementById("map")}
|
|
45
46
|
>
|
|
46
47
|
<div
|
|
47
48
|
key="single-marker"
|
|
@@ -91,6 +92,7 @@ export default function StakeholderIcon({
|
|
|
91
92
|
link,
|
|
92
93
|
onClickLink: () => onClickLink(marker),
|
|
93
94
|
})}
|
|
95
|
+
getPopupContainer={() => document.getElementById("map")}
|
|
94
96
|
>
|
|
95
97
|
<div
|
|
96
98
|
style={{
|
|
@@ -132,6 +134,7 @@ export default function StakeholderIcon({
|
|
|
132
134
|
link,
|
|
133
135
|
onClickLink: () => onClickLink(marker),
|
|
134
136
|
})}
|
|
137
|
+
getPopupContainer={() => document.getElementById("map")}
|
|
135
138
|
>
|
|
136
139
|
<Style
|
|
137
140
|
// onClick={toggleOpen}
|
|
@@ -283,7 +283,15 @@ export const useMap = ({
|
|
|
283
283
|
useEffect(() => {
|
|
284
284
|
if (mapRef) {
|
|
285
285
|
L.control.scale().addTo(mapRef);
|
|
286
|
-
L.tileLayer(TILE_LAYER_URL, {
|
|
286
|
+
L.tileLayer(TILE_LAYER_URL, {
|
|
287
|
+
access_token: MAP_TOKEN,
|
|
288
|
+
keepBuffer: 4,
|
|
289
|
+
updateWhenZooming: false,
|
|
290
|
+
updateInterval: 200,
|
|
291
|
+
maxNativeZoom: 18,
|
|
292
|
+
tileSize: 256,
|
|
293
|
+
fadeAnimation: true,
|
|
294
|
+
}).addTo(mapRef);
|
|
287
295
|
}
|
|
288
296
|
}, [mapRef]);
|
|
289
297
|
|
|
@@ -362,6 +370,28 @@ export const useMap = ({
|
|
|
362
370
|
}
|
|
363
371
|
}, [activeMarker, mapRef]);
|
|
364
372
|
|
|
373
|
+
useEffect(() => {
|
|
374
|
+
if (mapRef && type === "chain") {
|
|
375
|
+
const handleMapClick = (e) => {
|
|
376
|
+
const clickedElement = e.originalEvent.target;
|
|
377
|
+
const isMarkerClick = clickedElement.closest('.marker-chain') ||
|
|
378
|
+
clickedElement.closest('.leaflet-marker-icon');
|
|
379
|
+
|
|
380
|
+
if (!isMarkerClick && selectedMarkersId.length > 0) {
|
|
381
|
+
setSelectedMarkersId([]);
|
|
382
|
+
openPopupIdRef.current = null;
|
|
383
|
+
setMarkerWithPopup(null);
|
|
384
|
+
}
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
mapRef.on('click', handleMapClick);
|
|
388
|
+
|
|
389
|
+
return () => {
|
|
390
|
+
mapRef.off('click', handleMapClick);
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
}, [mapRef, type, selectedMarkersId]);
|
|
394
|
+
|
|
365
395
|
return {
|
|
366
396
|
container,
|
|
367
397
|
activeMarker,
|
|
@@ -21,6 +21,7 @@ function TradeRelationship({
|
|
|
21
21
|
onFilterChange = () => {},
|
|
22
22
|
renderTooltipItems = () => [],
|
|
23
23
|
getTotal = () => 0,
|
|
24
|
+
onRenderComplete = () => {},
|
|
24
25
|
}) {
|
|
25
26
|
const reactFlowWrapper = useRef(null);
|
|
26
27
|
const [nodes, setNodes] = useNodesState([]);
|
|
@@ -30,6 +31,27 @@ function TradeRelationship({
|
|
|
30
31
|
// const [initCenter, setInitCenter] = useState(true);
|
|
31
32
|
const [associatedNodes, setAssociatedNodes] = useState(null);
|
|
32
33
|
|
|
34
|
+
const isFullyRenderedRef = useRef(false);
|
|
35
|
+
const [isFullyRendered, setIsFullyRendered] = useState(false);
|
|
36
|
+
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
isFullyRenderedRef.current = false;
|
|
39
|
+
setIsFullyRendered(false);
|
|
40
|
+
setActiveNode(null);
|
|
41
|
+
}, [data]);
|
|
42
|
+
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
if (nodes.length > 0 && edges.length > 0 && !isFullyRenderedRef.current) {
|
|
45
|
+
const timeoutId = setTimeout(() => {
|
|
46
|
+
isFullyRenderedRef.current = true;
|
|
47
|
+
setIsFullyRendered(true);
|
|
48
|
+
onRenderComplete(true);
|
|
49
|
+
}, 200);
|
|
50
|
+
|
|
51
|
+
return () => clearTimeout(timeoutId);
|
|
52
|
+
}
|
|
53
|
+
}, [nodes.length, edges.length, associatedNodes]);
|
|
54
|
+
|
|
33
55
|
useEffect(() => {
|
|
34
56
|
setActiveNode(null);
|
|
35
57
|
}, [data]);
|
|
@@ -58,7 +80,7 @@ function TradeRelationship({
|
|
|
58
80
|
[edges, activeNode, associatedNodes]
|
|
59
81
|
);
|
|
60
82
|
|
|
61
|
-
useEffect(() => {
|
|
83
|
+
useEffect(() => {
|
|
62
84
|
let yInit = 0;
|
|
63
85
|
let xInit = 0;
|
|
64
86
|
const isBilateral = data?.sources?.length >= 1;
|
|
@@ -71,10 +93,9 @@ function TradeRelationship({
|
|
|
71
93
|
setEdges([]);
|
|
72
94
|
return;
|
|
73
95
|
}
|
|
74
|
-
|
|
75
96
|
const _nodes = [
|
|
76
97
|
{
|
|
77
|
-
id: data.id,
|
|
98
|
+
id: data.id?.toString(),
|
|
78
99
|
type: "expandedNode",
|
|
79
100
|
position: {
|
|
80
101
|
x: xInit,
|
|
@@ -89,10 +110,10 @@ function TradeRelationship({
|
|
|
89
110
|
if (isBilateral) {
|
|
90
111
|
(data.sources || []).forEach((source) => {
|
|
91
112
|
const hasPrev = false;
|
|
92
|
-
|
|
113
|
+
const edge = {
|
|
93
114
|
id: `e-${data.id}-${source}`,
|
|
94
|
-
source: source,
|
|
95
|
-
type: "
|
|
115
|
+
source: source?.toString(),
|
|
116
|
+
type: "defaultEdge",
|
|
96
117
|
target: data?.id?.toString(),
|
|
97
118
|
sourceHandle: "left",
|
|
98
119
|
targetHandle: "right",
|
|
@@ -106,7 +127,8 @@ function TradeRelationship({
|
|
|
106
127
|
tooltipTitle,
|
|
107
128
|
moreLeft: false,
|
|
108
129
|
},
|
|
109
|
-
}
|
|
130
|
+
};
|
|
131
|
+
_edges.push(edge);
|
|
110
132
|
});
|
|
111
133
|
}
|
|
112
134
|
|
|
@@ -164,7 +186,7 @@ function TradeRelationship({
|
|
|
164
186
|
? false
|
|
165
187
|
: true;
|
|
166
188
|
|
|
167
|
-
|
|
189
|
+
const edge = {
|
|
168
190
|
id: `e-${ch.id}-${source}`,
|
|
169
191
|
source: hasPrev ? source : ch?.id?.toString(),
|
|
170
192
|
type: isCustom ? "verticalPath" : "defaultEdge",
|
|
@@ -182,7 +204,8 @@ function TradeRelationship({
|
|
|
182
204
|
tooltipTitle,
|
|
183
205
|
moreLeft: prevChildren.length > children.length,
|
|
184
206
|
},
|
|
185
|
-
}
|
|
207
|
+
};
|
|
208
|
+
_edges.push(edge);
|
|
186
209
|
|
|
187
210
|
if (isCustom) {
|
|
188
211
|
customIndex += 1;
|
|
@@ -230,11 +253,25 @@ function TradeRelationship({
|
|
|
230
253
|
maxHeight: 0,
|
|
231
254
|
});
|
|
232
255
|
|
|
256
|
+
// Check for potential ID mismatches
|
|
257
|
+
const nodeIds = _nodes.map(n => n.id);
|
|
258
|
+
const edgeIssues = _edges.filter(e => {
|
|
259
|
+
const sourceExists = nodeIds.includes(e.source);
|
|
260
|
+
const targetExists = nodeIds.includes(e.target);
|
|
261
|
+
return !sourceExists || !targetExists;
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
// Set nodes first
|
|
233
265
|
setNodes(_nodes);
|
|
234
|
-
|
|
266
|
+
|
|
267
|
+
const timeoutId = setTimeout(() => {
|
|
268
|
+
setEdges(_edges);
|
|
269
|
+
}, 100); // 100ms is imperceptible to users but ensures React Flow is ready
|
|
270
|
+
|
|
271
|
+
// Cleanup to prevent memory leaks if component unmounts quickly
|
|
272
|
+
return () => clearTimeout(timeoutId);
|
|
235
273
|
}, [data, activeNode]);
|
|
236
274
|
|
|
237
|
-
// Used to find associated nodes, when a node is selected
|
|
238
275
|
useEffect(() => {
|
|
239
276
|
if (activeNode) {
|
|
240
277
|
let _associatedNodesRight = [activeNode];
|
|
@@ -293,6 +330,7 @@ function TradeRelationship({
|
|
|
293
330
|
|
|
294
331
|
return (
|
|
295
332
|
<BaseGraph
|
|
333
|
+
key={JSON.stringify(nodes) + JSON.stringify(edges)}
|
|
296
334
|
nodes={mappedNodes}
|
|
297
335
|
edges={mappedEdges}
|
|
298
336
|
maxZoom={maxZoom}
|
|
@@ -49,18 +49,22 @@ const BaseGraph = forwardRef(function BaseGraph(
|
|
|
49
49
|
return result;
|
|
50
50
|
}, [nodes.length, mandatoryNodesToFit?.length, mandatoryNodesToFit]);
|
|
51
51
|
|
|
52
|
+
// In BaseGraph.jsx, replace the useEffect with:
|
|
52
53
|
useEffect(() => {
|
|
53
54
|
if (nodesToFit.length === 0) return;
|
|
54
55
|
|
|
55
|
-
requestAnimationFrame
|
|
56
|
+
// Use setTimeout instead of requestAnimationFrame to ensure nodes are rendered
|
|
57
|
+
const timer = setTimeout(() => {
|
|
56
58
|
fitView({
|
|
57
59
|
padding: 0.4,
|
|
58
60
|
nodes: [...nodesToFit],
|
|
59
61
|
// duration: withDuration ? 300 : undefined,
|
|
60
62
|
maxZoom: 0.9,
|
|
61
63
|
});
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
+
}, 100); // Small delay to ensure nodes are rendered
|
|
65
|
+
|
|
66
|
+
return () => clearTimeout(timer);
|
|
67
|
+
}, [nodesToFit.length, nodesToFit.map(n => `${n.id}-${n.width}-${n.height}`).join(','), withDuration]);
|
|
64
68
|
|
|
65
69
|
return (
|
|
66
70
|
<ComponentWithFocus>
|
|
@@ -86,7 +90,7 @@ const BaseGraph = forwardRef(function BaseGraph(
|
|
|
86
90
|
fitView={true} // zoom out on default
|
|
87
91
|
fitViewOptions={{
|
|
88
92
|
padding: 0.2, //zoom out on default
|
|
89
|
-
|
|
93
|
+
duration: withDuration ? 300 : undefined,
|
|
90
94
|
}}
|
|
91
95
|
{...props}
|
|
92
96
|
>
|