datastake-daf 0.6.841 → 0.6.843

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/build/favicon.ico +0 -0
  2. package/build/logo192.png +0 -0
  3. package/build/logo512.png +0 -0
  4. package/build/manifest.json +25 -0
  5. package/build/robots.txt +3 -0
  6. package/dist/components/index.js +773 -768
  7. package/dist/hooks/index.js +4 -6
  8. package/dist/layouts/index.js +6 -0
  9. package/dist/pages/index.js +187 -133
  10. package/package.json +1 -1
  11. package/src/@daf/core/components/DynamicForm/hook.js +2 -2
  12. package/src/@daf/core/components/DynamicForm/index.jsx +1 -1
  13. package/src/@daf/core/components/Filters/selectFilters/index.jsx +7 -1
  14. package/src/@daf/core/components/Graphs/TradeRelationship/index.jsx +1 -27
  15. package/src/@daf/core/components/Graphs/components/BaseGraph.jsx +22 -18
  16. package/src/@daf/core/components/Select/MultiSelect/style.js +1 -1
  17. package/src/@daf/core/components/ViewForm/components/DataLink/flat.js +7 -3
  18. package/src/@daf/core/components/ViewForm/components/DataLink/index.js +6 -2
  19. package/src/@daf/core/components/ViewForm/components/input.js +7 -7
  20. package/src/@daf/hooks/useWidgetFetch.js +26 -35
  21. package/src/@daf/pages/Dashboards/ConflictManagement/components/RisksWidget/components/IncidentsTime/index.js +1 -0
  22. package/src/@daf/pages/Dashboards/SupplyChain/components/ChartsContainer/components/Locations/index.js +20 -19
  23. package/src/@daf/pages/Dashboards/SupplyChain/components/ChartsContainer/index.js +5 -2
  24. package/src/@daf/pages/Events/Activities/columns.js +7 -3
  25. package/src/@daf/pages/Events/Incidents/columns.js +7 -3
  26. package/src/@daf/pages/Summary/Operator/components/KeyInformation/config.js +0 -1
  27. package/src/@daf/pages/Summary/Operator/components/TradeRelationships/helper.js +7 -5
  28. package/src/@daf/pages/Summary/Operator/components/TradeRelationships/hook.js +29 -14
  29. package/src/@daf/pages/Summary/Operator/components/TradeRelationships/index.js +69 -20
  30. package/src/@daf/pages/Summary/Operator/index.jsx +1 -0
  31. package/src/@daf/pages/View/index.jsx +1 -1
  32. package/src/helpers/Forms.js +7 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "datastake-daf",
