datastake-daf 0.6.745 → 0.6.747

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 (91) 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 +71 -7
  7. package/dist/hooks/index.js +2 -2
  8. package/dist/pages/index.css +1 -0
  9. package/dist/pages/index.js +5924 -32
  10. package/dist/services/index.js +23 -1
  11. package/package.json +1 -1
  12. package/src/@daf/core/components/Dashboard/Widget/ImageCarousel/index.jsx +75 -54
  13. package/src/@daf/core/components/Dashboard/Widget/ImageCarousel/style.js +44 -0
  14. package/src/@daf/core/components/Screens/TableScreen/TablePageWithTabs/index.jsx +128 -0
  15. package/src/@daf/{pages/pages → core/components/TableScreen}/TablePageWithTabs/index.jsx +3 -3
  16. package/src/@daf/hooks/useSources.js +1 -1
  17. package/src/@daf/pages/Documents/index.jsx +1 -1
  18. package/src/@daf/pages/Events/Activities/index.jsx +1 -1
  19. package/src/@daf/pages/Events/Incidents/index.jsx +1 -1
  20. package/src/@daf/pages/Events/index.jsx +1 -1
  21. package/src/@daf/pages/Locations/MineSite/index.jsx +1 -1
  22. package/src/@daf/pages/Locations/index.jsx +1 -1
  23. package/src/@daf/pages/Stakeholders/Operators/index.jsx +1 -1
  24. package/src/@daf/pages/Stakeholders/Workers/index.jsx +1 -1
  25. package/src/@daf/pages/Stakeholders/index.jsx +1 -1
  26. package/src/@daf/pages/Summary/Activities/Restoration/config.js +36 -0
  27. package/src/@daf/pages/Summary/Activities/Restoration/helper.js +98 -0
  28. package/src/@daf/pages/Summary/Activities/Restoration/index.jsx +178 -0
  29. package/src/@daf/pages/Summary/Minesite/components/LocationMap/index.js +61 -0
  30. package/src/@daf/pages/Summary/Minesite/components/MineSiteDetails/config.js +77 -0
  31. package/src/@daf/pages/Summary/Minesite/components/MineSiteDetails/index.js +47 -0
  32. package/src/@daf/pages/Summary/Minesite/components/StakeholderMapping/config.js +26 -0
  33. package/src/@daf/pages/Summary/Minesite/components/StakeholderMapping/helper.js +64 -0
  34. package/src/@daf/pages/Summary/Minesite/components/StakeholderMapping/index.js +56 -0
  35. package/src/@daf/pages/Summary/Minesite/index.jsx +162 -0
  36. package/src/@daf/pages/Summary/Operator/components/Governance/config.js +26 -0
  37. package/src/@daf/pages/Summary/Operator/components/Governance/helper.js +61 -0
  38. package/src/@daf/pages/Summary/Operator/components/Governance/index.js +55 -0
  39. package/src/@daf/pages/Summary/Operator/components/KeyInformation/config.js +84 -0
  40. package/src/@daf/pages/Summary/Operator/components/KeyInformation/index.js +46 -0
  41. package/src/@daf/pages/Summary/Operator/components/TradeRelationships/config.js +40 -0
  42. package/src/@daf/pages/Summary/Operator/components/TradeRelationships/helper.js +98 -0
  43. package/src/@daf/pages/Summary/Operator/components/TradeRelationships/hook.js +160 -0
  44. package/src/@daf/pages/Summary/Operator/components/TradeRelationships/index.js +83 -0
  45. package/src/@daf/pages/Summary/Operator/hook.js +176 -0
  46. package/src/@daf/pages/Summary/Operator/index.jsx +170 -0
  47. package/src/@daf/pages/Summary/components/InformationAvailability/components/Contributions/index.js +36 -0
  48. package/src/@daf/pages/Summary/components/InformationAvailability/components/InformationCompleteness/index.js +58 -0
  49. package/src/@daf/pages/Summary/components/InformationAvailability/index.js +42 -0
  50. package/src/@daf/pages/Summary/hook.js +188 -0
  51. package/src/@daf/services/OperatorService.js +16 -0
  52. package/src/@daf/services/SourceService.js +1 -1
  53. package/src/helpers/StringHelper.js +7 -0
  54. package/src/pages.js +6 -4
  55. package/src/@daf/pages/Events/Incidents2/columns.js +0 -176
  56. package/src/@daf/pages/Events/Incidents2/config.js +0 -170
  57. package/src/@daf/pages/Events/Incidents2/create.jsx +0 -104
  58. package/src/@daf/pages/Events/Incidents2/index.jsx +0 -156
  59. /package/src/@daf/pages/{dashboards → Dashboards}/SupplyChain/components/ChartsContainer/components/GenderDistribution/config.js +0 -0
  60. /package/src/@daf/pages/{dashboards → Dashboards}/SupplyChain/components/ChartsContainer/components/GenderDistribution/index.js +0 -0
  61. /package/src/@daf/pages/{dashboards → Dashboards}/SupplyChain/components/ChartsContainer/components/Identification/hook.js +0 -0
  62. /package/src/@daf/pages/{dashboards → Dashboards}/SupplyChain/components/ChartsContainer/components/Identification/index.js +0 -0
  63. /package/src/@daf/pages/{dashboards → Dashboards}/SupplyChain/components/ChartsContainer/components/Locations/config.js +0 -0
  64. /package/src/@daf/pages/{dashboards → Dashboards}/SupplyChain/components/ChartsContainer/components/Locations/index.js +0 -0
  65. /package/src/@daf/pages/{dashboards → Dashboards}/SupplyChain/components/ChartsContainer/index.js +0 -0
  66. /package/src/@daf/pages/{dashboards → Dashboards}/SupplyChain/components/KeyIndicators/config.js +0 -0
  67. /package/src/@daf/pages/{dashboards → Dashboards}/SupplyChain/components/KeyIndicators/index.js +0 -0
  68. /package/src/@daf/pages/{dashboards → Dashboards}/SupplyChain/components/SupplyChainMap/index.js +0 -0
  69. /package/src/@daf/pages/{dashboards → Dashboards}/SupplyChain/components/TradeRelationships/index.js +0 -0
  70. /package/src/@daf/pages/{dashboards → Dashboards}/SupplyChain/config.js +0 -0
  71. /package/src/@daf/pages/{dashboards → Dashboards}/SupplyChain/index.jsx +0 -0
  72. /package/src/@daf/pages/{dashboards → Dashboards}/UserDashboard/components/AccumulationGraph/hook.js +0 -0
  73. /package/src/@daf/pages/{dashboards → Dashboards}/UserDashboard/components/AccumulationGraph/index.jsx +0 -0
  74. /package/src/@daf/pages/{dashboards → Dashboards}/UserDashboard/components/ContributionsGraph/helper.js +0 -0
  75. /package/src/@daf/pages/{dashboards → Dashboards}/UserDashboard/components/ContributionsGraph/hook.js +0 -0
  76. /package/src/@daf/pages/{dashboards → Dashboards}/UserDashboard/components/ContributionsGraph/index.jsx +0 -0
  77. /package/src/@daf/pages/{dashboards → Dashboards}/UserDashboard/components/CustomSegment/index.jsx +0 -0
  78. /package/src/@daf/pages/{dashboards → Dashboards}/UserDashboard/components/DataChainOfCustody/index.jsx +0 -0
  79. /package/src/@daf/pages/{dashboards → Dashboards}/UserDashboard/components/DataCompilation/index.jsx +0 -0
  80. /package/src/@daf/pages/{dashboards → Dashboards}/UserDashboard/components/DataConsilidation/index.jsx +0 -0
  81. /package/src/@daf/pages/{dashboards → Dashboards}/UserDashboard/components/KeyIndicators/config.js +0 -0
  82. /package/src/@daf/pages/{dashboards → Dashboards}/UserDashboard/components/KeyIndicators/index.jsx +0 -0
  83. /package/src/@daf/pages/{dashboards → Dashboards}/UserDashboard/components/MineSites/config.js +0 -0
  84. /package/src/@daf/pages/{dashboards → Dashboards}/UserDashboard/components/MineSites/helper.js +0 -0
  85. /package/src/@daf/pages/{dashboards → Dashboards}/UserDashboard/components/MineSites/index.jsx +0 -0
  86. /package/src/@daf/pages/{dashboards → Dashboards}/UserDashboard/components/Triangulation/config.js +0 -0
  87. /package/src/@daf/pages/{dashboards → Dashboards}/UserDashboard/components/Triangulation/hook.js +0 -0
  88. /package/src/@daf/pages/{dashboards → Dashboards}/UserDashboard/components/Triangulation/index.jsx +0 -0
  89. /package/src/@daf/pages/{dashboards → Dashboards}/UserDashboard/config.js +0 -0
  90. /package/src/@daf/pages/{dashboards → Dashboards}/UserDashboard/index.jsx +0 -0
  91. /package/src/@daf/pages/{dashboards → Dashboards}/helper.js +0 -0
