datastake-daf 0.6.720 → 0.6.722
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 +458 -437
- package/dist/context/index.js +7 -1
- package/dist/hooks/index.js +4660 -20
- package/dist/layouts/index.js +455 -432
- package/dist/pages/index.js +2014 -452
- package/dist/services/index.js +7 -1
- package/dist/utils/index.js +455 -432
- package/package.json +1 -1
- package/src/@daf/core/components/EditForm/form.jsx +3 -6
- package/src/@daf/core/components/EditForm/storyConfig2.js +23477 -10904
- package/src/@daf/core/components/Icon/configs/index.js +4 -0
- package/src/@daf/core/components/Icon/configs/partnerIcon.js +8 -0
- package/src/@daf/core/components/Icon/configs/userIcon.js +8 -0
- package/src/@daf/core/components/Screens/Admin/AdminViews/components/Users/helper.js +1 -1
- package/src/@daf/hooks/useWidgetFetch.js +1 -0
- package/src/@daf/pages/dashboards/SupplyChain/components/ChartsContainer/components/Identification/hook.js +1 -1
- package/src/@daf/pages/dashboards/UserDashboard/components/AccumulationGraph/hook.js +139 -0
- package/src/@daf/pages/dashboards/UserDashboard/components/AccumulationGraph/index.jsx +78 -0
- package/src/@daf/pages/dashboards/UserDashboard/components/ContributionsGraph/helper.js +75 -0
- package/src/@daf/pages/dashboards/UserDashboard/components/ContributionsGraph/hook.js +46 -0
- package/src/@daf/pages/dashboards/UserDashboard/components/ContributionsGraph/index.jsx +49 -0
- package/src/@daf/pages/dashboards/UserDashboard/components/CustomSegment/index.jsx +26 -0
- package/src/@daf/pages/dashboards/UserDashboard/components/DataChainOfCustody/index.jsx +18 -0
- package/src/@daf/pages/dashboards/UserDashboard/components/DataCompilation/index.jsx +69 -0
- package/src/@daf/pages/dashboards/UserDashboard/components/DataConsilidation/index.jsx +72 -0
- package/src/@daf/pages/dashboards/UserDashboard/components/KeyIndicators/config.js +120 -0
- package/src/@daf/pages/dashboards/UserDashboard/components/KeyIndicators/index.jsx +52 -0
- package/src/@daf/pages/dashboards/UserDashboard/components/MineSites/config.js +22 -0
- package/src/@daf/pages/dashboards/UserDashboard/components/MineSites/helper.js +142 -0
- package/src/@daf/pages/dashboards/UserDashboard/components/MineSites/index.jsx +209 -0
- package/src/@daf/pages/dashboards/UserDashboard/components/Triangulation/config.js +20 -0
- package/src/@daf/pages/dashboards/UserDashboard/components/Triangulation/hook.js +87 -0
- package/src/@daf/pages/dashboards/UserDashboard/components/Triangulation/index.jsx +68 -0
- package/src/@daf/pages/dashboards/UserDashboard/config.js +24 -24
- package/src/@daf/pages/dashboards/UserDashboard/index.jsx +56 -0
- package/src/@daf/services/AuthenticationService.js +7 -1
- package/src/pages.js +2 -1
- package/dist/style/datastake/mapbox-gl.css +0 -330
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import CustomIcon from '../../../../../core/components/Icon/CustomIcon.jsx';
|
|
3
|
+
|
|
4
|
+
export const getRowConfig = ({ t, data = {}, goTo, getRedirectLink, theme = {} }) => [
|
|
5
|
+
{
|
|
6
|
+
label: (
|
|
7
|
+
<div className="flex">
|
|
8
|
+
<div className="flex-1">{t("Monitored Locations")}</div>
|
|
9
|
+
<div
|
|
10
|
+
className="cursor-pointer"
|
|
11
|
+
onClick={() => goTo(getRedirectLink("/app/locations"))}
|
|
12
|
+
>
|
|
13
|
+
<CustomIcon
|
|
14
|
+
name="LinkNewTab"
|
|
15
|
+
width={16}
|
|
16
|
+
height={16}
|
|
17
|
+
color={theme.colorPrimary}
|
|
18
|
+
/>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
),
|
|
22
|
+
render: () => {
|
|
23
|
+
return <span>{data.locations ?? 0}</span>;
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
label: (
|
|
28
|
+
<div className="flex">
|
|
29
|
+
<div className="flex-1">{t("Identified Stakeholders")}</div>
|
|
30
|
+
<div
|
|
31
|
+
className="cursor-pointer"
|
|
32
|
+
onClick={() => goTo(getRedirectLink("/app/stakeholders"))}
|
|
33
|
+
>
|
|
34
|
+
<CustomIcon
|
|
35
|
+
name="LinkNewTab"
|
|
36
|
+
width={16}
|
|
37
|
+
height={16}
|
|
38
|
+
color={theme.colorPrimary}
|
|
39
|
+
/>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
),
|
|
43
|
+
render: () => <span>{data?.stakeholders ?? 0}</span>,
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
label: (
|
|
47
|
+
<div className="flex">
|
|
48
|
+
<div className="flex-1">{t("Corrective Actions")}</div>
|
|
49
|
+
<div
|
|
50
|
+
className="cursor-pointer"
|
|
51
|
+
onClick={() => goTo(getRedirectLink("/app/corrective-actions"))}
|
|
52
|
+
>
|
|
53
|
+
<CustomIcon
|
|
54
|
+
name="LinkNewTab"
|
|
55
|
+
width={16}
|
|
56
|
+
height={16}
|
|
57
|
+
color={theme.colorPrimary}
|
|
58
|
+
/>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
),
|
|
62
|
+
render: () => {
|
|
63
|
+
return (
|
|
64
|
+
<span>
|
|
65
|
+
{
|
|
66
|
+
(Array.isArray(data?.events) ? data.events : [])?.find(
|
|
67
|
+
(c) => c._id === "correctiveActions",
|
|
68
|
+
)?.count ?? 0
|
|
69
|
+
}
|
|
70
|
+
</span>
|
|
71
|
+
);
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
label: (
|
|
76
|
+
<div className="flex">
|
|
77
|
+
<div className="flex-1">{t("Reported Incidents")}</div>
|
|
78
|
+
<div
|
|
79
|
+
className="cursor-pointer"
|
|
80
|
+
onClick={() => goTo(getRedirectLink("/app/incident"))}
|
|
81
|
+
>
|
|
82
|
+
<CustomIcon
|
|
83
|
+
name="LinkNewTab"
|
|
84
|
+
width={16}
|
|
85
|
+
height={16}
|
|
86
|
+
color={theme.colorPrimary}
|
|
87
|
+
/>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
),
|
|
91
|
+
render: () => (
|
|
92
|
+
<span>
|
|
93
|
+
{
|
|
94
|
+
(Array.isArray(data?.events) ? data.events : [])?.find(
|
|
95
|
+
(c) => c._id === "incident",
|
|
96
|
+
)?.count ?? 0
|
|
97
|
+
}
|
|
98
|
+
</span>
|
|
99
|
+
),
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
label: (
|
|
103
|
+
<div className="flex">
|
|
104
|
+
<div className="flex-1">{t("Information Sources")}</div>
|
|
105
|
+
<div
|
|
106
|
+
className="cursor-pointer"
|
|
107
|
+
onClick={() => goTo(getRedirectLink("/app/partners"))}
|
|
108
|
+
>
|
|
109
|
+
<CustomIcon
|
|
110
|
+
name="LinkNewTab"
|
|
111
|
+
width={16}
|
|
112
|
+
height={16}
|
|
113
|
+
color={theme.colorPrimary}
|
|
114
|
+
/>
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
),
|
|
118
|
+
render: () => <span>{data.sources ?? 0}</span>,
|
|
119
|
+
},
|
|
120
|
+
];
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React, { useMemo } from 'react'
|
|
2
|
+
import KeyIndicatorsWidget from '../../../../../core/components/Dashboard/Widget/KeyIndicators/index.jsx'
|
|
3
|
+
import { useWidgetFetch } from '../../../../../hooks/useWidgetFetch.js';
|
|
4
|
+
import { getRowConfig } from './config.js';
|
|
5
|
+
|
|
6
|
+
const defaultFetchConfig = {
|
|
7
|
+
basepath: "analytics",
|
|
8
|
+
url: "/widgets/key-informations",
|
|
9
|
+
filters: {
|
|
10
|
+
metrics: ['locations', 'stakeholders', 'events', 'sources']
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
function KeyIndicators({
|
|
15
|
+
t = () => {},
|
|
16
|
+
goTo = () => {},
|
|
17
|
+
getRedirectLink = () => {},
|
|
18
|
+
theme = {},
|
|
19
|
+
partners = [],
|
|
20
|
+
}) {
|
|
21
|
+
const fetchConfig = useMemo(
|
|
22
|
+
() => ({
|
|
23
|
+
...defaultFetchConfig,
|
|
24
|
+
}),
|
|
25
|
+
[],
|
|
26
|
+
);
|
|
27
|
+
const { data, loading } = useWidgetFetch({config: fetchConfig});
|
|
28
|
+
|
|
29
|
+
const config = useMemo(
|
|
30
|
+
() =>
|
|
31
|
+
getRowConfig({
|
|
32
|
+
t,
|
|
33
|
+
data: { ...data, partners },
|
|
34
|
+
goTo,
|
|
35
|
+
getRedirectLink,
|
|
36
|
+
theme
|
|
37
|
+
}),
|
|
38
|
+
[t, data, goTo, getRedirectLink, partners, theme],
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<KeyIndicatorsWidget
|
|
43
|
+
t={t}
|
|
44
|
+
config={config}
|
|
45
|
+
loading={loading}
|
|
46
|
+
title={t("Key Information")}
|
|
47
|
+
className="small-content "
|
|
48
|
+
/>
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export default KeyIndicators
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const getTabs = (t) => {
|
|
2
|
+
return [
|
|
3
|
+
{ value: "location", label: t("Locations") },
|
|
4
|
+
{ value: "stakeholder", label: t("Stakeholders") },
|
|
5
|
+
{ value: "event", label: t("Events") },
|
|
6
|
+
]
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const getFiltersConfig = (t, filters, locationCategories) => {
|
|
10
|
+
const value = filters.type ? { value: filters.type } : {};
|
|
11
|
+
|
|
12
|
+
return [
|
|
13
|
+
{
|
|
14
|
+
label: t("Location type"),
|
|
15
|
+
placeholder: t("Select"),
|
|
16
|
+
key: "type",
|
|
17
|
+
type: "select",
|
|
18
|
+
...value,
|
|
19
|
+
options: locationCategories ?? [],
|
|
20
|
+
},
|
|
21
|
+
];
|
|
22
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { findOptions } from '../../../../../../helpers/StringHelper.js';
|
|
2
|
+
|
|
3
|
+
export const mapData = (data, activeTab, category, locationCategories, filters) => {
|
|
4
|
+
if (activeTab === "stakeholder") {
|
|
5
|
+
const locations = {};
|
|
6
|
+
|
|
7
|
+
data.filter((d) => d.location).forEach((d) => {
|
|
8
|
+
const { location, ...rest } = d;
|
|
9
|
+
|
|
10
|
+
const stakeholder = {
|
|
11
|
+
...rest,
|
|
12
|
+
sources: Array.isArray(rest.sources) ? rest?.sources?.length : rest?.sources,
|
|
13
|
+
category: findOptions(rest.category, category),
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
if (locations[location.datastakeId]) {
|
|
17
|
+
locations[location.datastakeId].stakeholders.push(stakeholder);
|
|
18
|
+
} else {
|
|
19
|
+
locations[location.datastakeId] = {
|
|
20
|
+
gps: location.gps,
|
|
21
|
+
authorId: location?.authorId,
|
|
22
|
+
name: location.name,
|
|
23
|
+
datastakeId: location.datastakeId,
|
|
24
|
+
stakeholders: [stakeholder],
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
return Object.values(locations);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (activeTab === "event") {
|
|
33
|
+
const locations = {};
|
|
34
|
+
|
|
35
|
+
data.filter((d) => d?.location).forEach((d) => {
|
|
36
|
+
const { location, ...rest } = d;
|
|
37
|
+
const event = {
|
|
38
|
+
...rest,
|
|
39
|
+
type:
|
|
40
|
+
rest?.typeOfEvent === "correctiveActions"
|
|
41
|
+
? "correctiveActions"
|
|
42
|
+
: rest?.severity
|
|
43
|
+
? `${rest.severity}_incident`
|
|
44
|
+
: "minor_incident",
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
if (locations[location.datastakeId]) {
|
|
48
|
+
locations[location.datastakeId].data.push(event);
|
|
49
|
+
} else {
|
|
50
|
+
locations[location.datastakeId] = {
|
|
51
|
+
gps: {
|
|
52
|
+
...location.gps,
|
|
53
|
+
latitude: location.gps?.latitude ?? 0,
|
|
54
|
+
longitude: location.gps?.longitude ?? 0,
|
|
55
|
+
},
|
|
56
|
+
authorId: location?.authorId,
|
|
57
|
+
name: location?.name,
|
|
58
|
+
datastakeId: location?.datastakeId,
|
|
59
|
+
data: [event],
|
|
60
|
+
type: findOptions(location?.category, locationCategories ?? []),
|
|
61
|
+
category: location?.category,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
return Object.values(locations)?.map((d) => {
|
|
67
|
+
const sources = [];
|
|
68
|
+
|
|
69
|
+
d.data.forEach((d) => {
|
|
70
|
+
if (Array.isArray(d.sources)) {
|
|
71
|
+
d.sources.forEach((s) => {
|
|
72
|
+
if (!sources.includes(s)) {
|
|
73
|
+
sources.push(s);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
return { ...d, total: d.data.length || 0, sources: sources.length };
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return data
|
|
84
|
+
?.filter((d) => {
|
|
85
|
+
if (filters.type && filters.type !== "mineSite") {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return !!d?.locationDetails?.gps;
|
|
90
|
+
})
|
|
91
|
+
?.map((d) => ({
|
|
92
|
+
...d?.locationDetails,
|
|
93
|
+
name: d.name,
|
|
94
|
+
datastakeId: d.datastakeId,
|
|
95
|
+
sources: d.sources || 1,
|
|
96
|
+
cadastre: d?.cadastreSituation || "--",
|
|
97
|
+
products: d?.products || "--",
|
|
98
|
+
category: d?.category,
|
|
99
|
+
authorId: d?.authorId,
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export const onClickLink = (data, getRedirectLink, activeTab, goTo, user) => {
|
|
104
|
+
const sourceId = data?.authorId;
|
|
105
|
+
|
|
106
|
+
const getLink = (link) => getRedirectLink(sourceId ? `${link}?sourceId=${sourceId}` : link);
|
|
107
|
+
|
|
108
|
+
if (activeTab === "stakeholder") {
|
|
109
|
+
switch (data.stakeholderType) {
|
|
110
|
+
case "operator":
|
|
111
|
+
return goTo(getLink(`/app/summary/operators/${data?.datastakeId}`));
|
|
112
|
+
case "worker":
|
|
113
|
+
return goTo(getLink(`/app/view/workers/${data?.datastakeId}`));
|
|
114
|
+
default:
|
|
115
|
+
return goTo(getLink(`/app/view/stakeholders/${data?.datastakeId}`));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (activeTab === "event") {
|
|
120
|
+
switch (data.category) {
|
|
121
|
+
case "mineSite":
|
|
122
|
+
return goTo(getLink(`/app/summary/scl/${data?.datastakeId}`));
|
|
123
|
+
default:
|
|
124
|
+
return goTo(getLink(`/app/view/locations/${data?.datastakeId}`));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
switch (data.category) {
|
|
129
|
+
case "mineSite": {
|
|
130
|
+
const isOwnData = user?.company?.id === data?.authorId;
|
|
131
|
+
return goTo(
|
|
132
|
+
`/app/summary/scl/${data?.datastakeId}${
|
|
133
|
+
!isOwnData ? `?sourceId=${data?.authorId}` : ""
|
|
134
|
+
}`,
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
case "area":
|
|
138
|
+
return goTo(getLink(`/app/view/conflict-areas/${data?.datastakeId}`));
|
|
139
|
+
default:
|
|
140
|
+
goTo(getLink(`/app/view/locations/${data?.datastakeId}`));
|
|
141
|
+
}
|
|
142
|
+
};
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import React, { useEffect, useMemo, useState } from 'react'
|
|
2
|
+
import { useWidgetFetch } from '../../../../../hooks/useWidgetFetch.js';
|
|
3
|
+
import { findOptions } from '../../../../../../helpers/StringHelper.js';
|
|
4
|
+
import { getFiltersConfig, getTabs } from './config.js';
|
|
5
|
+
import { mapData, onClickLink } from './helper.js';
|
|
6
|
+
import CustomIcon from '../../../../../core/components/Icon/CustomIcon.jsx';
|
|
7
|
+
import Widget from '../../../../../core/components/Dashboard/Widget/index.jsx';
|
|
8
|
+
import Multiselect from '../../../../../core/components/Select/MultiSelect/index.jsx';
|
|
9
|
+
import Map from "../../../../../core/components/Dashboard/Map/index.jsx";
|
|
10
|
+
|
|
11
|
+
const defaultFetchConfig = {
|
|
12
|
+
basepath: "forms",
|
|
13
|
+
url: "/location",
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
function MineSites({
|
|
17
|
+
t = () => {},
|
|
18
|
+
goTo = () => {},
|
|
19
|
+
getRedirectLink = () => {},
|
|
20
|
+
theme = {},
|
|
21
|
+
selectedPartners = {},
|
|
22
|
+
setSelectedPartners,
|
|
23
|
+
partners = [],
|
|
24
|
+
user = {},
|
|
25
|
+
options = {},
|
|
26
|
+
APP,
|
|
27
|
+
}) {
|
|
28
|
+
const { locationCategories = [], category } = useMemo(() => options ?? {}, [options]);
|
|
29
|
+
const [formData, setFormData] = useState();
|
|
30
|
+
const [filters, setFilters] = useState({});
|
|
31
|
+
const [activeTab, setActiveTab] = useState("location");
|
|
32
|
+
|
|
33
|
+
const _formFetchConfig = useMemo(
|
|
34
|
+
() => ({
|
|
35
|
+
...defaultFetchConfig,
|
|
36
|
+
params: {
|
|
37
|
+
scope: "create",
|
|
38
|
+
language: user?.language || "en",
|
|
39
|
+
}
|
|
40
|
+
}),
|
|
41
|
+
[user],
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const { data: _formData, loading: formLoading } = useWidgetFetch({config: _formFetchConfig});
|
|
45
|
+
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
if (data) {
|
|
48
|
+
setFormData(_formData?.identification);
|
|
49
|
+
}
|
|
50
|
+
},[_formData, _formData?.identification]);
|
|
51
|
+
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
setFilters({});
|
|
54
|
+
}, [activeTab]);
|
|
55
|
+
|
|
56
|
+
const dataFetchConfig = useMemo(
|
|
57
|
+
() => ({
|
|
58
|
+
basepath: "analytics",
|
|
59
|
+
url: "/widgets/gps-monitoring",
|
|
60
|
+
filters: { activeTab, sources: selectedPartners?.partners || [], ...(activeTab === 'event' ? { eventTypes: ['incident', 'correctiveActions'] } : {}) },
|
|
61
|
+
defaultData: [],
|
|
62
|
+
stop: selectedPartners?.loading,
|
|
63
|
+
}),
|
|
64
|
+
[activeTab, selectedPartners],
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
const { data, loading, setData } = useWidgetFetch({config: dataFetchConfig});
|
|
68
|
+
|
|
69
|
+
const tabs = useMemo(() => getTabs(t), [t]);
|
|
70
|
+
|
|
71
|
+
const filtersConfig = useMemo(() => getFiltersConfig(t, filters, locationCategories), [activeTab, filters, t, locationCategories]);
|
|
72
|
+
|
|
73
|
+
const onFilterChange = (filters) => {
|
|
74
|
+
setFilters((p) => ({ ...p, ...filters }));
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const _mapData = useMemo(() => mapData(data, activeTab, category, locationCategories, filters), [data, activeTab, category, locationCategories, filters]);
|
|
78
|
+
|
|
79
|
+
const renderTooltip = (data) => {
|
|
80
|
+
const country = data.admLevel1?.country;
|
|
81
|
+
const adminLevel1Label =
|
|
82
|
+
formData?.administrativeLevel1?.label[`country is ${country}`] ?? t("Province");
|
|
83
|
+
const adminLevel2Label =
|
|
84
|
+
formData?.administrativeLevel2?.label[`country is ${country}`] ?? t("Territory");
|
|
85
|
+
|
|
86
|
+
if (activeTab === "stakeholder") {
|
|
87
|
+
return [
|
|
88
|
+
{
|
|
89
|
+
label: t("Category"),
|
|
90
|
+
value: findOptions(data?.category, locationCategories ?? []) || "--",
|
|
91
|
+
},
|
|
92
|
+
];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (activeTab === "event") {
|
|
96
|
+
const correctiveActionsCount = data?.data?.filter(
|
|
97
|
+
(d) => d.type === "correctiveActions",
|
|
98
|
+
).length;
|
|
99
|
+
|
|
100
|
+
return [
|
|
101
|
+
{
|
|
102
|
+
label: t("Major Incidents"),
|
|
103
|
+
color: "#F04438",
|
|
104
|
+
value: data?.totals?.major || "--",
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
label: t("Moderate Incidents"),
|
|
108
|
+
color: "#FF7A45",
|
|
109
|
+
value: data?.totals?.moderate || "--",
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
label: t("Minor Incidents"),
|
|
113
|
+
color: "#FFC069",
|
|
114
|
+
value: data?.totals?.minor || "--",
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
label: t("Corrective Actions"),
|
|
118
|
+
color: "#12b76a",
|
|
119
|
+
value: correctiveActionsCount === 0 ? "--" : correctiveActionsCount,
|
|
120
|
+
},
|
|
121
|
+
];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return [
|
|
125
|
+
{
|
|
126
|
+
label: t("Location Type"),
|
|
127
|
+
value: findOptions(data?.category, locationCategories ?? []) ?? t("Mine Site"),
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
label: t(`${adminLevel1Label}`),
|
|
131
|
+
value: data?.admLevel1?.name || "--",
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
label: t(`${adminLevel2Label}`),
|
|
135
|
+
value: data?.admLevel2?.name || "--",
|
|
136
|
+
},
|
|
137
|
+
];
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const sourceOptions = useMemo(() => {
|
|
141
|
+
return partners.map((partner) => {
|
|
142
|
+
const isOwnData = partner.id === user?.company?.id;
|
|
143
|
+
return {
|
|
144
|
+
label: partner.nickName,
|
|
145
|
+
value: partner.id,
|
|
146
|
+
avatar: isOwnData ? <span>OWN</span> : <CustomIcon name={"Search02"} size={14} />,
|
|
147
|
+
background: isOwnData ? theme.colorPrimary7 : undefined,
|
|
148
|
+
color: isOwnData ? "white" : undefined,
|
|
149
|
+
};
|
|
150
|
+
});
|
|
151
|
+
}, [partners, user]);
|
|
152
|
+
|
|
153
|
+
return (
|
|
154
|
+
<Widget
|
|
155
|
+
loading={loading}
|
|
156
|
+
title={t("Monitoring Map")}
|
|
157
|
+
className="v2-widget no-px no-pb-body h-w-btn-header"
|
|
158
|
+
tabsConfig={{
|
|
159
|
+
tabs,
|
|
160
|
+
value: activeTab,
|
|
161
|
+
onChange: (tab) => {
|
|
162
|
+
setData([]);
|
|
163
|
+
setActiveTab(tab);
|
|
164
|
+
},
|
|
165
|
+
}}
|
|
166
|
+
addedHeader={
|
|
167
|
+
<>
|
|
168
|
+
<div className="flex-1" />
|
|
169
|
+
<Multiselect
|
|
170
|
+
options={[...sourceOptions]}
|
|
171
|
+
isAvatarGroup
|
|
172
|
+
selectionType="checkbox"
|
|
173
|
+
canUnselectLast={false}
|
|
174
|
+
key={`partners-${partners?.length}`}
|
|
175
|
+
onChange={(selected) => {
|
|
176
|
+
setSelectedPartners((prev) => ({
|
|
177
|
+
...prev,
|
|
178
|
+
partners: selected,
|
|
179
|
+
loading: false,
|
|
180
|
+
}));
|
|
181
|
+
}}
|
|
182
|
+
dropDownWidth={200}
|
|
183
|
+
defaultSelected={partners.map((p) => p.id) || []}
|
|
184
|
+
/>
|
|
185
|
+
</>
|
|
186
|
+
}
|
|
187
|
+
>
|
|
188
|
+
<Map
|
|
189
|
+
t={t}
|
|
190
|
+
app={APP}
|
|
191
|
+
showSider={false}
|
|
192
|
+
user={user}
|
|
193
|
+
data={_mapData}
|
|
194
|
+
mapConfig={{ maxZoom: 10 }}
|
|
195
|
+
primaryLink
|
|
196
|
+
type={activeTab}
|
|
197
|
+
onFilterChange={onFilterChange}
|
|
198
|
+
filtersConfig={filtersConfig}
|
|
199
|
+
renderTooltip={renderTooltip}
|
|
200
|
+
onClickLink={(data) => {
|
|
201
|
+
onClickLink(data, getRedirectLink, activeTab, goTo, user);
|
|
202
|
+
}}
|
|
203
|
+
link={true}
|
|
204
|
+
/>
|
|
205
|
+
</Widget>
|
|
206
|
+
)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export default MineSites
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const getConfig = (theme = {}) => {
|
|
2
|
+
return [
|
|
3
|
+
{
|
|
4
|
+
key: "singleSource",
|
|
5
|
+
label: {
|
|
6
|
+
"data-compilation": "Private",
|
|
7
|
+
"data-consolidation": "Single Source",
|
|
8
|
+
},
|
|
9
|
+
color: theme.colorPrimary7,
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
key: "multipleSource",
|
|
13
|
+
label: {
|
|
14
|
+
"data-compilation": "Submitted",
|
|
15
|
+
"data-consolidation": "Multiple Sources",
|
|
16
|
+
},
|
|
17
|
+
color: theme.colorPrimary4,
|
|
18
|
+
},
|
|
19
|
+
]
|
|
20
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { useMemo, useCallback } from "react";
|
|
2
|
+
import { renderTooltipJsx } from '../../../../../utils/tooltip.js'
|
|
3
|
+
import { getConfig } from './config.js'
|
|
4
|
+
|
|
5
|
+
export const useTriangulation = ({ widgetData, t = () => {}, section, theme = {} }) => {
|
|
6
|
+
|
|
7
|
+
const config = useMemo(() => getConfig(theme), [theme]);
|
|
8
|
+
|
|
9
|
+
const data = useMemo(() => {
|
|
10
|
+
const data = {
|
|
11
|
+
singleSource: 0,
|
|
12
|
+
multipleSource: 0,
|
|
13
|
+
total: 0,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
Object.values(widgetData).forEach((val) => {
|
|
17
|
+
data.total += val?.total || 0;
|
|
18
|
+
data.singleSource += val?.singleSource || 0;
|
|
19
|
+
data.multipleSource += val?.multiSource || 0;
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
singleSource: data.total > 0 ? Math.round((data.singleSource / data.total) * 100) : 0,
|
|
25
|
+
multipleSource:
|
|
26
|
+
data.total > 0 ? Math.round((data.multipleSource / data.total) * 100) : 0,
|
|
27
|
+
};
|
|
28
|
+
}, [widgetData]);
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
const pieData = useMemo(() => {
|
|
32
|
+
// console.log("data", data);
|
|
33
|
+
const total = Object.values(data).reduce((all, val) => all + (val || 0), 0);
|
|
34
|
+
return config.map((conf) => ({
|
|
35
|
+
percent: (data[conf.key] || 0) / total,
|
|
36
|
+
color: conf.color,
|
|
37
|
+
key: conf.key,
|
|
38
|
+
}));
|
|
39
|
+
}, [data]);
|
|
40
|
+
|
|
41
|
+
const isEmpty = useMemo(() => Object.keys(data).filter((k) => !!data[k]).length === 0, [data]);
|
|
42
|
+
|
|
43
|
+
const getTooltipChildren = useCallback(
|
|
44
|
+
(item) => {
|
|
45
|
+
if (isEmpty) {
|
|
46
|
+
return renderTooltipJsx({
|
|
47
|
+
title: t("Triangulation"),
|
|
48
|
+
items: config.map((conf) => ({
|
|
49
|
+
label: t(conf.label[section]),
|
|
50
|
+
color: conf.color,
|
|
51
|
+
value: "0%",
|
|
52
|
+
})),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const _config = config.find((c) => c.key === item.key);
|
|
57
|
+
|
|
58
|
+
if (_config) {
|
|
59
|
+
return renderTooltipJsx({
|
|
60
|
+
title: t(
|
|
61
|
+
section === "data-compilation"
|
|
62
|
+
? "nashiriki::Information Sharing"
|
|
63
|
+
: "Triangulation",
|
|
64
|
+
),
|
|
65
|
+
items: [
|
|
66
|
+
{
|
|
67
|
+
// color: _config.color,
|
|
68
|
+
label: t(_config.label[section]),
|
|
69
|
+
value: `${data[_config.key] || 0}%`,
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return null;
|
|
76
|
+
},
|
|
77
|
+
[t, data, section, isEmpty],
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
pieData,
|
|
82
|
+
isEmpty,
|
|
83
|
+
getTooltipChildren,
|
|
84
|
+
data,
|
|
85
|
+
config,
|
|
86
|
+
}
|
|
87
|
+
}
|