datastake-daf 0.6.775 → 0.6.777

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.
@@ -5322,7 +5322,7 @@ const getMetaPlaceholer = (inputMeta, t) => inputMeta.notApplicable ? t("Not app
5322
5322
  * @param {string} [filterCond=null] - Filter condition.
5323
5323
  * @returns {Object[]} - Filtered options.
5324
5324
  */
5325
- function filterOptions(options, filters, formsValue = {}, repeatValues = {}, filterCond = null) {
5325
+ function filterOptions$1(options, filters, formsValue = {}, repeatValues = {}, filterCond = null) {
5326
5326
  const isOrCond = filterCond !== "and";
5327
5327
  const objFilter = {};
5328
5328
  filters.forEach(f => {
@@ -7570,8 +7570,6 @@ const Style$f = styled__default["default"].div`
7570
7570
  width: 100%;
7571
7571
  height: 472px;
7572
7572
 
7573
-
7574
-
7575
7573
  .filter-cont {
7576
7574
  position: absolute;
7577
7575
  top: 24px;
@@ -7674,24 +7672,11 @@ const Style$f = styled__default["default"].div`
7674
7672
  align-items: center;
7675
7673
  }
7676
7674
 
7677
- .marker-chain {
7678
- display: flex;
7679
- align-items: center;
7680
- justify-content: center;
7681
- }
7682
-
7683
- .animated-polyline {
7684
- stroke-dasharray: 10 10;
7685
- animation: dash-flow 1.5s linear infinite;
7686
- stroke-linecap: round;
7687
- }
7688
-
7689
- @keyframes dash-flow {
7690
- to {
7691
- stroke-dashoffset: -20;
7692
- }
7693
- }
7694
-
7675
+ .marker-chain {
7676
+ display: flex;
7677
+ align-items: center;
7678
+ justify-content: center;
7679
+ }
7695
7680
 
7696
7681
  }
7697
7682
 
@@ -8215,15 +8200,18 @@ const VILLAGE = "village";
8215
8200
  const EXPORTER = "exporter";
8216
8201
  const PROCESSOR = "mineralProcessor";
8217
8202
  const DEPOT = "depot";
8218
- const OPERATOR = "miningOperator";
8219
8203
  const MAX_EXTRA_SMALL_ZOOM_THRESHOLD = 2;
8220
8204
  const MAX_SMALL_ZOOM_THRESHOLD = 3;
8221
8205
  const MAX_MEDIUM_ZOOM_THRESHOLD = 6;
8222
8206
  const LOCATION_TYPES = [MINE_SITE, VILLAGE];
8223
- const STAKEHOLDER_TYPES = [EXPORTER, PROCESSOR, DEPOT, OPERATOR];
8207
+ const STAKEHOLDER_TYPES = [EXPORTER, PROCESSOR, DEPOT];
8224
8208
  const RADIUS_SMALL = 15;
8225
8209
  const RADIUS_MEDIUM = 35;
8226
8210
  const RADIUS_LARGE = 60;
8211
+ const RADIUS_CURVE_SMALL = 10;
8212
+ const RADIUS_CURVE_MEDIUM = 15;
8213
+ const RADIUS_CURVE_LARGE = 20;
8214
+ const TENSION = 0.2;
8227
8215
  function isLocation(type) {
8228
8216
  return LOCATION_TYPES.includes(type);
8229
8217
  }
@@ -8280,6 +8268,7 @@ function getStakeholderPosition({
8280
8268
  const isLarge = isLargeMarker(zoom);
8281
8269
  let radius;
8282
8270
  let center = {
8271
+ // NOT BEING USED FOR NOW AND MAYBE NEVER
8283
8272
  left: 0,
8284
8273
  top: 0
8285
8274
  };
@@ -8303,25 +8292,6 @@ function getStakeholderPosition({
8303
8292
  angleDeg
8304
8293
  };
8305
8294
  }
8306
- function applyAnimationDirect(el, isShortLink) {
8307
- if (!(el instanceof SVGElement) || isShortLink) return;
8308
- el.style.strokeDasharray = "10, 10";
8309
- el.style.strokeDashoffset = "0";
8310
- el.style.animation = "dash-flow 1.2s linear infinite";
8311
- el.classList.add('animated-polyline');
8312
- }
8313
- function removeAnimationFromElement(element) {
8314
- if (!element) return;
8315
- element.classList.remove('animated-polyline');
8316
- element.style.animation = '';
8317
- element.style.strokeDasharray = '';
8318
- }
8319
- function applyAnimationToPolyline(polyline, isShortLink) {
8320
- const element = polyline.getElement();
8321
- if (element) {
8322
- applyAnimationDirect(element, isShortLink);
8323
- }
8324
- }
8325
8295
  function createPolyline({
8326
8296
  L,
8327
8297
  startLatLng,
@@ -8331,48 +8301,110 @@ function createPolyline({
8331
8301
  zoom,
8332
8302
  listOfPolylines = [],
8333
8303
  isFromStakeholder = false,
8334
- isForceOpen = false,
8335
- stakeholderType = null,
8336
- animated = false,
8337
- mapRef
8304
+ isForceOpen = false
8338
8305
  }) {
8339
- const lineWidth = isFromStakeholder && isExtraSmallMarker(zoom) && !isForceOpen ? 0 : 1.2;
8340
- const isShortLink = stakeholderType === OPERATOR || isFromStakeholder;
8341
- const shouldAnimate = animated;
8342
- const lineCoordinates = [[startLatLng.lat, startLatLng.lng], [endLatLng.lat, endLatLng.lng]];
8343
- const polylineStyle = {
8306
+ const width = isFromStakeholder && isExtraSmallMarker(zoom) && !isForceOpen ? 0 : 1.2;
8307
+ const coordinates = [[startLatLng.lat, startLatLng.lng], [endLatLng.lat, endLatLng.lng]];
8308
+ const style = {
8344
8309
  color: "var(--base-gray-70)",
8345
- weight: lineWidth,
8346
- opacity: isSelected ? 1 : 0.5,
8347
- smoothFactor: 0,
8310
+ weight: width,
8311
+ opacity: 0.5,
8312
+ smoothFactor: 1,
8348
8313
  id,
8349
- dashArray: isShortLink ? "0, 0" : shouldAnimate ? "10, 10" : !isSelected ? "5, 5" : "10, 10",
8350
- renderer: L.svg()
8314
+ dashArray: !isSelected ? "5, 5" : "0, 0"
8351
8315
  };
8352
- const existingPolyline = listOfPolylines.find(p => p.options.id === id);
8353
- if (existingPolyline) {
8354
- removeAnimationFromElement(existingPolyline.getElement());
8355
- existingPolyline.setLatLngs(lineCoordinates);
8356
- existingPolyline.setStyle(polylineStyle);
8357
- if (shouldAnimate && isSelected) {
8358
- existingPolyline.once('add', () => {
8359
- applyAnimationToPolyline(existingPolyline, isShortLink);
8360
- });
8361
- applyAnimationToPolyline(existingPolyline, isShortLink);
8362
- }
8363
- return existingPolyline;
8364
- }
8365
- const newPolyline = L.polyline(lineCoordinates, polylineStyle);
8366
- newPolyline.addTo(mapRef);
8367
- listOfPolylines.push(newPolyline);
8368
- if (shouldAnimate && isSelected) {
8369
- newPolyline.once('add', () => {
8370
- applyAnimationToPolyline(newPolyline, isShortLink);
8371
- });
8372
- applyAnimationToPolyline(newPolyline, isShortLink);
8316
+ const newPolyline = L.polyline(coordinates, style);
8317
+ if (listOfPolylines.find(p => p.options.id === id)) {
8318
+ const polylineToUpdateCoordinates = listOfPolylines.find(p => p.options.id === id);
8319
+ polylineToUpdateCoordinates.setLatLngs(coordinates);
8320
+ polylineToUpdateCoordinates.setStyle(style);
8321
+ } else {
8322
+ listOfPolylines.push(newPolyline);
8373
8323
  }
8374
8324
  return newPolyline;
8375
8325
  }
8326
+ function createCurvePath({
8327
+ zoom,
8328
+ totalMarkers,
8329
+ markerIndex
8330
+ }) {
8331
+ const radius = getCurvePointRadius(zoom);
8332
+ const {
8333
+ x,
8334
+ y,
8335
+ angleDeg
8336
+ } = getAngleDeg(totalMarkers, markerIndex, radius);
8337
+ return {
8338
+ x,
8339
+ y,
8340
+ angleDeg
8341
+ };
8342
+ }
8343
+ function getCurvePointRadius(zoom) {
8344
+ const isSmall = isSmallMarker(zoom) || isExtraSmallMarker(zoom);
8345
+ const isMedium = isMediumMarker(zoom);
8346
+ if (isSmall) {
8347
+ return RADIUS_SMALL + RADIUS_CURVE_SMALL;
8348
+ } else if (isMedium) {
8349
+ return RADIUS_MEDIUM + RADIUS_CURVE_MEDIUM;
8350
+ } else {
8351
+ return RADIUS_LARGE + RADIUS_CURVE_LARGE;
8352
+ }
8353
+ }
8354
+ function buildSmoothCurve(layerPoints, mapRef) {
8355
+ const path = [];
8356
+ for (let i = 0; i < layerPoints.length - 1; i++) {
8357
+ const p0 = layerPoints[i];
8358
+ const p1 = layerPoints[i + 1];
8359
+ const pPrev = layerPoints[i - 1] || p0;
8360
+ const pNext = layerPoints[i + 2] || p1;
8361
+ const cp1 = L__namespace.point(p0.x + (p1.x - pPrev.x) * TENSION, p0.y + (p1.y - pPrev.y) * TENSION);
8362
+ const cp2 = L__namespace.point(p1.x - (pNext.x - p0.x) * TENSION, p1.y - (pNext.y - p0.y) * TENSION);
8363
+ if (i === 0) {
8364
+ path.push("M", [mapRef.layerPointToLatLng(p0).lat, mapRef.layerPointToLatLng(p0).lng]);
8365
+ }
8366
+ path.push("C", [mapRef.layerPointToLatLng(cp1).lat, mapRef.layerPointToLatLng(cp1).lng], [mapRef.layerPointToLatLng(cp2).lat, mapRef.layerPointToLatLng(cp2).lng], [mapRef.layerPointToLatLng(p1).lat, mapRef.layerPointToLatLng(p1).lng]);
8367
+ }
8368
+ return path;
8369
+ }
8370
+ function getSiblingCurveStrength(zoom) {
8371
+ if (isExtraSmallMarker(zoom)) return RADIUS_CURVE_SMALL / 2;
8372
+ if (isSmallMarker(zoom)) return RADIUS_CURVE_MEDIUM;
8373
+ if (isMediumMarker(zoom)) return RADIUS_CURVE_LARGE;
8374
+ return RADIUS_CURVE_LARGE;
8375
+ }
8376
+ function buildCurveWIthTwoSiblings({
8377
+ mapRef,
8378
+ startLatLng,
8379
+ endLatLng,
8380
+ zoom,
8381
+ isSelected,
8382
+ id
8383
+ }) {
8384
+ const fromPoint = mapRef.latLngToLayerPoint(startLatLng);
8385
+ const toPoint = mapRef.latLngToLayerPoint(endLatLng);
8386
+ const midX = (fromPoint.x + toPoint.x) / 2;
8387
+ const midY = (fromPoint.y + toPoint.y) / 2 + (isSmallMarker(zoom) ? RADIUS_CURVE_SMALL / 2 : 0);
8388
+ const dx = toPoint.x - fromPoint.x;
8389
+ const dy = toPoint.y - fromPoint.y;
8390
+ const normal = L__namespace.point(-dy, dx);
8391
+ const length = Math.sqrt(normal.x ** 2 + normal.y ** 2) || 1;
8392
+ const normalized = normal.multiplyBy(1 / length);
8393
+ const curveStrength = getSiblingCurveStrength(zoom);
8394
+ const controlPoint = L__namespace.point(midX, midY).add(normalized.multiplyBy(curveStrength));
8395
+ const latlngs = [startLatLng, mapRef.layerPointToLatLng(controlPoint), endLatLng];
8396
+ const layerPoints = latlngs.map(latlng => mapRef.latLngToLayerPoint(latlng));
8397
+ const path = buildSmoothCurve(layerPoints, mapRef);
8398
+ const curve = L__namespace.curve(path, {
8399
+ color: "var(--base-gray-70)",
8400
+ weight: isExtraSmallMarker(zoom) ? 0 : 1.2,
8401
+ opacity: 0.5,
8402
+ smoothFactor: 1,
8403
+ id,
8404
+ dashArray: !isSelected ? "5, 5" : "0, 0"
8405
+ });
8406
+ mapRef.addLayer(curve);
8407
+ }
8376
8408
 
8377
8409
  const StakeholderMarker = styled__default["default"].div`
8378
8410
  background-color: var(--blue-50);
@@ -8673,9 +8705,6 @@ function StakeholderIcon$1({
8673
8705
  return null;
8674
8706
  }, [parentId, allData]);
8675
8707
  React.useEffect(() => {
8676
- if (selectedMarkersId.length === 0 || !isSelected) {
8677
- return;
8678
- }
8679
8708
  linkNodesData.map(node => {
8680
8709
  const isConnectingToStakeholder = node.isStakeholder;
8681
8710
  const id = `${data.datastakeId}-${node.stakeholderId || node.datastakeId}`;
@@ -8687,6 +8716,8 @@ function StakeholderIcon$1({
8687
8716
  const stakeholderPoint = centerPoint.add(L__namespace.point(x, y));
8688
8717
  const stakeholderLatLng = mapRef.layerPointToLatLng(stakeholderPoint);
8689
8718
  let endLatLng = L__namespace.latLng(node.gps.latitude, node.gps.longitude);
8719
+ const areNextToEachOther = targetMarkerIndex === index + 1 || targetMarkerIndex === index - 1 || index === 0 && targetMarkerIndex === node.totalStakeholders - 1 || targetMarkerIndex === 0 && index === node.totalStakeholders - 1;
8720
+ const areOnlyTwoSiblings = node.totalStakeholders === 2;
8690
8721
  if (isExtraSmallMarker(zoom) && !isForceOpen) {
8691
8722
  createPolyline({
8692
8723
  L: L__namespace,
@@ -8696,8 +8727,7 @@ function StakeholderIcon$1({
8696
8727
  zoom,
8697
8728
  isSelected,
8698
8729
  id,
8699
- listOfPolylines: polylinesRef.current,
8700
- animated: true
8730
+ listOfPolylines: polylinesRef.current
8701
8731
  });
8702
8732
  return;
8703
8733
  }
@@ -8715,8 +8745,61 @@ function StakeholderIcon$1({
8715
8745
  const nodePoint = mapRef.latLngToLayerPoint(nodeLatLng);
8716
8746
  const endPoint = L__namespace.point(x + nodePoint.x + center.left, y + nodePoint.y + center.top);
8717
8747
  endLatLng = mapRef.layerPointToLatLng(endPoint);
8748
+ if (isSibling && (!areNextToEachOther || areOnlyTwoSiblings)) {
8749
+ if (areOnlyTwoSiblings) {
8750
+ buildCurveWIthTwoSiblings({
8751
+ mapRef,
8752
+ startLatLng: stakeholderLatLng,
8753
+ endLatLng,
8754
+ zoom,
8755
+ isSelected,
8756
+ id
8757
+ });
8758
+ return;
8759
+ }
8760
+ const total = node.totalStakeholders;
8761
+ let from = index;
8762
+ let to = targetMarkerIndex;
8763
+ let flip = false;
8764
+ const forwardDistance = (to - from + total) % total;
8765
+ const backwardDistance = (from - to + total) % total;
8766
+ if (backwardDistance < forwardDistance) {
8767
+ [from, to] = [to, from];
8768
+ flip = true;
8769
+ }
8770
+ const intermediateIndices = [];
8771
+ for (let i = 1; i < (to - from + total) % total; i++) {
8772
+ intermediateIndices.push((from + i) % total);
8773
+ }
8774
+ const indices = [from, ...intermediateIndices, to];
8775
+ const intermediatePoints = [];
8776
+ for (const i of indices) {
8777
+ const {
8778
+ x,
8779
+ y
8780
+ } = createCurvePath({
8781
+ zoom,
8782
+ totalMarkers: node.totalStakeholders,
8783
+ markerIndex: i
8784
+ });
8785
+ const point = centerPoint.add(L__namespace.point(x, y));
8786
+ const latlng = mapRef.layerPointToLatLng(point);
8787
+ intermediatePoints.push(latlng);
8788
+ }
8789
+ const latlngs = flip ? [endLatLng, ...intermediatePoints, stakeholderLatLng] : [stakeholderLatLng, ...intermediatePoints, endLatLng];
8790
+ const layerPoints = latlngs.map(latlng => mapRef.latLngToLayerPoint(latlng));
8791
+ const path = buildSmoothCurve(layerPoints, mapRef);
8792
+ const curve = L__namespace?.curve?.(path, {
8793
+ color: "var(--base-gray-70)",
8794
+ weight: isExtraSmallMarker(zoom) ? 0 : 1,
8795
+ opacity: isSelected ? 1 : 0.5,
8796
+ smoothFactor: 1,
8797
+ id
8798
+ });
8799
+ mapRef.addLayer(curve);
8800
+ return;
8801
+ }
8718
8802
  }
8719
- // Always use straight lines
8720
8803
  createPolyline({
8721
8804
  L: L__namespace,
8722
8805
  mapRef,
@@ -8726,11 +8809,10 @@ function StakeholderIcon$1({
8726
8809
  isFromStakeholder: false,
8727
8810
  isSelected,
8728
8811
  id,
8729
- listOfPolylines: polylinesRef.current,
8730
- animated: true
8812
+ listOfPolylines: polylinesRef.current
8731
8813
  });
8732
8814
  });
8733
- }, [mapRef, x, y, parentData, linkNodesData, isSelected, zoom, isForceOpen, selectedMarkersId]);
8815
+ }, [mapRef, x, y, parentData, linkNodesData, isSelected, zoom, isForceOpen]);
8734
8816
  return /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
8735
8817
  children: /*#__PURE__*/jsxRuntime.jsx(antd.Popover, {
8736
8818
  content: renderTooltipJsx({
@@ -8797,8 +8879,6 @@ function LocationIcon({
8797
8879
  const linkedNodesData = React.useMemo(() => {
8798
8880
  const nodes = [];
8799
8881
  const links = data.links || [];
8800
-
8801
- // Add links from the location itself
8802
8882
  links.forEach(link => {
8803
8883
  allData.forEach(d => {
8804
8884
  if (d.datastakeId === link) {
@@ -8818,45 +8898,8 @@ function LocationIcon({
8818
8898
  }
8819
8899
  });
8820
8900
  });
8821
-
8822
- // ADD: Also include links from this location's stakeholders
8823
- const stakeholders = data.stakeholders || [];
8824
- stakeholders.forEach(stakeholder => {
8825
- const stakeholderLinks = stakeholder.links || [];
8826
- stakeholderLinks.forEach(link => {
8827
- allData.forEach(d => {
8828
- // Check if it's a direct location link
8829
- if (d.datastakeId === link) {
8830
- // Avoid duplicates
8831
- if (!nodes.find(n => n.datastakeId === link && !n.isStakeholder)) {
8832
- nodes.push({
8833
- ...d,
8834
- fromStakeholderId: stakeholder.datastakeId
8835
- });
8836
- }
8837
- }
8838
- // Check if it's a stakeholder link
8839
- if (d.stakeholders && d.stakeholders.length > 0) {
8840
- d.stakeholders.forEach(targetStakeholder => {
8841
- if (targetStakeholder.datastakeId === link) {
8842
- // Avoid duplicates
8843
- if (!nodes.find(n => n.isStakeholder && n.datastakeId === d.datastakeId && n.stakeholdersIndex === d.stakeholders.indexOf(targetStakeholder))) {
8844
- nodes.push({
8845
- ...d,
8846
- isStakeholder: true,
8847
- totalStakeholders: d.stakeholders.length,
8848
- stakeholdersIndex: d.stakeholders.indexOf(targetStakeholder),
8849
- fromStakeholderId: stakeholder.datastakeId
8850
- });
8851
- }
8852
- }
8853
- });
8854
- }
8855
- });
8856
- });
8857
- });
8858
8901
  return nodes;
8859
- }, [JSON.stringify(allData), JSON.stringify(data.links), JSON.stringify(data.stakeholders), zoom]);
8902
+ }, [JSON.stringify(allData), JSON.stringify(data.links), zoom]);
8860
8903
  const stakeholdersOfLocation = React.useMemo(() => {
8861
8904
  return data?.stakeholders || [];
8862
8905
  }, [data.stakeholders, zoom]);
@@ -8874,13 +8917,7 @@ function LocationIcon({
8874
8917
  currentRoots.clear();
8875
8918
  markersRef.current = [];
8876
8919
 
8877
- // Only create stakeholder markers if this location or any of its stakeholders are selected
8878
- const shouldShowStakeholders = isSelected || stakeholdersOfLocation.some(stk => selectedMarkersId.includes(stk.datastakeId));
8879
- if (!shouldShowStakeholders || selectedMarkersId.length === 0) {
8880
- return;
8881
- }
8882
-
8883
- // Create new markers only when selected
8920
+ // Create new markers
8884
8921
  stakeholdersOfLocation.forEach((stakeholder, index) => {
8885
8922
  const markerId = `${stakeholder.datastakeId}`;
8886
8923
  const {
@@ -8966,9 +9003,7 @@ function LocationIcon({
8966
9003
  zoom,
8967
9004
  isFromStakeholder: true,
8968
9005
  isForceOpen,
8969
- listOfPolylines: polylinesRef.current,
8970
- stakeholderType: stakeholder.type,
8971
- animated: true
9006
+ listOfPolylines: polylinesRef.current
8972
9007
  });
8973
9008
  });
8974
9009
  return () => {
@@ -8983,88 +9018,38 @@ function LocationIcon({
8983
9018
  rootsMapRef.current.clear();
8984
9019
  markersRef.current = [];
8985
9020
  };
8986
- }, [stakeholdersOfLocation, selectedMarkersId, activeMarker, zoom]);
8987
-
8988
- // Only create polylines for linked nodes when something is selected
8989
- React.useEffect(() => {
8990
- if (selectedMarkersId.length === 0) {
8991
- return;
8992
- }
8993
-
8994
- // IMPORTANT: Only draw links if this location is actually selected
8995
- // Not just highlighted as part of the chain
8996
- if (!isSelected) {
8997
- return;
8998
- }
8999
-
9000
- // Filter linkedNodesData to only include nodes that are in the selected chain
9001
- const relevantLinks = linkedNodesData.filter(node => {
9002
- // Check if the target node (location) is in the selected markers
9003
- const targetLocationInSelection = selectedMarkersId.includes(node.datastakeId);
9004
-
9005
- // If connecting to a stakeholder, check if that stakeholder is selected
9006
- if (node.isStakeholder) {
9007
- const stakeholderInSelection = node.stakeholdersIndex !== undefined && selectedMarkersId.includes(node.datastakeId);
9008
- return stakeholderInSelection;
9009
- }
9010
- return targetLocationInSelection;
9011
- });
9012
- relevantLinks.forEach(node => {
9013
- const id = node.fromStakeholderId ? `${node.fromStakeholderId}-${node.datastakeId}` : `${data.datastakeId}-${node.datastakeId}`;
9014
- const isConnectingToStakeholder = node.isStakeholder;
9015
-
9016
- // If the link is from a stakeholder, start from the stakeholder position
9017
- let startLatLng;
9018
- if (node.fromStakeholderId) {
9019
- // Find the stakeholder index in this location's stakeholders
9020
- const stakeholderIndex = stakeholdersOfLocation.findIndex(s => s.datastakeId === node.fromStakeholderId);
9021
- if (stakeholderIndex !== -1) {
9022
- const {
9023
- x,
9024
- y
9025
- } = getStakeholderPosition({
9026
- zoom,
9027
- totalMarkers: stakeholdersOfLocation.length,
9028
- markerIndex: stakeholderIndex
9029
- });
9030
- const centerLatLng = L__namespace.latLng(data.gps.latitude, data.gps.longitude);
9031
- const centerPoint = mapRef.latLngToLayerPoint(centerLatLng);
9032
- const stakeholderPoint = centerPoint.add(L__namespace.point(x, y));
9033
- startLatLng = mapRef.layerPointToLatLng(stakeholderPoint);
9034
- } else {
9035
- startLatLng = L__namespace.latLng(data.gps.latitude, data.gps.longitude);
9036
- }
9037
- } else {
9038
- startLatLng = L__namespace.latLng(data.gps.latitude, data.gps.longitude);
9039
- }
9040
- let endLatLng = L__namespace.latLng(node.gps.latitude, node.gps.longitude);
9041
- const isConnectingToStakeholderSelected = selectedMarkersId.includes(node.datastakeId);
9042
- if (isConnectingToStakeholder && !isExtraSmallMarker(zoom)) {
9043
- const {
9044
- x,
9045
- y
9046
- } = getStakeholderPosition({
9047
- zoom,
9048
- totalMarkers: node.totalStakeholders,
9049
- markerIndex: node.stakeholdersIndex
9050
- });
9051
- const nodeLatLng = L__namespace.latLng(node.gps.latitude, node.gps.longitude);
9052
- const nodePoint = mapRef.latLngToLayerPoint(nodeLatLng);
9053
- const endPoint = L__namespace.point(x + nodePoint.x, y + nodePoint.y);
9054
- endLatLng = mapRef.layerPointToLatLng(endPoint);
9055
- }
9056
- createPolyline({
9057
- L: L__namespace,
9058
- mapRef,
9059
- startLatLng,
9060
- endLatLng,
9061
- isSelected: isConnectingToStakeholderSelected,
9062
- id,
9021
+ }, [stakeholdersOfLocation, selectedMarkersId, activeMarker]);
9022
+ linkedNodesData.map(node => {
9023
+ const id = `${data.datastakeId}-${node.datastakeId}`;
9024
+ const isConnectingToStakeholder = node.isStakeholder;
9025
+ const centerLatLng = L__namespace.latLng(data.gps.latitude, data.gps.longitude);
9026
+ let endLatLng = L__namespace.latLng(node.gps.latitude, node.gps.longitude);
9027
+ const isConnectingToStakeholderSelected = selectedMarkersId.includes(node.datastakeId);
9028
+ if (isConnectingToStakeholder && !isExtraSmallMarker(zoom)) {
9029
+ const {
9030
+ x,
9031
+ y
9032
+ } = getStakeholderPosition({
9063
9033
  zoom,
9064
- listOfPolylines: polylinesRef.current
9034
+ totalMarkers: node.totalStakeholders,
9035
+ markerIndex: node.stakeholdersIndex
9065
9036
  });
9037
+ const nodeLatLng = L__namespace.latLng(node.gps.latitude, node.gps.longitude);
9038
+ const nodePoint = mapRef.latLngToLayerPoint(nodeLatLng);
9039
+ const endPoint = L__namespace.point(x + nodePoint.x, y + nodePoint.y);
9040
+ endLatLng = mapRef.layerPointToLatLng(endPoint);
9041
+ }
9042
+ createPolyline({
9043
+ L: L__namespace,
9044
+ mapRef,
9045
+ startLatLng: centerLatLng,
9046
+ endLatLng,
9047
+ isSelected: isConnectingToStakeholderSelected,
9048
+ id,
9049
+ zoom,
9050
+ listOfPolylines: polylinesRef.current
9066
9051
  });
9067
- }, [linkedNodesData, selectedMarkersId, zoom, stakeholdersOfLocation, isSelected]);
9052
+ });
9068
9053
  return /*#__PURE__*/jsxRuntime.jsx(antd.Popover, {
9069
9054
  content: renderTooltipJsx({
9070
9055
  title: data.name,
@@ -9580,8 +9565,7 @@ function useMapHelper$1({
9580
9565
  link: link,
9581
9566
  onClickLink: onClickLink,
9582
9567
  activeStakeholder: activeStakeholder,
9583
- setActiveStakeholder: setActiveStakeholder,
9584
- mapRef: mapRef
9568
+ setActiveStakeholder: setActiveStakeholder
9585
9569
  }));
9586
9570
  roots.current.push(root);
9587
9571
  } else if (type === "location") {
@@ -9786,8 +9770,7 @@ const useMap = ({
9786
9770
  MAP_TOKEN
9787
9771
  } = useMapConfig({
9788
9772
  app,
9789
- isSatellite,
9790
- mapRef: container
9773
+ isSatellite
9791
9774
  });
9792
9775
  const [initialMarkerSetIsDone, setInitialMarkerSetIsDone] = React.useState(false);
9793
9776
  const [mapCenter, setMapCenter] = React.useState([0, 0]);
@@ -9804,8 +9787,6 @@ const useMap = ({
9804
9787
  const graph = new Map();
9805
9788
  const stakeToLoc = new Map();
9806
9789
  const nodeTypes = new Map();
9807
-
9808
- // Build the graph
9809
9790
  for (const loc of data) {
9810
9791
  const locId = loc.datastakeId;
9811
9792
  nodeTypes.set(locId, loc.type);
@@ -9830,45 +9811,26 @@ const useMap = ({
9830
9811
  }
9831
9812
  }
9832
9813
  const highlightTable = {};
9833
-
9834
- // Perform BFS/DFS to find all connected nodes in the entire chain
9835
9814
  for (const [node] of graph) {
9836
9815
  const highlighted = new Set();
9837
- const queue = [node];
9838
- const visited = new Set([node]);
9839
- while (queue.length > 0) {
9840
- const current = queue.shift();
9841
- highlighted.add(current);
9842
-
9843
- // Add parent location if current is stakeholder
9844
- const currentIsStakeholder = !isLocation(nodeTypes.get(current));
9845
- if (currentIsStakeholder && stakeToLoc.has(current)) {
9846
- const parentLoc = stakeToLoc.get(current);
9847
- if (!visited.has(parentLoc)) {
9848
- highlighted.add(parentLoc);
9849
- visited.add(parentLoc);
9850
- queue.push(parentLoc);
9851
- }
9852
- }
9853
-
9854
- // Traverse all neighbors
9855
- for (const neighbor of graph.get(current) || []) {
9856
- if (!visited.has(neighbor)) {
9857
- visited.add(neighbor);
9858
- queue.push(neighbor);
9816
+ highlighted.add(node);
9817
+ const nodeIsStakeholder = !isLocation(nodeTypes.get(node));
9818
+ if (nodeIsStakeholder && stakeToLoc.has(node)) {
9819
+ const parentLoc = stakeToLoc.get(node);
9820
+ highlighted.add(parentLoc);
9821
+ }
9822
+ for (const neighbor of graph.get(node) || []) {
9823
+ const neighborIsStakeholder = !isLocation(nodeTypes.get(neighbor));
9824
+ if (neighborIsStakeholder && stakeToLoc.has(neighbor)) {
9825
+ const neighborParent = stakeToLoc.get(neighbor);
9826
+ if (isLocation(nodeTypes.get(node)) && neighborParent === node || nodeIsStakeholder && stakeToLoc.get(node) === neighborParent) {
9859
9827
  highlighted.add(neighbor);
9860
-
9861
- // If neighbor is stakeholder, add its parent location
9862
- const neighborIsStakeholder = !isLocation(nodeTypes.get(neighbor));
9863
- if (neighborIsStakeholder && stakeToLoc.has(neighbor)) {
9864
- const neighborParent = stakeToLoc.get(neighbor);
9865
- if (!visited.has(neighborParent)) {
9866
- highlighted.add(neighborParent);
9867
- visited.add(neighborParent);
9868
- queue.push(neighborParent);
9869
- }
9870
- }
9828
+ } else {
9829
+ highlighted.add(neighbor);
9830
+ highlighted.add(neighborParent);
9871
9831
  }
9832
+ } else {
9833
+ highlighted.add(neighbor);
9872
9834
  }
9873
9835
  }
9874
9836
  highlightTable[node] = [...highlighted];
@@ -9933,29 +9895,19 @@ const useMap = ({
9933
9895
  });
9934
9896
  }
9935
9897
  }
9936
- if (type === "chain" && selectedMarkersId.length === 0) {
9937
- if (polylinesRef.current.length) {
9938
- polylinesRef.current.forEach(polyline => {
9939
- if (mapRef.hasLayer(polyline)) {
9940
- mapRef.removeLayer(polyline);
9941
- }
9942
- });
9943
- polylinesRef.current = [];
9944
- }
9945
- }
9946
9898
  clearMapMarkers();
9947
9899
  if (data) {
9948
- const filteredData = data?.filter(obj => obj.type === 'mineSite' || obj?.stakeholders?.length > 0 || data.some(other => other.datastakeId !== obj.datastakeId && (other.stakeholders || []).some(stk => (stk.links || []).includes(obj.datastakeId))));
9900
+ // Filters out locations that are not connected to any stakeholders
9901
+ const excludedType = ['village', 'town', 'area', 'territory'];
9902
+ const filteredData = data?.filter(obj => !excludedType.includes(obj?.type) && (obj?.stakeholders?.length > 0 || data.some(other => other.datastakeId !== obj.datastakeId && (other.stakeholders || []).some(stk => (stk.links || []).includes(obj.datastakeId)))));
9949
9903
  const maxTotal = Math.max(...(data || []).map(d => d.total));
9950
9904
  const dataToRender = type === "chain" ? filteredData : data;
9951
9905
  dataToRender.forEach((d, i) => {
9952
9906
  addIconToMapInitialy([d?.marker?.lat, d?.marker?.lng], "location", d.category || "mineSite", d, maxTotal, i);
9953
9907
  });
9954
- if (selectedMarkersId.length > 0) {
9955
- polylinesRef.current.forEach(polyline => {
9956
- mapRef.addLayer(polyline);
9957
- });
9958
- }
9908
+ polylinesRef.current.forEach(polyline => {
9909
+ mapRef.addLayer(polyline);
9910
+ });
9959
9911
  mapRef.invalidateSize();
9960
9912
  mapRef.fire("moveend");
9961
9913
  }
@@ -27313,7 +27265,7 @@ const inputTypeComponent = {
27313
27265
  opts = JSON.parse(JSON.stringify(opts));
27314
27266
  opts = opts.map(o => getSelectOptions(o, formsValue));
27315
27267
  if (optionsFilter && Array.isArray(optionsFilter)) {
27316
- opts = filterOptions(opts, optionsFilter, formsValue, repeatValues, filterCond);
27268
+ opts = filterOptions$1(opts, optionsFilter, formsValue, repeatValues, filterCond);
27317
27269
  }
27318
27270
  if (propHasValue(value)) {
27319
27271
  const selectOption = opts.find(o => o.value === value);
@@ -27432,7 +27384,7 @@ const inputTypeComponent = {
27432
27384
  opts = JSON.parse(JSON.stringify(opts));
27433
27385
  opts = opts.map(o => getSelectOptions(o, formsValue));
27434
27386
  if (optionsFilter && Array.isArray(optionsFilter)) {
27435
- opts = filterOptions(opts, optionsFilter, formsValue, repeatValues, filterCond);
27387
+ opts = filterOptions$1(opts, optionsFilter, formsValue, repeatValues, filterCond);
27436
27388
  }
27437
27389
  if (propHasValue(value) && Array.isArray(value) && value.length > 0 && !tags) {
27438
27390
  try {
@@ -43794,9 +43746,10 @@ const calculateHealthAndSafetyPieData = (healthAndSafetyDistributionData, t) =>
43794
43746
  * @param {Object} healthAndSafetyDistributionData - Distribution object
43795
43747
  * @param {Function} t - Translation function
43796
43748
  * @param {Function} renderTooltipJsx - Function to render tooltip JSX
43749
+ * @param {string} tooltipTitle - Title to display in the tooltip (defaults to "Health and Safety")
43797
43750
  * @returns {JSX.Element|null} Tooltip content or null
43798
43751
  */
43799
- const getHealthAndSafetyTooltipChildren = (item, isEmpty, healthAndSafetyDistributionData, t, renderTooltipJsx) => {
43752
+ const getHealthAndSafetyTooltipChildren = (item, isEmpty, healthAndSafetyDistributionData, t, renderTooltipJsx, tooltipTitle = "Health and Safety") => {
43800
43753
  // If empty or no data, return null to display nothing
43801
43754
  if (isEmpty || !Object.keys(healthAndSafetyDistributionData).length) {
43802
43755
  return null;
@@ -43833,25 +43786,39 @@ const getHealthAndSafetyTooltipChildren = (item, isEmpty, healthAndSafetyDistrib
43833
43786
 
43834
43787
  // Show all items with their percentages
43835
43788
  return renderTooltipJsx({
43836
- title: t("Health and Safety"),
43789
+ title: t(tooltipTitle),
43837
43790
  items: itemsWithData
43838
43791
  });
43839
43792
  };
43840
43793
 
43794
+ const filterOptions = [{
43795
+ value: 'aidKitAccessible',
43796
+ label: 'Aid kit availability'
43797
+ }, {
43798
+ value: 'hsTrainingConfirmation',
43799
+ label: 'H&S training delivery'
43800
+ }, {
43801
+ value: 'duosFormed',
43802
+ label: 'Workers safe pairing'
43803
+ }, {
43804
+ value: 'presenceOfChildren',
43805
+ label: 'No children'
43806
+ }];
43841
43807
  const HealthAndSafety = ({
43842
43808
  id,
43843
43809
  getSummaryDetail,
43844
43810
  loading = false,
43845
43811
  t = s => s
43846
43812
  }) => {
43813
+ const [selectedField, setSelectedField] = React.useState('aidKitAccessible');
43847
43814
  const defaultConfig = React.useMemo(() => ({
43848
43815
  basepath: "planting-cycle",
43849
43816
  url: `/summary/${id}/filtered-piechart`,
43850
43817
  filters: {
43851
- field: 'duosFormed'
43818
+ field: selectedField
43852
43819
  },
43853
43820
  stop: !id
43854
- }), [id]);
43821
+ }), [id, selectedField]);
43855
43822
  const customGetData = React.useMemo(() => {
43856
43823
  if (getSummaryDetail && id) {
43857
43824
  return rest => {
@@ -43882,7 +43849,7 @@ const HealthAndSafety = ({
43882
43849
  });
43883
43850
 
43884
43851
  // Process the fetched pie chart data
43885
- // The API returns data in format: [{count: 1, duosFormed: "null"}, {count: 1, duosFormed: "no"}, {count: 1, duosFormed: "yes"}]
43852
+ // The API returns data in format: [{count: 1, [field]: "null"}, {count: 1, [field]: "no"}, {count: 1, [field]: "yes"}]
43886
43853
  const healthAndSafetyDistributionData = React.useMemo(() => {
43887
43854
  if (!pieChartData) return {
43888
43855
  compliant: 0,
@@ -43895,7 +43862,7 @@ const HealthAndSafety = ({
43895
43862
  return pieChartData;
43896
43863
  }
43897
43864
 
43898
- // If it's an array, process it
43865
+ // If it's an array, process it using the selected field
43899
43866
  if (Array.isArray(pieChartData)) {
43900
43867
  const distribution = {
43901
43868
  compliant: 0,
@@ -43903,15 +43870,15 @@ const HealthAndSafety = ({
43903
43870
  empty: 0
43904
43871
  };
43905
43872
  pieChartData.forEach(item => {
43906
- const duosFormedValue = item.duosFormed;
43873
+ const fieldValue = item[selectedField];
43907
43874
  const count = item.count || 0;
43908
43875
 
43909
- // Map duosFormed values to distribution categories
43910
- if (duosFormedValue === "yes" || duosFormedValue === true) {
43876
+ // Map field values to distribution categories
43877
+ if (fieldValue === "yes" || fieldValue === true) {
43911
43878
  distribution.compliant += count;
43912
- } else if (duosFormedValue === "no" || duosFormedValue === false) {
43879
+ } else if (fieldValue === "no" || fieldValue === false) {
43913
43880
  distribution.notCompliant += count;
43914
- } else if (duosFormedValue === "null" || duosFormedValue === null || duosFormedValue === undefined) {
43881
+ } else if (fieldValue === "null" || fieldValue === null || fieldValue === undefined) {
43915
43882
  distribution.empty += count;
43916
43883
  }
43917
43884
  });
@@ -43920,16 +43887,41 @@ const HealthAndSafety = ({
43920
43887
 
43921
43888
  // Fallback: try to extract from activityData-like structure
43922
43889
  return getHealthAndSafetyDistributionData(pieChartData);
43923
- }, [pieChartData]);
43890
+ }, [pieChartData, selectedField]);
43924
43891
  const isEmpty = React.useMemo(() => isHealthAndSafetyDistributionEmpty(healthAndSafetyDistributionData), [healthAndSafetyDistributionData]);
43925
43892
  const pieData = React.useMemo(() => calculateHealthAndSafetyPieData(healthAndSafetyDistributionData, t), [healthAndSafetyDistributionData, t]);
43926
- const getTooltipChildren = React.useCallback(item => getHealthAndSafetyTooltipChildren(item, isEmpty, healthAndSafetyDistributionData, t, renderTooltipJsx), [t, isEmpty, healthAndSafetyDistributionData]);
43893
+
43894
+ // Get the label for the selected field to use as tooltip title
43895
+ const selectedFieldLabel = React.useMemo(() => {
43896
+ const selectedOption = filterOptions.find(opt => opt.value === selectedField);
43897
+ return selectedOption ? selectedOption.label : 'Health and Safety';
43898
+ }, [selectedField]);
43899
+ const getTooltipChildren = React.useCallback(item => getHealthAndSafetyTooltipChildren(item, isEmpty, healthAndSafetyDistributionData, t, renderTooltipJsx, selectedFieldLabel), [t, isEmpty, healthAndSafetyDistributionData, selectedFieldLabel]);
43900
+ const handleFilterChange = React.useCallback(value => {
43901
+ setSelectedField(value);
43902
+ }, []);
43927
43903
  return /*#__PURE__*/jsxRuntime.jsx(Widget, {
43928
43904
  loading: loading || pieChartLoading,
43929
43905
  title: /*#__PURE__*/jsxRuntime.jsx("div", {
43930
43906
  children: t("Health and Safety")
43931
43907
  }),
43932
43908
  className: "with-border-header h-w-btn-header ",
43909
+ addedHeader: /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
43910
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
43911
+ className: "flex-1"
43912
+ }), /*#__PURE__*/jsxRuntime.jsx(antd.Select, {
43913
+ value: selectedField,
43914
+ style: {
43915
+ width: 180
43916
+ },
43917
+ onChange: handleFilterChange,
43918
+ options: filterOptions.map(opt => ({
43919
+ ...opt,
43920
+ label: t(opt.label)
43921
+ })),
43922
+ popupMatchSelectWidth: 180
43923
+ })]
43924
+ }),
43933
43925
  children: /*#__PURE__*/jsxRuntime.jsx("div", {
43934
43926
  style: {
43935
43927
  marginTop: "auto",