@@ -0,0 +1,176 @@
1
+ import { useState, useMemo, useCallback, useEffect } from "react"
2
+ import { debounce } from "lodash";
3
+ import { StorageManager } from "../../../../helpers/StorageManager.js";
4
+
5
+ export const useSummary = ({
6
+ getOne,
7
+ getMultiple,
8
+ id,
9
+ hasSelect = false,
10
+ storageKey,
11
+ data,
12
+ isPdf,
13
+ params,
14
+ partners,
15
+ selectedPartners,
16
+ user,
17
+ t,
18
+ theme = {},
19
+ service
20
+ }) => {
21
+ const [search, setSearch] = useState("");
22
+ const [debouncedSearch, setDebouncedSearch] = useState("");
23
+ const [hasInitialized, setHasInitialized] = useState(false);
24
+ const [singleItemData, setSingleItemData] = useState();
25
+ const [loading, setLoading] = useState(false);
26
+ const [_partners, _setPartners] = useState();
27
+
28
+ const [selectedItem, setSelectedItem] = useState(undefined);
29
+
30
+ const dataOptions = useMemo(() => {
31
+ const mappedData = data?.map((item) => ({
32
+ label: item?.name,
33
+ value: item?.datastakeId
34
+ })) || [];
35
+
36
+ const storedData = StorageManager.get(storageKey);
37
+ if (storedData) {
38
+ try {
39
+ const parsedStoredData = JSON.parse(storedData);
40
+ const existsInData = mappedData?.find(item => item.value === parsedStoredData.value);
41
+
42
+ if (!existsInData) {
43
+ return [...mappedData, parsedStoredData];
44
+ }
45
+ } catch (error) {
46
+ console.log('Error parsing stored data:', error);
47
+ }
48
+ }
49
+
50
+ return mappedData;
51
+ }, [data, hasSelect, storageKey])
52
+
53
+ useEffect(() => {
54
+ if (hasSelect && dataOptions && dataOptions.length > 0 && !debouncedSearch && !hasInitialized) {
55
+ let selectedValue;
56
+
57
+ if (isPdf) {
58
+ selectedValue = id;
59
+ } else {
60
+ const storedData = StorageManager.get(storageKey);
61
+ if (storedData) {
62
+ try {
63
+ const parsedData = JSON.parse(storedData);
64
+ const existsInOptions = dataOptions?.find((item) => item?.value === parsedData?.value);
65
+ selectedValue = existsInOptions ? parsedData?.value : (Array.isArray(dataOptions) ? dataOptions[0]?.value : undefined);
66
+ } catch (error) {
67
+ console.log('Error parsing stored data:', error);
68
+ selectedValue = Array.isArray(dataOptions) ? dataOptions[0]?.value : undefined;
69
+ }
70
+ } else {
71
+ selectedValue = Array.isArray(dataOptions) ? dataOptions[0]?.value : undefined;
72
+ }
73
+ }
74
+
75
+ setSelectedItem(selectedValue);
76
+ setHasInitialized(true);
77
+ }
78
+ }, [hasSelect, storageKey, isPdf, id, debouncedSearch, hasInitialized, dataOptions]);
79
+
80
+ useEffect(() => {
81
+ if (selectedItem) {
82
+ const selectedData = data?.find((item) => item?.datastakeId === selectedItem);
83
+ if(selectedData) {
84
+ const saved = {
85
+ label: selectedData.name,
86
+ value: selectedData.datastakeId,
87
+ }
88
+ StorageManager.set(storageKey, JSON.stringify(saved));
89
+ }
90
+ }
91
+ }, [selectedItem, storageKey]);
92
+
93
+ const debouncedSetSearch = useMemo(
94
+ () => debounce((value) => setDebouncedSearch(value), 300),
95
+ []
96
+ );
97
+
98
+ const onSearch = useCallback((value) => {
99
+ setSearch(value);
100
+ debouncedSetSearch(value);
101
+ }, [debouncedSetSearch]);
102
+
103
+
104
+ useEffect(() => {
105
+ setDebouncedSearch("");
106
+ }, [selectedItem]);
107
+
108
+ const filters = useMemo(() => {
109
+ return {
110
+ pagination: { size: 20, page: 1 },
111
+ ...(debouncedSearch
112
+ ? { search: { qs: debouncedSearch, fields: ["name","datastakeId","orgShortName"] } }
113
+ : {}),
114
+ };
115
+ }, [debouncedSearch]);
116
+
117
+ useEffect(() => {
118
+ if (_partners !== undefined) {
119
+ if ((params?.id !== null || (isPdf && id !== null)) && !hasSelect) {
120
+ getOne(params?.id || id, { sources: _partners });
121
+ }
122
+ }
123
+ if (hasSelect && !params?.id) {
124
+ getMultiple(filters);
125
+ }
126
+ }, [params?.id, hasSelect, getOne, getMultiple, _partners, isPdf, id, filters]);
127
+
128
+ useEffect(() => {
129
+ if (selectedItem && _partners !== undefined) {
130
+ const fetchSingleItem = async () => {
131
+ setLoading(true);
132
+ try {
133
+ const { data } = await service.getOne(selectedItem, { sources: _partners });
134
+ setSingleItemData(data);
135
+ } catch (error) {
136
+ console.log(error);
137
+ } finally {
138
+ setLoading(false);
139
+ }
140
+ };
141
+ fetchSingleItem();
142
+ }
143
+ }, [selectedItem, service, _partners]);
144
+
145
+ useEffect(() => {
146
+ _setPartners(selectedPartners?.partners);
147
+ }, [selectedPartners]);
148
+
149
+ const sourceOptions = useMemo(() => {
150
+ return partners?.map((partner) => {
151
+ const isOwnData = partner.id === user?.company?.id;
152
+
153
+ return {
154
+ label: isOwnData ? t("Own Data") : partner.nickName,
155
+ value: partner.id,
156
+ avatar: isOwnData ? <span>OWN</span> : undefined,
157
+ background: isOwnData ? theme.colorPrimary7 : undefined,
158
+ color: isOwnData ? "white" : undefined,
159
+ };
160
+ });
161
+ }, [partners, user]);
162
+
163
+ return {
164
+ selectedItem,
165
+ setSelectedItem,
166
+ dataOptions,
167
+ search,
168
+ debouncedSearch,
169
+ onSearch,
170
+ setSearch,
171
+ setDebouncedSearch,
172
+ sourceOptions,
173
+ singleItemData,
174
+ loading,
175
+ }
176
+ }
@@ -0,0 +1,170 @@
1
+ import React from 'react'
2
+ import DashboardLayout from '../../../core/components/Dashboard/DashboardLayout/index.jsx'
3
+ import { Select, Spin } from 'antd'
4
+ import { useSummary } from '../hook.js'
5
+ import Header from '../../../core/components/Header/index.jsx'
6
+ import Multiselect from '../../../core/components/Select/MultiSelect/index.jsx'
7
+ import KeyInformation from './components/KeyInformation/index.js'
8
+ import InformationAvailability from '../components/InformationAvailability/index.js'
9
+ import TradeRelationships from './components/TradeRelationships/index.js'
10
+ import Governance from './components/Governance/index.js'
11
+
12
+ const OperatorSummary = ({
13
+ hasSelect = false,
14
+ loading = false,
15
+ getSingleData = () => {},
16
+ getMultipleData = () => {},
17
+ data = [],
18
+ id = '',
19
+ storageKey = '',
20
+ isPdf = false,
21
+ params = {},
22
+ partners = [],
23
+ selectedPartners = {},
24
+ user = {},
25
+ t = () => {},
26
+ theme = {},
27
+ service,
28
+ options = {},
29
+ goTo = () => {},
30
+ getRedirectLink = () => {},
31
+ goBack = () => {},
32
+ onIdChange = () => {}
33
+ }) => {
34
+ const {
35
+ selectedItem,
36
+ setSelectedItem,
37
+ dataOptions,
38
+ search,
39
+ debouncedSearch,
40
+ onSearch,
41
+ setSearch,
42
+ setDebouncedSearch,
43
+ sourceOptions,
44
+ setSelectedPartners,
45
+ singleItemData,
46
+ loading: loadingData,
47
+ } = useSummary({
48
+ getOne: getSingleData,
49
+ getMultiple: getMultipleData,
50
+ id,
51
+ hasSelect,
52
+ storageKey,
53
+ data,
54
+ isPdf: false,
55
+ params,
56
+ partners,
57
+ selectedPartners,
58
+ user,
59
+ t,
60
+ theme,
61
+ service,
62
+ onIdChange,
63
+ });
64
+
65
+ return (
66
+ <DashboardLayout
67
+ header={
68
+ <Header
69
+ title={t('Operator Summary')}
70
+ className="with-border-header h-w-btn-header no-px-body"
71
+ goBackTo={!hasSelect && goBack}
72
+ addedHeaderFirst
73
+ actionButtons={[
74
+ {
75
+ tooltip: t("Details"),
76
+ icon: "FileEdit",
77
+ onClick: () => {
78
+ goTo(getRedirectLink(`/app/view/operators/${params?.id ? params?.id : selectedItem}`));
79
+ },
80
+ },
81
+ {
82
+ tooltip: t("Find Data"),
83
+ icon: "Search",
84
+ onClick: () => {},
85
+ disabled: true,
86
+ },
87
+ ]}
88
+ addedHeader={
89
+ <div className="flex flex-row gap-4" style={{ marginRight: 8 }}>
90
+ <Multiselect
91
+ options={[...sourceOptions]}
92
+ isAvatarGroup
93
+ selectionType="checkbox"
94
+ key={partners?.length}
95
+ canUnselectLast={false}
96
+ onChange={(selected) => {
97
+ setSelectedPartners((prev) => ({
98
+ ...prev,
99
+ partners: selected,
100
+ loading: false,
101
+ }));
102
+ }}
103
+ dropDownWidth={200}
104
+ defaultSelected={(partners || []).map((p) => p.id) || []}
105
+ />
106
+ </div>
107
+ }
108
+ />
109
+ }
110
+ >
111
+ {hasSelect && (
112
+ <section>
113
+ <Select
114
+ showSearch
115
+ debounceTimeout={300}
116
+ onSearch={onSearch}
117
+ isSingle
118
+ style={{ height: "40px", width: "100%" }}
119
+ value={selectedItem}
120
+ onChange={setSelectedItem}
121
+ options={dataOptions}
122
+ filterOption={false}
123
+ loading={loading}
124
+ notFoundContent={loading ? <Spin size="small" /> : null}
125
+ />
126
+ </section>
127
+ )}
128
+ <KeyInformation
129
+ options={options}
130
+ selectedPartners={selectedPartners}
131
+ t={t}
132
+ id={params?.id || selectedItem}
133
+ data={hasSelect ? singleItemData : data}
134
+ loading={loading}
135
+ />
136
+ <section>
137
+ <InformationAvailability
138
+ selectedPartners={selectedPartners}
139
+ t={t}
140
+ id={params?.id || selectedItem}
141
+ />
142
+ </section>
143
+ <section>
144
+ <TradeRelationships
145
+ selectedPartners={selectedPartners}
146
+ t={t}
147
+ id={params?.id || selectedItem}
148
+ options={options}
149
+ goTo={goTo}
150
+ getRedirectLink={getRedirectLink}
151
+ operatorData={hasSelect ? singleItemData : data}
152
+ />
153
+ </section>
154
+ <section>
155
+ <Governance
156
+ selectedPartners={selectedPartners}
157
+ t={t}
158
+ id={params?.id || selectedItem}
159
+ options={options}
160
+ goTo={goTo}
161
+ getRedirectLink={getRedirectLink}
162
+ operatorData={hasSelect ? singleItemData : data}
163
+ />
164
+ </section>
165
+
166
+ </DashboardLayout>
167
+ )
168
+ }
169
+
170
+ export default OperatorSummary
@@ -0,0 +1,36 @@
1
+ import React from 'react'
2
+ import Widget from '../../../../../../core/components/Dashboard/Widget/index.jsx';
3
+ import BarChart from '../../../../../../core/components/Charts/BarChart/index.jsx';
4
+
5
+ const Contributions = ({
6
+ data = {},
7
+ loading = false,
8
+ t = () => {},
9
+ }) => {
10
+ return (
11
+ <Widget
12
+ title={t("Contributions")}
13
+ className="with-border-header h-w-btn-header"
14
+ loading={loading}
15
+ >
16
+ <BarChart
17
+ data={data?.stakeholders || []}
18
+ xFieldKey="completedDatapoints"
19
+ yFieldKey="author"
20
+ renderTooltipContent={(title, item) => {
21
+ return {
22
+ title: title,
23
+ items: [
24
+ {
25
+ label: t("Datapoints"),
26
+ value: item?.[0]?.data?.completedDatapoints || 0,
27
+ },
28
+ ],
29
+ };
30
+ }}
31
+ />
32
+ </Widget>
33
+ )
34
+ }
35
+
36
+ export default Contributions
@@ -0,0 +1,58 @@
1
+ import React, { useMemo } from 'react'
2
+ import Widget from '../../../../../../core/components/Dashboard/Widget/index.jsx';
3
+ import RadialBarChart from '../../../../../../core/components/Charts/RadialBarChart/index.jsx';
4
+
5
+ const InformationCompleteness = ({
6
+ data = {},
7
+ loading = false,
8
+ t = () => {},
9
+ }) => {
10
+
11
+ const graphData = useMemo(() => {
12
+ const keys = {
13
+ ownDataCompletion: data?.ownDataCompletion || 0,
14
+ consolidatedCompletion: data?.consolidatedCompletion || 0,
15
+ };
16
+
17
+ const _data = Object.keys(keys).map((key) => {
18
+ const item = keys[key];
19
+
20
+ if (!Array.isArray(item)) {
21
+ return {
22
+ label: key?.includes("own") ? t("Own Data") : t("Consolidated"),
23
+ value: item,
24
+ };
25
+ }
26
+ });
27
+
28
+ return _data.filter((item) => item !== undefined);
29
+ }, [data]);
30
+
31
+ return (
32
+ <Widget
33
+ title={t("Information Completeness")}
34
+ loading={loading}
35
+ className="with-border-header h-w-btn-header"
36
+ >
37
+ <RadialBarChart
38
+ data={graphData}
39
+ renderTooltipContent={(title, item) => {
40
+ const value =
41
+ item?.[0]?.data?.value > 100 ? 100 : item?.[0]?.data?.value || 0;
42
+
43
+ return {
44
+ title: title,
45
+ items: [
46
+ {
47
+ label: t("Completion"),
48
+ value: `${value}%`,
49
+ },
50
+ ],
51
+ };
52
+ }}
53
+ />
54
+ </Widget>
55
+ )
56
+ }
57
+
58
+ export default InformationCompleteness
@@ -0,0 +1,42 @@
1
+ import React, { useMemo } from 'react'
2
+ import { useWidgetFetch } from '../../../../hooks/useWidgetFetch.js';
3
+ import Widget from '../../../../core/components/Dashboard/Widget/index.jsx';
4
+ import InformationCompleteness from './components/InformationCompleteness/index.js';
5
+ import Contributions from './components/Contributions/index.js';
6
+
7
+ const InformationAvailability = ({
8
+ selectedPartners = {},
9
+ t = () => {},
10
+ id,
11
+ }) => {
12
+ const defaultFetchConfig = useMemo(
13
+ () => ({
14
+ basepath: "analytics",
15
+ url: "/widgets/completeness",
16
+ defaultData: [],
17
+ stop: selectedPartners?.loading,
18
+ filters: {
19
+ datastakeId: id,
20
+ sources: selectedPartners?.partners || [],
21
+ },
22
+ }),
23
+ [id, selectedPartners],
24
+ );
25
+
26
+ const { data, loading } = useWidgetFetch({config: defaultFetchConfig});
27
+
28
+ return (
29
+ <Widget
30
+ title={t("Information Availability")}
31
+ loading={loading}
32
+ className="with-border-header h-w-btn-header"
33
+ >
34
+ <div className="flex flex-row flex-col-mobile gap-6">
35
+ <InformationCompleteness data={data} loading={loading} t={t} />
36
+ <Contributions data={data} loading={loading} t={t} />
37
+ </div>
38
+ </Widget>
39
+ )
40
+ }
41
+
42
+ export default InformationAvailability
@@ -0,0 +1,188 @@
1
+ import { useState, useMemo, useCallback, useEffect } from "react"
2
+ import { debounce } from "lodash";
3
+ import { StorageManager } from "../../../helpers/StorageManager.js";
4
+
5
+ export const useSummary = ({
6
+ getOne,
7
+ getMultiple,
8
+ id,
9
+ hasSelect = false,
10
+ storageKey,
11
+ data,
12
+ isPdf,
13
+ params,
14
+ partners,
15
+ selectedPartners,
16
+ user,
17
+ t,
18
+ theme = {},
19
+ service,
20
+ onIdChange = () => {}
21
+ }) => {
22
+ const [search, setSearch] = useState("");
23
+ const [debouncedSearch, setDebouncedSearch] = useState("");
24
+ const [hasInitialized, setHasInitialized] = useState(false);
25
+ const [singleItemData, setSingleItemData] = useState();
26
+ const [loading, setLoading] = useState(false);
27
+ const [_partners, _setPartners] = useState();
28
+
29
+ const [selectedItem, setSelectedItem] = useState(undefined);
30
+
31
+ const dataOptions = useMemo(() => {
32
+ if(hasSelect) {
33
+ const mappedData = Array.isArray(data) ? data.map((item) => ({
34
+ label: item?.name,
35
+ value: item?.datastakeId
36
+ })) : [];
37
+
38
+ const storedData = StorageManager.get(storageKey);
39
+ if (storedData) {
40
+ try {
41
+ const parsedStoredData = JSON.parse(storedData);
42
+ const existsInData = mappedData?.find(item => item.value === parsedStoredData.value);
43
+
44
+ if (!existsInData) {
45
+ return [...mappedData, parsedStoredData];
46
+ }
47
+ } catch (error) {
48
+ console.log('Error parsing stored data:', error);
49
+ }
50
+ }
51
+
52
+ return mappedData;
53
+ }
54
+ }, [data, hasSelect, storageKey])
55
+
56
+ useEffect(() => {
57
+ if (hasSelect && dataOptions && dataOptions.length > 0 && !debouncedSearch && !hasInitialized) {
58
+ let selectedValue;
59
+
60
+ if (isPdf) {
61
+ selectedValue = id;
62
+ } else {
63
+ const storedData = StorageManager.get(storageKey);
64
+ if (storedData) {
65
+ try {
66
+ const parsedData = JSON.parse(storedData);
67
+ const existsInOptions = dataOptions?.find((item) => item?.value === parsedData?.value);
68
+ selectedValue = existsInOptions ? parsedData?.value : (Array.isArray(dataOptions) ? dataOptions[0]?.value : undefined);
69
+ } catch (error) {
70
+ console.log('Error parsing stored data:', error);
71
+ selectedValue = Array.isArray(dataOptions) ? dataOptions[0]?.value : undefined;
72
+ }
73
+ } else {
74
+ selectedValue = Array.isArray(dataOptions) ? dataOptions[0]?.value : undefined;
75
+ }
76
+ }
77
+
78
+ setSelectedItem(selectedValue);
79
+ setHasInitialized(true);
80
+ }
81
+ }, [hasSelect, storageKey, isPdf, id, debouncedSearch, hasInitialized, dataOptions]);
82
+
83
+ useEffect(() => {
84
+ if (selectedItem && Array.isArray(data)) {
85
+ const selectedData = data.find((item) => item?.datastakeId === selectedItem);
86
+ if(selectedData) {
87
+ const saved = {
88
+ label: selectedData.name,
89
+ value: selectedData.datastakeId,
90
+ }
91
+ StorageManager.set(storageKey, JSON.stringify(saved));
92
+ }
93
+ }
94
+ }, [selectedItem, storageKey, data]);
95
+
96
+ const debouncedSetSearch = useMemo(
97
+ () => debounce((value) => setDebouncedSearch(value), 300),
98
+ []
99
+ );
100
+
101
+ const onSearch = useCallback((value) => {
102
+ setSearch(value);
103
+ debouncedSetSearch(value);
104
+ }, [debouncedSetSearch]);
105
+
106
+
107
+ useEffect(() => {
108
+ setDebouncedSearch("");
109
+ }, [selectedItem]);
110
+
111
+ const filters = useMemo(() => {
112
+ return {
113
+ pagination: { size: 20, page: 1 },
114
+ ...(debouncedSearch
115
+ ? { search: { qs: debouncedSearch, fields: ["name","datastakeId","orgShortName"] } }
116
+ : {}),
117
+ };
118
+ }, [debouncedSearch]);
119
+
120
+ useEffect(() => {
121
+ if (_partners !== undefined) {
122
+ if ((params?.id !== null || (isPdf && id !== null)) && !hasSelect) {
123
+ getOne({ datastakeId: params?.id || id, sources: _partners });
124
+ }
125
+ }
126
+ if (hasSelect && !params?.id) {
127
+ getMultiple(filters);
128
+ }
129
+ }, [params?.id, hasSelect, getOne, getMultiple, _partners, isPdf, id, filters]);
130
+
131
+ useEffect(() => {
132
+ if (selectedItem && _partners !== undefined) {
133
+ const fetchSingleItem = async () => {
134
+ setLoading(true);
135
+ try {
136
+ const { data } = await service.getOne(selectedItem, { sources: _partners });
137
+ setSingleItemData(data);
138
+ } catch (error) {
139
+ console.log(error);
140
+ } finally {
141
+ setLoading(false);
142
+ }
143
+ };
144
+ fetchSingleItem();
145
+ }
146
+ }, [selectedItem, service, _partners]);
147
+
148
+ useEffect(() => {
149
+ _setPartners(selectedPartners?.partners);
150
+ }, [selectedPartners]);
151
+
152
+ useEffect(() => {
153
+ const currentId = params?.id || selectedItem;
154
+ if(typeof onIdChange === 'function') {
155
+ if (currentId) {
156
+ onIdChange(currentId);
157
+ }
158
+ }
159
+ }, [params?.id, selectedItem, onIdChange]);
160
+
161
+ const sourceOptions = useMemo(() => {
162
+ return (partners || [])?.map((partner) => {
163
+ const isOwnData = partner.id === user?.company?.id;
164
+
165
+ return {
166
+ label: isOwnData ? t("Own Data") : partner.nickName,
167
+ value: partner.id,
168
+ avatar: isOwnData ? <span>OWN</span> : undefined,
169
+ background: isOwnData ? theme.colorPrimary7 : undefined,
170
+ color: isOwnData ? "white" : undefined,
171
+ };
172
+ });
173
+ }, [partners, user, hasSelect]);
174
+
175
+ return {
176
+ selectedItem,
177
+ setSelectedItem,
178
+ dataOptions,
179
+ search,
180
+ debouncedSearch,
181
+ onSearch,
182
+ setSearch,
183
+ setDebouncedSearch,
184
+ sourceOptions,
185
+ singleItemData,
186
+ loading,
187
+ }
188
+ }
@@ -14,8 +14,24 @@ const namespaceEnums = {
14
14
 
15
15
  class OperatorService extends BaseService {
16
16
  get(params) {
17
+ const { datastakeId, ...rest } = params;
18
+ if(datastakeId) {
19
+ return this.apiGet({
20
+ url: `/stakeholder/${datastakeId}`,
21
+ params: {...rest},
22
+ isApp: true,
23
+ });
24
+ }
17
25
  return this.apiGet({
18
26
  url: "/stakeholder",
27
+ params: {...rest},
28
+ isApp: true,
29
+ });
30
+ }
31
+
32
+ getOne(id, params) {
33
+ return this.apiGet({
34
+ url: `/stakeholder/${id}`,
19
35
  params,
20
36
  isApp: true,
21
37
  });
@@ -28,7 +28,7 @@ class SourceService extends BaseService {
28
28
 
29
29
  getSources({type,id}) {
30
30
  return this.apiGet({
31
- url: `/${type}/sources-for-subject/${id}`,
31
+ url: `/${type}/sources/${id}`,
32
32
  });
33
33
  }
34
34
  }