3
- "version": "0.6.841",
3
+ "version": "0.6.843",
4
4
  "dependencies": {
5
5
  "@ant-design/icons": "^5.2.5",
6
6
  "@antv/g2": "^5.1.1",
@@ -1,7 +1,7 @@
1
1
  import { useRef, useEffect } from "react";
2
2
  import { resolveCombinedPrefilledValue } from "../../../../helpers/Forms";
3
3
 
4
- export const useCombinedPrefilledValues = (combinedPrefilledValues, values, parentValues, setValues, MainForm) => {
4
+ export const useCombinedPrefilledValues = (combinedPrefilledValues, values, parentValues, setValues, MainForm, form) => {
5
5
  const combinedValuesRef = useRef({});
6
6
 
7
7
  useEffect(() => {
@@ -14,7 +14,7 @@ export const useCombinedPrefilledValues = (combinedPrefilledValues, values, pare
14
14
 
15
15
  Object.keys(combinedPrefilledValues).forEach(fieldKey => {
16
16
  const template = combinedPrefilledValues[fieldKey];
17
- const resolvedValue = resolveCombinedPrefilledValue(template, values, parentValues);
17
+ const resolvedValue = resolveCombinedPrefilledValue(template, values, parentValues, form);
18
18
 
19
19
  if (resolvedValue === null) {
20
20
  return;
@@ -178,7 +178,7 @@ export default function DynamicForm({
178
178
  }, [data, isCreate]);
179
179
 
180
180
  // Handle combined prefilled values (auto-fill based on templates)
181
- useCombinedPrefilledValues(combinedPrefilledValues, values, parentValues, setValues, MainForm);
181
+ useCombinedPrefilledValues(combinedPrefilledValues, values, parentValues, setValues, MainForm, form);
182
182
 
183
183
  // Initialize default values for hidden and disabled fields
184
184
  useEffect(() => {
@@ -1,6 +1,6 @@
1
1
  import PropTypes from 'prop-types'
2
2
  import { Button, Input, Tooltip } from 'antd';
3
- import React, { useMemo, useState } from 'react';
3
+ import React, { useMemo, useState, useEffect } from 'react';
4
4
  import { CustomSelect } from './Select.jsx';
5
5
  import { Timeframe } from './Timeframe.jsx';
6
6
  import { AjaxSelect } from "./AjaxSelect.jsx";
@@ -26,6 +26,12 @@ const SelectFilters = ({
26
26
  const [filters, setFilters] = useState(selectedFilters || {});
27
27
  const [initFilters, setInitFilters] = useState(selectedFilters || {})
28
28
 
29
+ // Sync internal state with selectedFilters prop when it changes
30
+ useEffect(() => {
31
+ setFilters(selectedFilters || {});
32
+ setInitFilters(selectedFilters || {});
33
+ }, [selectedFilters]);
34
+
29
35
  const getClearLabel = () => {
30
36
  switch (type) {
31
37
  case 'small':
@@ -21,7 +21,6 @@ function TradeRelationship({
21
21
  onFilterChange = () => {},
22
22
  renderTooltipItems = () => [],
23
23
  getTotal = () => 0,
24
- onRenderComplete = () => {},
25
24
  }) {
26
25
  const reactFlowWrapper = useRef(null);
27
26
  const [nodes, setNodes] = useNodesState([]);
@@ -31,31 +30,6 @@ function TradeRelationship({
31
30
  // const [initCenter, setInitCenter] = useState(true);
32
31
  const [associatedNodes, setAssociatedNodes] = useState(null);
33
32
 
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
- if(nodes.length === 0 || edges.length === 0) {
54
- setIsFullyRendered(true);
55
- onRenderComplete(true);
56
- }
57
- }, [nodes.length, edges.length, associatedNodes]);
58
-
59
33
  useEffect(() => {
60
34
  setActiveNode(null);
61
35
  }, [data]);
@@ -274,7 +248,7 @@ function TradeRelationship({
274
248
 
275
249
  // Cleanup to prevent memory leaks if component unmounts quickly
276
250
  return () => clearTimeout(timeoutId);
277
- }, [data, activeNode]);
251
+ }, [data]);
278
252
 
279
253
  useEffect(() => {
280
254
  if (activeNode) {
@@ -2,7 +2,7 @@ import { ReactFlow, Controls, ControlButton, useReactFlow } from "@xyflow/react"
2
2
  import { UpOutlined, DownOutlined, AimOutlined } from "@ant-design/icons";
3
3
 
4
4
  import ComponentWithFocus from "../../Dashboard/ComponentWithFocus/index.jsx";
5
- import { forwardRef } from "react";
5
+ import { forwardRef, useRef } from "react";
6
6
  import { PrimaryNode, IconNode, NameNode, ExpandedNode } from "./Nodes/index.jsx";
7
7
  import { ToolTipEdge, VerticalPathEdge, DefaultEdge } from "./Edges/index.jsx";
8
8
  import Filters from "../../Filters/FloatingFilters/index.js";
@@ -38,6 +38,7 @@ const BaseGraph = forwardRef(function BaseGraph(
38
38
  ref,
39
39
  ) {
40
40
  const { setViewport, getViewport, fitView } = useReactFlow();
41
+ const hasInitialFitRef = useRef(false);
41
42
 
42
43
  const nodesToFit = useMemo(() => {
43
44
  let result;
@@ -49,31 +50,34 @@ const BaseGraph = forwardRef(function BaseGraph(
49
50
  return result;
50
51
  }, [nodes.length, mandatoryNodesToFit?.length, mandatoryNodesToFit]);
51
52
 
52
- // In BaseGraph.jsx, replace the useEffect with:
53
+ // Only auto-fit on initial render or when node count changes, not on property changes
53
54
  useEffect(() => {
54
55
  if (nodesToFit.length === 0) return;
55
56
 
56
- // Use setTimeout instead of requestAnimationFrame to ensure nodes are rendered
57
- const timer = setTimeout(() => {
58
- fitView({
59
- padding: 0.4,
60
- nodes: [...nodesToFit],
61
- // duration: withDuration ? 300 : undefined,
62
- maxZoom: 0.9,
63
- });
64
- }, 100); // Small delay to ensure nodes are rendered
57
+ // Only auto-fit on initial render or when node count changes
58
+ if (!hasInitialFitRef.current) {
59
+ hasInitialFitRef.current = true;
60
+
61
+ const timer = setTimeout(() => {
62
+ fitView({
63
+ padding: 0.4,
64
+ nodes: [...nodesToFit],
65
+ maxZoom: 0.9,
66
+ });
67
+ }, 100);
65
68
 
66
- return () => clearTimeout(timer);
67
- }, [nodesToFit.length, nodesToFit.map(n => `${n.id}-${n.width}-${n.height}`).join(','), withDuration]);
69
+ return () => clearTimeout(timer);
70
+ }
71
+ }, [nodesToFit.length, withDuration]);
68
72
 
69
73
  return (
70
74
  <ComponentWithFocus>
71
- <div style={{ height: "100%", width: "100%" }} ref={ref}>
72
- {filtersConfig ? (
73
- <Filters t={t} filtersConfig={filtersConfig} onFilterChange={onFilterChange} />
74
- ) : null}
75
+ <div style={{ height: "100%", width: "100%", position: "relative" }} ref={ref}>
76
+ {filtersConfig ? (
77
+ <Filters t={t} filtersConfig={filtersConfig} onFilterChange={onFilterChange} />
78
+ ) : null}
75
79
 
76
- <ReactFlow
80
+ <ReactFlow
77
81
  nodes={nodes}
78
82
  edges={edges}
79
83
  zoomOnDoubleClick={false}
@@ -5,7 +5,7 @@ const MultiSelectStyled = styled(Select)`
5
5
  &.ant-select-single {
6
6
  .ant-select-selector {
7
7
  padding-inline-end: 24px !important;
8
- padding: 0 !important;
8
+ padding: 3px !important;
9
9
  max-width: 56px !important;
10
10
  width: 56px !important;
11
11
  }
@@ -177,9 +177,13 @@ export default function DataLinkFlat({
177
177
  }, [entity, values.linking])
178
178
 
179
179
  const dataLinkFormData = useMemo(() => {
180
- const _formData = isSingle ? formData && !Array.isArray(formData)
181
- ? [{ ...form?.meta?.prefilledValues, ...formData }] : []
182
- : (Array.isArray(formData) ? formData : []).map((f) => ({ ...form?.meta?.prefilledValues, ...f }));
180
+ const filteredPrefilledValues = Object.entries(form?.meta?.prefilledValues || {})
181
+ .filter(([_, value]) => !(value && typeof value === 'object' && 'combine' in value))
182
+ .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {});
183
+
184
+ const _formData = isSingle ? formData && !Array.isArray(formData)
185
+ ? [{ ...filteredPrefilledValues, ...formData }] : []
186
+ : (Array.isArray(formData) ? formData : []).map((f) => ({ ...filteredPrefilledValues, ...f }));
183
187
 
184
188
  return (_formData || []).map((f, i) => {
185
189
  if (isAjaxModal && typeof f === 'string' && linkingData[f]) {
@@ -111,9 +111,13 @@ export default function DataLink({
111
111
  })
112
112
 
113
113
  const data = useMemo(() => {
114
+ const filteredPrefilledValues = Object.entries(form?.meta?.prefilledValues || {})
115
+ .filter(([_, value]) => !(value && typeof value === 'object' && 'combine' in value))
116
+ .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {});
117
+
114
118
  const _formData = isSingle ? formData && !Array.isArray(formData)
115
- ? [{ ...form?.meta?.prefilledValues, ...formData }] : []
116
- : (Array.isArray(formData) ? formData : []).map((f) => ({ ...form?.meta?.prefilledValues, ...f }));
119
+ ? [{ ...filteredPrefilledValues, ...formData }] : []
120
+ : (Array.isArray(formData) ? formData : []).map((f) => ({ ...filteredPrefilledValues, ...f }));
117
121
 
118
122
  return (_formData || []).map((f, i) => {
119
123
  if (isAjaxModal && typeof f === 'string' && linkingData[f]) {
@@ -361,13 +361,13 @@ export const BasicInput = ({
361
361
  case 'phoneNumber':
362
362
  case 'textarea':
363
363
  return item
364
- ? (propHasValue(item[inputName]) ? item[inputName] : placeholder(item, inputName, withPlaceholder))
365
- : (propHasValue(data[inputName]) ? data[inputName] : placeholder(data, inputName, withPlaceholder));
364
+ ? (propHasValue(item[inputName]) && item[inputName] !== '' ? item[inputName] : placeholder(item, inputName, withPlaceholder))
365
+ : (propHasValue(data[inputName]) && data[inputName] !== '' ? data[inputName] : placeholder(data, inputName, withPlaceholder));
366
366
  case 'website':
367
367
  case 'link':
368
368
  const v = item
369
- ? (propHasValue(item[inputName]) ? item[inputName] : placeholder(item, inputName, withPlaceholder))
370
- : (propHasValue(data[inputName]) ? data[inputName] : placeholder(data, inputName, withPlaceholder))
369
+ ? (propHasValue(item[inputName]) && item[inputName] !== '' ? item[inputName] : placeholder(item, inputName, withPlaceholder))
370
+ : (propHasValue(data[inputName]) && data[inputName] !== '' ? data[inputName] : placeholder(data, inputName, withPlaceholder))
371
371
 
372
372
  if (isModal) {
373
373
  return (
@@ -1023,7 +1023,7 @@ const Input = ({
1023
1023
  >
1024
1024
  </BasicInput>
1025
1025
  })}
1026
- {isRepeatable && Array.isArray(modalData) && !modalData.length ? (
1026
+ {isRepeatable && Array.isArray(modalData) && !modalData.length || modalData === "" ? (
1027
1027
  <span className="text-muted">{t('Not answered')}</span>
1028
1028
  ) : null}
1029
1029
  </React.Fragment>
@@ -1068,7 +1068,7 @@ const Input = ({
1068
1068
  })
1069
1069
  }
1070
1070
  {
1071
- (!modalData || (Array.isArray(modalData) && !modalData.length)) ? (
1071
+ (!modalData || (Array.isArray(modalData) && !modalData.length) || modalData === "") ? (
1072
1072
  <span className="text-muted">{t('Not answered')}</span>
1073
1073
  ) : (
1074
1074
  (Array.isArray(modalData) ? modalData : [modalData]).map((item, itemId) => (
@@ -1174,7 +1174,7 @@ const Input = ({
1174
1174
  >
1175
1175
  </BasicInput>
1176
1176
  })}
1177
- {(!formData || (Array.isArray(formData) && !formData.length)) ? (
1177
+ {(!formData || (Array.isArray(formData) && !formData.length) || formData === "") ? (
1178
1178
  <span className="text-muted">{t('Not answered')}</span>
1179
1179
  ) : (
1180
1180
  (Array.isArray(formData) ? formData : [formData])?.map((item, itemId) => (
@@ -2,7 +2,6 @@ import { useState, useEffect, useRef } from "react";
2
2
  import DashboardService from "../services/DashboardService.js";
3
3
  import { isErrorResponse, getErrorMessage } from "../../helpers/errorHandling.js";
4
4
  import { message } from "antd";
5
-
6
5
  // config: {
7
6
  // stop: boolean,
8
7
  // defaultData: object,
@@ -10,56 +9,48 @@ import { message } from "antd";
10
9
  // url: string
11
10
  // basePath: string,
12
11
  // }
13
-
14
12
  export const useWidgetFetch = ({config, getData = DashboardService.getWidget, onFetch = () => {}}) => {
15
13
  const { stop, defaultData, ...rest} = config;
16
14
  const [ data, setData ] = useState(defaultData || {});
17
15
  const [ loading, setLoading ] = useState(false);
18
16
  const [ initFetchDone, setInitFetchDone ] = useState(false);
19
17
  const isMounted = useRef(true);
20
-
21
- const fetchData = async () => {
22
- if (stop) {
23
- return;
24
- }
25
-
26
- setLoading(true);
27
-
28
- try {
29
- const { data } = await getData(rest);
30
- if (!isMounted.current) return;
31
- setData(data || defaultData);
32
- if (isErrorResponse(data)) {
33
- const errorMessage = getErrorMessage(data);
34
- message.error(errorMessage);
35
- return;
36
- }
18
+
19
+ const fetchData = async () => {
20
+ setLoading(true);
21
+ try {
22
+ const { data } = await getData(rest);
23
+ if (!isMounted.current) return;
24
+ setData(data || defaultData);
25
+ if (isErrorResponse(data)) {
26
+ const errorMessage = getErrorMessage(data);
27
+ message.error(errorMessage);
28
+ return;
29
+ }
37
30
  onFetch();
38
31
  setInitFetchDone(true);
39
- } catch (err) {
40
- console.log(err);
41
- }
42
-
43
- if (isMounted.current) {
44
- setLoading(false);
45
- }
46
- };
47
-
32
+ } catch (err) {
33
+ console.log(err);
34
+ }
35
+ if (isMounted.current) {
36
+ setLoading(false);
37
+ }
38
+ };
48
39
  useEffect(() => {
49
40
  isMounted.current = true;
50
41
  return () => {
51
42
  isMounted.current = false;
52
43
  };
53
44
  }, []);
54
-
55
- useEffect(() => {
56
- fetchData();
57
- }, [JSON.stringify(config)]);
58
-
45
+ useEffect(() => {
46
+ if(!stop) {
47
+ fetchData();
48
+ }
49
+ }, [JSON.stringify(config), stop]);
59
50
  return {
60
51
  data,
61
52
  loading,
62
- setData,
53
+ setData,
63
54
  initFetchDone
64
55
  }
65
- }
56
+ }
@@ -92,6 +92,7 @@ export default function IncidentsTimeline({
92
92
  if (selectedRange === "12") return baseMonths.map((m) => m.label);
93
93
  return baseWeeks.map((w) => w.label);
94
94
  }, [selectedRange, baseMonths, baseWeeks]);
95
+ console.log({filtersConfig})
95
96
 
96
97
  const getTooltipContent = useCallback(
97
98
  ({ item }) => {
@@ -6,28 +6,29 @@ import Widget from '../../../../../../../core/components/Dashboard/Widget/index.
6
6
  import Chart from '../../../../../../../core/components/Charts/PieChart/chart.jsx';
7
7
  import { getColors } from './config';
8
8
 
9
- function Locations({selectedSources = {}, data = [], loading = false, t = () => {}, options = {}, theme = {}}) {
9
+ function Locations({selectedSources = {}, data = {}, loading = false, t = () => {}, options = {}, theme = {}}) {
10
10
  const { countries = [] } = options;
11
11
  const colors = getColors(theme);
12
-
13
12
  const pieData = useMemo(() => {
14
- // eslint-disable-next-line no-shadow-restricted-names
15
- const { undefined, ...rest } = data;
16
- const total = Object.values(rest).reduce((all, val) => all + (val || 0), 0);
17
-
18
- return Object.keys(rest).map((key, index) => {
19
- const color = colors[index % colors.length];
20
-
21
- return {
22
- value: rest[key] || 0,
23
- percent: (rest[key] || 0) / total,
24
- color: color,
25
- label: findOptions(key, countries),
26
- key: key,
27
- };
28
- });
29
- }, [data, countries]);
30
-
13
+ const rest = data || {};
14
+
15
+ const total = Object.values(rest).reduce((sum, val) => sum + (val || 0), 0);
16
+
17
+ return Object.keys(rest).map((key, index) => {
18
+ const color = colors[index % colors.length];
19
+ const value = rest[key] || 0;
20
+
21
+ return {
22
+ value,
23
+ percent: total ? value / total : 0,
24
+ color,
25
+ label: findOptions(key, countries) || key,
26
+ key,
27
+ };
28
+ });
29
+ }, [data, countries, colors]);
30
+
31
+ console.log({data});
31
32
  const isEmpty = useMemo(
32
33
  () => Object.keys(data).filter((k) => !!data[k]).length === 0,
33
34
  [data],
@@ -24,13 +24,15 @@ function ChartsContainer({selectedSources = {}, isTradeActions = false, t = () =
24
24
  range: selectedRange,
25
25
  },
26
26
  stop: selectedSources?.loading,
27
- defaultData: [],
27
+ defaultData: {},
28
28
  }),
29
29
  [isTradeActions, selectedSources, selectedRange],
30
30
  );
31
31
 
32
32
  const { loading, data } = useWidgetFetch({config: defaultConfig, onFetch: () => setPreviousRange(selectedRange)});
33
33
 
34
+ console.log('ChartsContainer data:', data);
35
+
34
36
  return (
35
37
  <Widget
36
38
  title={isTradeActions ? t("Trade Actors") : t("Mining Sites")}
@@ -50,12 +52,13 @@ function ChartsContainer({selectedSources = {}, isTradeActions = false, t = () =
50
52
  options={options}
51
53
  />
52
54
  <Locations
53
- data={data?.locations}
55
+ data={data?.location}
54
56
  t={t}
55
57
  theme={theme}
56
58
  selectedSources={selectedSources}
57
59
  loading={loading}
58
60
  options={options}
61
+
59
62
  />
60
63
  <GenderDistribution
61
64
  selectedSources={selectedSources}
@@ -79,14 +79,16 @@ export const getColumns = ({t, goTo, user, options, activeTab, getRedirectLink,
79
79
  return <div className="daf-default-cell" />
80
80
  }
81
81
 
82
- const region = getLinkValue(all?.location?.administrativeLevel1, all?.location?.linking?.SCL);
82
+ const region = all?.location
83
+ ? getLinkValue(all?.location?.administrativeLevel1, all?.location?.linking?.SCL)
84
+ : (getLinkValue(all?.administrativeLevel1Name, all?.linking?.SCL) || all?.administrativeLevel1Name);
83
85
 
84
86
  return region ? <Tooltip title={region}>{region}</Tooltip> : '-';
85
87
  },
86
88
  },
87
89
  {
88
90
  dataIndex: 'territory',
89
- title: findOptions(user?.company?.country, options?.administrativeLevel2)?.length > 2 ? findOptions(user?.company?.country, options?.administrativeLevel2) : t("Territory"),
91
+ title: findOptions(user?.company?.country, options?.administrativeLevel2)?.length > 2 ? findOptions(user?.company?.country, options?.administrativeLevel2Name) : t("Territory"),
90
92
  ellipsis: true,
91
93
  show: true,
92
94
  render: (v, all) => {
@@ -94,7 +96,9 @@ export const getColumns = ({t, goTo, user, options, activeTab, getRedirectLink,
94
96
  return <div className="daf-default-cell" />
95
97
  }
96
98
 
97
- const district = getLinkValue(all?.location?.administrativeLevel2, all?.location?.linking?.SCL);
99
+ const district = all?.location
100
+ ? getLinkValue(all?.location?.administrativeLevel2, all?.location?.linking?.SCL)
101
+ : (getLinkValue(all?.administrativeLevel2, all?.linking?.SCL) || all?.administrativeLevel2);
98
102
 
99
103
  return district ? <Tooltip title={district}>{district}</Tooltip> : '-';
100
104
  },
@@ -79,7 +79,9 @@ export const getColumns = ({t, goTo, user, options, activeTab, getRedirectLink,
79
79
  return <div className="daf-default-cell" />
80
80
  }
81
81
 
82
- const region = getLinkValue(all?.location?.administrativeLevel1, all?.location?.linking?.SCL);
82
+ const region = all?.location
83
+ ? getLinkValue(all?.location?.administrativeLevel1, all?.location?.linking?.SCL)
84
+ : (getLinkValue(all?.administrativeLevel1Name, all?.linking?.SCL) || all?.administrativeLevel1Name);
83
85
 
84
86
  return region ? <Tooltip title={region}>{region}</Tooltip> : '-';
85
87
  },
@@ -94,11 +96,13 @@ export const getColumns = ({t, goTo, user, options, activeTab, getRedirectLink,
94
96
  return <div className="daf-default-cell" />
95
97
  }
96
98
 
97
- const district = getLinkValue(all?.location?.administrativeLevel2, all?.location?.linking?.SCL);
99
+ const district = all?.location
100
+ ? getLinkValue(all?.location?.administrativeLevel2, all?.location?.linking?.SCL)
101
+ : (getLinkValue(all?.administrativeLevel2, all?.linking?.SCL) || all?.administrativeLevel2);
98
102
 
99
103
  return district ? <Tooltip title={district}>{district}</Tooltip> : '-';
100
104
  },
101
- },
105
+ },
102
106
  {
103
107
  dataIndex: 'eventCategory',
104
108
  title: t('Category'),
@@ -43,7 +43,6 @@ export const getKeyIndicatorConfig = ({ t, data = {}, options = {} }) => [
43
43
  label: t("Legal Form"),
44
44
  render: () => {
45
45
  const subCategory = findOptions(data?.subCategory, options?.subCategoriesOptions || options?.subCategory);
46
- console.log({subCategory, initialSub: data?.subCategory, options: options?.subCategoriesOptions || options?.subCategory})
47
46
  if(subCategory?.length > 22) {
48
47
  const _subCategory = truncateString(subCategory, 22);
49
48
  return <Tooltip title={subCategory}>
@@ -2,6 +2,7 @@ import { leftIcons, leftBackgroundColorLocation, leftBackgroundColorStakeholder,
2
2
  import { findOptions } from '../../../../../../helpers/StringHelper.js';
3
3
 
4
4
  export const getFilterConfig = ({operatorData = {}, options = {}, filters = {}, t = () => {}, APP}) => {
5
+ console.log({operatorData})
5
6
  const productSet = new Set();
6
7
  const allTradeMineralOptions = [
7
8
  ...(operatorData?.suppliers || []),
@@ -33,17 +34,18 @@ const label = options?.[
33
34
  return option && index === self.findIndex((o) => o.value === option.value);
34
35
  });
35
36
 
36
- const value = filters.products ? { value: filters.products } : {};
37
- return [
38
- {
37
+ const value = filters?.products ? { value: filters?.products } : {};
38
+ return {
39
+ products: {
39
40
  label: t("Products"),
40
41
  placeholder: t("Select"),
41
42
  key: "products",
42
43
  type: "select",
43
- ...value,
44
+ // ...value,
45
+ style: { flex: 1 },
44
46
  options: combinedMineralOptions,
45
47
  },
46
- ];
48
+ };
47
49
  }
48
50
 
49
51
  export const getLeft = (data = {}, mapChildren = () => {}, supplierLocations = []) => {
@@ -1,4 +1,4 @@
1
- import { useEffect, useState, useMemo } from "react";
1
+ import { useEffect, useState, useMemo, useRef } from "react";
2
2
  import { useWidgetFetch } from "../../../../../hooks/useWidgetFetch.js";
3
3
  import { leftIcons, leftBackgroundColorLocation, leftBackgroundColorStakeholder, topIcons } from './config.js';
4
4
  import { findOptions } from '../../../../../../helpers/StringHelper.js';
@@ -8,6 +8,8 @@ import { getLeft, mapItem as _mapItem } from './helper.js';
8
8
  export const useTradeRelationship = ({
9
9
  id,
10
10
  selectedPartners,
11
+ isProductsFilterReady,
12
+ hasProducts,
11
13
  options,
12
14
  goTo,
13
15
  getRedirectLink,
@@ -19,26 +21,38 @@ export const useTradeRelationship = ({
19
21
  const [graphData, setGraphData] = useState({});
20
22
  const [loading, setLoading] = useState(false);
21
23
  const [fetchedProducts, setFetchedProducts] = useState(false);
22
-
23
- const config = useMemo(() => ({
24
- basepath: "analytics",
25
- url: `/widgets/trade-relationship-map`,
26
- filters: {
24
+ const initFetchDoneRef = useRef(false);
25
+
26
+ const product = useMemo(() => {
27
+ return filters?.products
28
+ }, [filters?.products]);
29
+
30
+ console.log({hasProducts, product, isProductsFilterReady, stop: !selectedPartners?.partners?.length
31
+ || selectedPartners?.loading || !isProductsFilterReady || (isProductsFilterReady && hasProducts && !product)},
32
+ !selectedPartners?.partners?.length,
33
+ selectedPartners?.loading,
34
+ !isProductsFilterReady,
35
+ (isProductsFilterReady && hasProducts && !product))
36
+ const config = useMemo(() => ({
37
+ basepath: "analytics",
38
+ url: `/widgets/trade-relationship-map`,
39
+ filters: {
27
40
  datastakeId: id,
28
- product: filters?.products,
29
- sources: selectedPartners?.partners || [],
30
- },
31
- stop: !selectedPartners?.partners?.length || selectedPartners?.loading,
32
- }), [id, filters?.products, selectedPartners?.partners, selectedPartners?.loading]);
33
-
34
- const { data } = useWidgetFetch({config: config});
41
+ ...(product && {product: product}),
42
+ sources: selectedPartners?.partners || [],
43
+ },
44
+ stop: !selectedPartners?.partners?.length
45
+ || selectedPartners?.loading || !isProductsFilterReady || (isProductsFilterReady && hasProducts && !product)
46
+ }), [id, product, selectedPartners?.partners, selectedPartners?.loading, isProductsFilterReady, hasProducts]);
47
+
48
+ const { data, loading: dataLoading } = useWidgetFetch({config: config});
35
49
 
36
50
  const mapItem = (data) => {
37
51
  return _mapItem(data, options, goTo, getRedirectLink, operatorData, APP);
38
52
  }
39
53
 
40
54
  useEffect(() => {
41
- if (id && selectedPartners?.partners?.length > 0 && fetchedProducts) {
55
+ if (id && selectedPartners?.partners?.length > 0) {
42
56
  const _fetch = async () => {
43
57
  setLoading(true);
44
58
 
@@ -156,5 +170,6 @@ export const useTradeRelationship = ({
156
170
  setGraphData,
157
171
  setLoading,
158
172
  data,
173
+ dataLoading
159
174
  }
160
175
  }