datastake-daf 0.6.834 → 0.6.837
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 +2354 -2200
- package/dist/hooks/index.js +7 -8
- package/dist/pages/index.js +441 -234
- package/dist/services/index.js +7 -8
- package/dist/utils/index.js +18 -0
- package/package.json +1 -1
- package/src/@daf/core/components/AuthForm/index.jsx +34 -1
- package/src/@daf/core/components/Screens/Admin/AdminDashboard/components/UserStatistics/TopContributors/hook.js +3 -3
- package/src/@daf/core/components/Screens/Admin/AdminDashboard/components/UserStatistics/TopContributors/index.jsx +2 -2
- package/src/@daf/core/components/Screens/Admin/AdminDashboard/components/UserStatistics/index.jsx +2 -6
- package/src/@daf/core/components/Screens/Admin/AdminTables/AccountTable/index.jsx +0 -1
- package/src/@daf/{core/components/Screens → pages/Dashboards}/ConflictManagement/components/KeyIndicators/config.js +2 -3
- package/src/@daf/{core/components/Screens → pages/Dashboards}/ConflictManagement/components/KeyIndicators/index.js +2 -2
- package/src/@daf/{core/components/Screens → pages/Dashboards}/ConflictManagement/components/MineSite/index.js +3 -3
- package/src/@daf/pages/Dashboards/ConflictManagement/components/RisksWidget/components/IncidentsTime/config.js +206 -0
- package/src/@daf/pages/Dashboards/ConflictManagement/components/RisksWidget/components/IncidentsTime/hook.js +48 -0
- package/src/@daf/pages/Dashboards/ConflictManagement/components/RisksWidget/components/IncidentsTime/index.js +154 -0
- package/src/@daf/pages/Dashboards/ConflictManagement/components/RisksWidget/components/ProblemSolver/hook.js +83 -0
- package/src/@daf/{core/components/Screens → pages/Dashboards}/ConflictManagement/components/RisksWidget/components/ProblemSolver/index.js +14 -7
- package/src/@daf/pages/Dashboards/ConflictManagement/components/RisksWidget/components/TerritorialDistribution/config.js +10 -0
- package/src/@daf/{core/components/Screens → pages/Dashboards}/ConflictManagement/components/RisksWidget/components/TerritorialDistribution/index.js +18 -13
- package/src/@daf/{core/components/Screens → pages/Dashboards}/ConflictManagement/components/RisksWidget/index.js +1 -1
- package/src/@daf/{core/components/Screens → pages/Dashboards}/ConflictManagement/index.js +17 -19
- package/src/@daf/pages/Dashboards/SupplyChain/components/ChartsContainer/components/GenderDistribution/index.js +1 -1
- package/src/@daf/pages/Dashboards/SupplyChain/components/KeyIndicators/config.js +4 -4
- package/src/@daf/pages/Data/Channels/columns.js +1 -1
- package/src/@daf/pages/Events/Activities/columns.js +1 -2
- package/src/@daf/pages/Events/Incidents/columns.js +1 -2
- package/src/@daf/pages/Events/Testimonials/columns.js +1 -2
- package/src/@daf/pages/Events/columns.js +3 -3
- package/src/@daf/pages/Locations/MineSite/columns.js +1 -1
- package/src/@daf/pages/Stakeholders/Operators/columns.js +0 -2
- package/src/@daf/pages/Stakeholders/Workers/columns.js +1 -3
- package/src/@daf/pages/Summary/Operator/components/KeyInformation/config.js +1 -0
- package/src/@daf/pages/TablePage/create.jsx +6 -6
- package/src/@daf/pages/TablePage/index.jsx +1 -7
- package/src/@daf/services/DashboardService.js +8 -8
- package/src/constants/locales/en/translation.js +6 -0
- package/src/constants/locales/fr/translation.js +6 -0
- package/src/constants/locales/sp/translation.js +6 -0
- package/src/pages.js +1 -1
- package/build/favicon.ico +0 -0
- package/build/logo192.png +0 -0
- package/build/logo512.png +0 -0
- package/build/manifest.json +0 -25
- package/build/robots.txt +0 -3
- package/src/@daf/core/components/Screens/ConflictManagement/components/RisksWidget/components/IncidentsTime/hook.js +0 -32
- package/src/@daf/core/components/Screens/ConflictManagement/components/RisksWidget/components/IncidentsTime/index.js +0 -73
- package/src/@daf/core/components/Screens/ConflictManagement/components/RisksWidget/components/ProblemSolver/hook.js +0 -86
- package/src/@daf/core/components/Screens/ConflictManagement/components/RisksWidget/components/TerritorialDistribution/config.js +0 -34
- /package/src/@daf/{core/components/Screens → pages/Dashboards}/ConflictManagement/components/MineSite/helper.js +0 -0
- /package/src/@daf/{core/components/Screens → pages/Dashboards}/ConflictManagement/components/RisksWidget/config.js +0 -0
package/dist/services/index.js
CHANGED
|
@@ -1516,14 +1516,13 @@ class DashboardService extends BaseService {
|
|
|
1516
1516
|
isUserManager: true
|
|
1517
1517
|
});
|
|
1518
1518
|
}
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
// }
|
|
1519
|
+
getWidgetConflictManagement(url, params, basepath = "dashboard/conflict-management") {
|
|
1520
|
+
return this.apiGet({
|
|
1521
|
+
url: `/${basepath}${url}`,
|
|
1522
|
+
params,
|
|
1523
|
+
isApp: true
|
|
1524
|
+
});
|
|
1525
|
+
}
|
|
1527
1526
|
}
|
|
1528
1527
|
var DashboardService$1 = createLazyService(DashboardService);
|
|
1529
1528
|
|
package/dist/utils/index.js
CHANGED
|
@@ -7850,6 +7850,11 @@ function mapUser(user) {
|
|
|
7850
7850
|
}
|
|
7851
7851
|
|
|
7852
7852
|
const en = {
|
|
7853
|
+
"Identified Mine Sites": "Identified Mine Sites",
|
|
7854
|
+
"Associated Documents": "Associated Documents",
|
|
7855
|
+
"Male": "Male",
|
|
7856
|
+
"Female": "Female",
|
|
7857
|
+
"Invalid input": "Invalid input",
|
|
7853
7858
|
"conflict-management": "Conflict Management",
|
|
7854
7859
|
"review-requests": "Review Requests",
|
|
7855
7860
|
"create-account": "Create Account",
|
|
@@ -9121,6 +9126,7 @@ const en = {
|
|
|
9121
9126
|
"max-char": "Maximum {{filled}}/{{chars}} characters.",
|
|
9122
9127
|
"max-items": "Maximum {{chars}} items.",
|
|
9123
9128
|
"max-item": "Maximum {{chars}} item.",
|
|
9129
|
+
"organisation-already-exist": "If your organisation is already active on {{appName}}, your application will not be reviewed. Instead, please contact the account's main user and request an invitation.",
|
|
9124
9130
|
projectInviteBackDesc: "Are you sure you want to invite this source again?This user will receive a new notification",
|
|
9125
9131
|
DataStore: {
|
|
9126
9132
|
overview: "Overview",
|
|
@@ -9215,6 +9221,11 @@ const en = {
|
|
|
9215
9221
|
};
|
|
9216
9222
|
|
|
9217
9223
|
const fr = {
|
|
9224
|
+
"Identified Mine Sites": "Sites miniers identifiés",
|
|
9225
|
+
"Associated Documents": "Documents associés",
|
|
9226
|
+
"Male": "Masculin",
|
|
9227
|
+
"Female": "Féminin",
|
|
9228
|
+
"Invalid input": "Entrée invalide",
|
|
9218
9229
|
"review-requests": "Examiner les demandes",
|
|
9219
9230
|
"create-account": "Créer un compte",
|
|
9220
9231
|
"manage-users": "Gérer les utilisateurs",
|
|
@@ -10538,6 +10549,7 @@ const fr = {
|
|
|
10538
10549
|
"Please introduce yourself": "Prière de vous présenter",
|
|
10539
10550
|
"Almost There": "On y est presque",
|
|
10540
10551
|
"Help us guide you to the right application": "Aidez-nous à vous guider vers la bonne application",
|
|
10552
|
+
"organisation-already-exist": "Si votre organisation est déjà active dans {{appName}}, votre requête ne sera pas revue. Prière de contacter l’utilisateur principal et solliciter une invitation.",
|
|
10541
10553
|
"If your organisation is already active on Datastake, your application will not be reviewed. Instead, please contact the account's main user and request an invitation": "Si votre organisation est déjà active dans Datastake, votre requête ne sera pas revue. Prière de contacter l’utilisateur principal et solliciter une invitation",
|
|
10542
10554
|
"Yes, I understand": "Oui, je comprends",
|
|
10543
10555
|
"Protect your data assets": "Protégez vos données",
|
|
@@ -11146,6 +11158,11 @@ const fr = {
|
|
|
11146
11158
|
};
|
|
11147
11159
|
|
|
11148
11160
|
const sp = {
|
|
11161
|
+
"Identified Mine Sites": "Sitios mineros identificados",
|
|
11162
|
+
"Associated Documents": "Documentos asociados",
|
|
11163
|
+
"Male": "Masculino",
|
|
11164
|
+
"Female": "Femenino",
|
|
11165
|
+
"Invalid input": "Entrada inválida",
|
|
11149
11166
|
"review-requests": "Revisar solicitudes",
|
|
11150
11167
|
"create-account": "Crear cuenta",
|
|
11151
11168
|
"manage-users": "Gestionar usuarios",
|
|
@@ -12152,6 +12169,7 @@ const sp = {
|
|
|
12152
12169
|
"Please introduce yourself": "Preséntese",
|
|
12153
12170
|
"Almost There": "Ya casi está",
|
|
12154
12171
|
"Help us guide you to the right application": "Ayúdenos a guiarle hacia la solicitud correcta",
|
|
12172
|
+
"organisation-already-exist": "Si su organización ya está activa en {{appName}}, su solicitud no será revisada. En su lugar, póngase en contacto con el usuario principal de la cuenta y solicite una invitación.",
|
|
12155
12173
|
"If your organisation is already active on Datastake, your application will not be reviewed. Instead, please contact the account's main user and request an invitation": "Si su organización ya está activa en Datastake, su solicitud no será revisada. En su lugar, póngase en contacto con el usuario principal de la cuenta y solicite una invitación.",
|
|
12156
12174
|
"Yes, I understand": "Sí, entiendo",
|
|
12157
12175
|
"Protect your data assets": "Proteja sus activos de datos",
|
package/package.json
CHANGED
|
@@ -206,7 +206,40 @@ function AuthForm ({
|
|
|
206
206
|
onFinish={handleSubmit}
|
|
207
207
|
onValuesChange={handleValuesChange}
|
|
208
208
|
>
|
|
209
|
-
{
|
|
209
|
+
{(() => {
|
|
210
|
+
const { step, order } = additionalItemConfig;
|
|
211
|
+
const shouldShowAdditionalItem = additionalItem &&
|
|
212
|
+
(step === undefined || step === currentStep);
|
|
213
|
+
|
|
214
|
+
if (!shouldShowAdditionalItem) {
|
|
215
|
+
return currentFields.map(renderField);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const fieldsWithAdditionalItem = [...currentFields];
|
|
219
|
+
const insertIndex = order !== undefined ? order : fieldsWithAdditionalItem.length;
|
|
220
|
+
|
|
221
|
+
return fieldsWithAdditionalItem.map((field, index) => {
|
|
222
|
+
const elements = [];
|
|
223
|
+
|
|
224
|
+
if (index === insertIndex) {
|
|
225
|
+
elements.push(
|
|
226
|
+
<div key="additional-item" style={{ marginBottom: '16px', marginTop: '16px' }}>
|
|
227
|
+
{additionalItem}
|
|
228
|
+
</div>
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
elements.push(renderField(field));
|
|
233
|
+
|
|
234
|
+
return elements;
|
|
235
|
+
}).flat().concat(
|
|
236
|
+
insertIndex >= fieldsWithAdditionalItem.length ? (
|
|
237
|
+
<div key="additional-item" style={{ marginBottom: '16px', marginTop: '16px' }}>
|
|
238
|
+
{additionalItem}
|
|
239
|
+
</div>
|
|
240
|
+
) : []
|
|
241
|
+
);
|
|
242
|
+
})()}
|
|
210
243
|
|
|
211
244
|
|
|
212
245
|
{formErrors ? (
|
|
@@ -8,7 +8,7 @@ import AdminService from "../../../../../../../../services/AdminService";
|
|
|
8
8
|
|
|
9
9
|
const { useToken } = theme;
|
|
10
10
|
|
|
11
|
-
export default function useTopContributors({ container,
|
|
11
|
+
export default function useTopContributors({ container, t }) {
|
|
12
12
|
const [mainGraph, setMainGraph] = useState(null);
|
|
13
13
|
const [data, setData] = useState([]);
|
|
14
14
|
const [loading, setLoading] = useState(false);
|
|
@@ -18,7 +18,7 @@ export default function useTopContributors({ container, params, t }) {
|
|
|
18
18
|
const fetchTopContributors = async () => {
|
|
19
19
|
try {
|
|
20
20
|
setLoading(true);
|
|
21
|
-
const response = await AdminService.getTopContributors({
|
|
21
|
+
const response = await AdminService.getTopContributors({ });
|
|
22
22
|
const transformedData = (response?.data || []).map(item => ({
|
|
23
23
|
label: item.name,
|
|
24
24
|
Score: item.value
|
|
@@ -33,7 +33,7 @@ export default function useTopContributors({ container, params, t }) {
|
|
|
33
33
|
};
|
|
34
34
|
|
|
35
35
|
fetchTopContributors();
|
|
36
|
-
}, [
|
|
36
|
+
}, []);
|
|
37
37
|
useEffect(() => {
|
|
38
38
|
if (container.current) {
|
|
39
39
|
if (mainGraph) {
|
|
@@ -4,10 +4,10 @@ import useTopContributors from "./hook.js";
|
|
|
4
4
|
|
|
5
5
|
import Style from "../style.js";
|
|
6
6
|
|
|
7
|
-
export default function TopContributors({
|
|
7
|
+
export default function TopContributors({ t }) {
|
|
8
8
|
const container = useRef(null);
|
|
9
9
|
|
|
10
|
-
const { loading } = useTopContributors({ container,
|
|
10
|
+
const { loading } = useTopContributors({ container, t });
|
|
11
11
|
return (
|
|
12
12
|
<Widget
|
|
13
13
|
title={t(`admin::top-contributors`)}
|
package/src/@daf/core/components/Screens/Admin/AdminDashboard/components/UserStatistics/index.jsx
CHANGED
|
@@ -10,13 +10,9 @@ export default function UserStatistics({
|
|
|
10
10
|
data,
|
|
11
11
|
t,
|
|
12
12
|
translationKeys,
|
|
13
|
+
|
|
13
14
|
}) {
|
|
14
|
-
|
|
15
|
-
// console.log("UserStatistics:loadingUserGrowth", loadingUserGrowth);
|
|
16
|
-
// console.log("UserStatistics:data", data);
|
|
17
|
-
// console.log("UserStatistics:userActivityData", data?.userActivityData);
|
|
18
|
-
// console.log("UserStatistics:topContributorsData", data?.topContributorsData);
|
|
19
|
-
// console.log("UserStatistics:userGrowthData", data?.userGrowthData);
|
|
15
|
+
|
|
20
16
|
|
|
21
17
|
|
|
22
18
|
return (
|
|
@@ -18,7 +18,6 @@ import {
|
|
|
18
18
|
|
|
19
19
|
import CombineAccountModal from "../../AdminModals/CombineAccount/index.jsx";
|
|
20
20
|
|
|
21
|
-
// import NewAccount from "../../../Admin/AdminModals/NewAccount/index.jsx";
|
|
22
21
|
import CustomIcon from "../../../../Icon/CustomIcon.jsx";
|
|
23
22
|
import AddAccountModal from "../../AdminModals/AddAccount/index.jsx";
|
|
24
23
|
export default function AccountTable({
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import CustomIcon from "../../../../../components/Icon/CustomIcon.jsx";
|
|
3
|
-
|
|
2
|
+
import CustomIcon from "../../../../../core/components/Icon/CustomIcon.jsx";
|
|
4
3
|
const renderNumber = (number, locale = 'en') => {
|
|
5
4
|
return new Intl.NumberFormat(locale).format(number);
|
|
6
5
|
}
|
|
@@ -33,7 +32,7 @@ export const getRowConfig = ({ t, data = {}, goTo, getRedirectLink, theme = {} }
|
|
|
33
32
|
<div className="flex-1">{t("Reported Incidents")}</div>
|
|
34
33
|
<div
|
|
35
34
|
className="cursor-pointer"
|
|
36
|
-
onClick={() => goTo(getRedirectLink("/app/
|
|
35
|
+
onClick={() => goTo(getRedirectLink("/app/incidents"))}
|
|
37
36
|
>
|
|
38
37
|
<CustomIcon
|
|
39
38
|
name="LinkNewTab"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useMemo } from "react";
|
|
2
|
-
import KeyIndicatorsWidget from "
|
|
2
|
+
import KeyIndicatorsWidget from "../../../../../core/components/Dashboard/Widget/KeyIndicators/index.jsx";
|
|
3
3
|
import { getRowConfig } from "./config.js";
|
|
4
|
-
import {useWidgetFetch} from "
|
|
4
|
+
import {useWidgetFetch} from "../../../../../hooks/useWidgetFetch.js";
|
|
5
5
|
|
|
6
6
|
export const defaultFetchConfig = {
|
|
7
7
|
url: "/informations",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React, { useEffect, useMemo, useState } from "react";
|
|
2
2
|
// import { useSelector } from "react-redux";
|
|
3
|
-
import MineSiteMap from "
|
|
4
|
-
import Widget from "
|
|
3
|
+
import MineSiteMap from "../../../../../core/components/Dashboard/Map/index.jsx";
|
|
4
|
+
import Widget from "../../../../../core/components/Dashboard/Widget/index.jsx";
|
|
5
5
|
import { areaColors } from "./helper.js";
|
|
6
|
-
import {useWidgetFetch} from "
|
|
6
|
+
import {useWidgetFetch} from "../../../../../hooks/useWidgetFetch.js";
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
const TERRITORY_MAP = "territory";
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { useMemo, useCallback } from "react";
|
|
2
|
+
import dayjs from "dayjs";
|
|
3
|
+
import isoWeek from "dayjs/plugin/isoWeek";
|
|
4
|
+
dayjs.extend(isoWeek);
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
export function useTimelineBase({ language, selectedRange }) {
|
|
9
|
+
const locale = useMemo(
|
|
10
|
+
() => (language === "sp" ? "es" : language || "en"),
|
|
11
|
+
[language]
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
const baseMonths = useMemo(() => {
|
|
17
|
+
if (selectedRange === "12") {
|
|
18
|
+
const y = dayjs().year();
|
|
19
|
+
const arr = [];
|
|
20
|
+
for (let i = 0; i < 12; i++) {
|
|
21
|
+
const d = dayjs().year(y).month(i);
|
|
22
|
+
arr.push({
|
|
23
|
+
key: d.format("YYYY-MM"),
|
|
24
|
+
label: d.locale(locale).format("MMM YYYY"),
|
|
25
|
+
date: d.toISOString(),
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
return arr;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (selectedRange === "3") {
|
|
32
|
+
const end = dayjs().endOf("month");
|
|
33
|
+
const start = end.subtract(2, "month").startOf("month");
|
|
34
|
+
const diff = end.diff(start, "month");
|
|
35
|
+
const arr = [];
|
|
36
|
+
for (let i = 0; i <= diff; i++) {
|
|
37
|
+
const d = start.add(i, "month");
|
|
38
|
+
arr.push({
|
|
39
|
+
key: d.format("YYYY-MM"),
|
|
40
|
+
label: d.locale(locale).format("MMM YYYY"),
|
|
41
|
+
date: d.toISOString(),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return arr;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return [];
|
|
48
|
+
}, [locale, selectedRange]);
|
|
49
|
+
|
|
50
|
+
const baseWeeks = useMemo(() => {
|
|
51
|
+
if (selectedRange !== "3") return [];
|
|
52
|
+
const end = dayjs().endOf("week");
|
|
53
|
+
const start = end.subtract(12, "week");
|
|
54
|
+
const diff = end.diff(start, "week");
|
|
55
|
+
const arr = [];
|
|
56
|
+
for (let i = 0; i <= diff; i++) {
|
|
57
|
+
const d = start.add(i, "week");
|
|
58
|
+
arr.push({
|
|
59
|
+
key: d.format("GGGG-[W]WW"),
|
|
60
|
+
label: d.format("[W]WW"),
|
|
61
|
+
date: d.toISOString(),
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
return arr;
|
|
65
|
+
}, [selectedRange]);
|
|
66
|
+
|
|
67
|
+
const severityOrder = ["minor", "moderate", "major"];
|
|
68
|
+
|
|
69
|
+
const mergeWithData = useCallback(
|
|
70
|
+
(backendData = []) => {
|
|
71
|
+
let events = [];
|
|
72
|
+
|
|
73
|
+
if (Array.isArray(backendData)) {
|
|
74
|
+
backendData.forEach((entry) => {
|
|
75
|
+
if (!entry) return;
|
|
76
|
+
if (typeof entry === "object" && !Array.isArray(entry)) {
|
|
77
|
+
Object.values(entry).forEach((arr) => {
|
|
78
|
+
if (Array.isArray(arr)) events.push(...arr);
|
|
79
|
+
});
|
|
80
|
+
} else if (Array.isArray(entry)) {
|
|
81
|
+
events.push(...entry);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
} else if (backendData && typeof backendData === "object") {
|
|
85
|
+
Object.values(backendData).forEach((arr) => {
|
|
86
|
+
if (Array.isArray(arr)) events.push(...arr);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (selectedRange === "12") {
|
|
91
|
+
const monthBuckets = baseMonths.reduce((acc, m) => {
|
|
92
|
+
acc[m.key] = [];
|
|
93
|
+
return acc;
|
|
94
|
+
}, {});
|
|
95
|
+
|
|
96
|
+
events.forEach((ev) => {
|
|
97
|
+
const d = dayjs(ev.date);
|
|
98
|
+
const key = d.format("YYYY-MM");
|
|
99
|
+
if (monthBuckets[key]) monthBuckets[key].push(ev);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const res = [];
|
|
103
|
+
baseMonths.forEach((m) => {
|
|
104
|
+
const arr = monthBuckets[m.key];
|
|
105
|
+
if (!arr.length) {
|
|
106
|
+
res.push({
|
|
107
|
+
label: m.label,
|
|
108
|
+
key: m.key,
|
|
109
|
+
severity: "placeholder",
|
|
110
|
+
category: "placeholder",
|
|
111
|
+
value: 1,
|
|
112
|
+
isPlaceholder: true,
|
|
113
|
+
});
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
arr
|
|
117
|
+
.sort(
|
|
118
|
+
(a, b) =>
|
|
119
|
+
severityOrder.indexOf(a.severity) -
|
|
120
|
+
severityOrder.indexOf(b.severity)
|
|
121
|
+
)
|
|
122
|
+
.forEach((ev, idx) => {
|
|
123
|
+
const source = Array.isArray(ev.source)
|
|
124
|
+
? ev.source.join(", ")
|
|
125
|
+
: ev.source;
|
|
126
|
+
res.push({
|
|
127
|
+
...ev,
|
|
128
|
+
source,
|
|
129
|
+
label: m.label,
|
|
130
|
+
key: m.key,
|
|
131
|
+
indexInGroup: idx + 1,
|
|
132
|
+
severity: ev.severity || "undetermined",
|
|
133
|
+
category: ev.severity || "undetermined",
|
|
134
|
+
value: 1,
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
return res;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (selectedRange === "3") {
|
|
143
|
+
const weekBuckets = baseWeeks.reduce((acc, w) => {
|
|
144
|
+
acc[w.key] = [];
|
|
145
|
+
return acc;
|
|
146
|
+
}, {});
|
|
147
|
+
|
|
148
|
+
events.forEach((ev) => {
|
|
149
|
+
const d = dayjs(ev.date);
|
|
150
|
+
const key = d.format("GGGG-[W]WW");
|
|
151
|
+
if (weekBuckets[key]) weekBuckets[key].push(ev);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const res = [];
|
|
155
|
+
baseWeeks.forEach((w) => {
|
|
156
|
+
const arr = weekBuckets[w.key];
|
|
157
|
+
if (!arr.length) {
|
|
158
|
+
res.push({
|
|
159
|
+
label: w.label,
|
|
160
|
+
key: w.key,
|
|
161
|
+
severity: "placeholder",
|
|
162
|
+
category: "placeholder",
|
|
163
|
+
value: 1,
|
|
164
|
+
isPlaceholder: true,
|
|
165
|
+
});
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
arr
|
|
169
|
+
.sort(
|
|
170
|
+
(a, b) =>
|
|
171
|
+
severityOrder.indexOf(a.severity) -
|
|
172
|
+
severityOrder.indexOf(b.severity)
|
|
173
|
+
)
|
|
174
|
+
.forEach((ev, idx) => {
|
|
175
|
+
const source = Array.isArray(ev.source)
|
|
176
|
+
? ev.source.join(", ")
|
|
177
|
+
: ev.source;
|
|
178
|
+
res.push({
|
|
179
|
+
...ev,
|
|
180
|
+
source,
|
|
181
|
+
label: w.label,
|
|
182
|
+
key: w.key,
|
|
183
|
+
indexInGroup: idx + 1,
|
|
184
|
+
severity: ev.severity || "undetermined",
|
|
185
|
+
category: ev.severity || "undetermined",
|
|
186
|
+
value: 1,
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
return res;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return [];
|
|
195
|
+
},
|
|
196
|
+
[selectedRange, baseMonths, baseWeeks]
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
return {
|
|
200
|
+
baseMonths,
|
|
201
|
+
baseWeeks,
|
|
202
|
+
mergeWithData,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export default useTimelineBase;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { useMemo, useState } from "react";
|
|
2
|
+
import useTimelineBase from "./config.js";
|
|
3
|
+
|
|
4
|
+
export default function useIncidentsTimeline({
|
|
5
|
+
t,
|
|
6
|
+
language,
|
|
7
|
+
severityOptions = [],
|
|
8
|
+
selectedRange = "12",
|
|
9
|
+
}) {
|
|
10
|
+
const [filters, setFilters] = useState({ severity: "all" });
|
|
11
|
+
|
|
12
|
+
const { baseMonths, baseWeeks, mergeWithData } = useTimelineBase({ language, selectedRange });
|
|
13
|
+
|
|
14
|
+
const filtersConfig = useMemo(
|
|
15
|
+
() => ({
|
|
16
|
+
language,
|
|
17
|
+
filtersConfig: {
|
|
18
|
+
severity: {
|
|
19
|
+
type: "select",
|
|
20
|
+
label: "",
|
|
21
|
+
placeholder: (tFn) => tFn(""),
|
|
22
|
+
style: { flex: 1 },
|
|
23
|
+
labelStyle: { flex: 1 },
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
onApply: (val) => setFilters(val),
|
|
27
|
+
options: {
|
|
28
|
+
severity: [
|
|
29
|
+
{ value: "all", label: t("All") },
|
|
30
|
+
...(severityOptions || []),
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
selectedFilters: filters,
|
|
34
|
+
type: "small",
|
|
35
|
+
t,
|
|
36
|
+
}),
|
|
37
|
+
[t, language, filters, severityOptions]
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
filters,
|
|
42
|
+
filtersConfig,
|
|
43
|
+
setFilters,
|
|
44
|
+
baseMonths,
|
|
45
|
+
baseWeeks,
|
|
46
|
+
mergeWithData
|
|
47
|
+
};
|
|
48
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { useMemo, useCallback } from "react";
|
|
2
|
+
import Widget from "../../../../../../../core/components/Dashboard/Widget/index.jsx";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import useIncidentsTimeline from "./hook.js";
|
|
5
|
+
import { useWidgetFetch } from "../../../../../../../hooks/useWidgetFetch.js";
|
|
6
|
+
import DashboardService from "../../../../../../../services/DashboardService.js";
|
|
7
|
+
import { renderDateFormatted } from "../../../../../../../../helpers/Forms.js";
|
|
8
|
+
import StackChart from "../../../../../../../core/components/Charts/StackChart/index.jsx";
|
|
9
|
+
|
|
10
|
+
export default function IncidentsTimeline({
|
|
11
|
+
selectedRange,
|
|
12
|
+
selectedPartners = {},
|
|
13
|
+
t,
|
|
14
|
+
language,
|
|
15
|
+
goTo,
|
|
16
|
+
user,
|
|
17
|
+
options,
|
|
18
|
+
}) {
|
|
19
|
+
const {
|
|
20
|
+
filters,
|
|
21
|
+
filtersConfig,
|
|
22
|
+
mergeWithData,
|
|
23
|
+
baseMonths,
|
|
24
|
+
baseWeeks,
|
|
25
|
+
} = useIncidentsTimeline({
|
|
26
|
+
t,
|
|
27
|
+
language,
|
|
28
|
+
severityOptions: options?.severityOptions || [],
|
|
29
|
+
selectedRange,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const getSourceParam = useCallback(
|
|
33
|
+
(sourceId) => {
|
|
34
|
+
if (user?.company?.id !== sourceId) return `?sourceId=${sourceId}`;
|
|
35
|
+
return "";
|
|
36
|
+
},
|
|
37
|
+
[user?.company?.id]
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const severityColors = useMemo(
|
|
41
|
+
() => ({
|
|
42
|
+
major: "#cf1322",
|
|
43
|
+
minor: "#fadb14",
|
|
44
|
+
moderate: "#fa8c16",
|
|
45
|
+
undetermined: "#999999",
|
|
46
|
+
placeholder: "transparent",
|
|
47
|
+
}),
|
|
48
|
+
[]
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const defaultFetchConfig = useMemo(
|
|
52
|
+
() => ({
|
|
53
|
+
url: `/incidents-timeline`,
|
|
54
|
+
filters: {
|
|
55
|
+
...filters,
|
|
56
|
+
severity: filters.severity ? filters.severity : "all",
|
|
57
|
+
period: selectedRange,
|
|
58
|
+
sources: selectedPartners?.partners || [],
|
|
59
|
+
},
|
|
60
|
+
defaultData: [],
|
|
61
|
+
stop: selectedPartners?.loading,
|
|
62
|
+
}),
|
|
63
|
+
[filters, selectedRange, selectedPartners]
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const getIncidentsTimelineData = useCallback(
|
|
67
|
+
({ url, filters }) =>
|
|
68
|
+
DashboardService.getWidgetConflictManagement(url, filters),
|
|
69
|
+
[]
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const { data, loading } = useWidgetFetch({
|
|
73
|
+
config: defaultFetchConfig,
|
|
74
|
+
getData: getIncidentsTimelineData,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const renderSeverity = (val) => {
|
|
78
|
+
if (val === "major")
|
|
79
|
+
return <span style={{ color: severityColors.major }}>{t("Major")}</span>;
|
|
80
|
+
if (val === "minor")
|
|
81
|
+
return <span style={{ color: severityColors.minor }}>{t("Minor")}</span>;
|
|
82
|
+
if (val === "moderate")
|
|
83
|
+
return (
|
|
84
|
+
<span style={{ color: severityColors.moderate }}>{t("Moderate")}</span>
|
|
85
|
+
);
|
|
86
|
+
return <span>{t("Undetermined")}</span>;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const chartData = useMemo(() => mergeWithData(data), [data, mergeWithData]);
|
|
90
|
+
|
|
91
|
+
const categories = useMemo(() => {
|
|
92
|
+
if (selectedRange === "12") return baseMonths.map((m) => m.label);
|
|
93
|
+
return baseWeeks.map((w) => w.label);
|
|
94
|
+
}, [selectedRange, baseMonths, baseWeeks]);
|
|
95
|
+
|
|
96
|
+
const getTooltipContent = useCallback(
|
|
97
|
+
({ item }) => {
|
|
98
|
+
if (!item) return { title: "", items: [] };
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
title: item.name || item.label || t("Undetermined"),
|
|
102
|
+
subTitle: renderDateFormatted(item.date, "DD MMM YYYY"),
|
|
103
|
+
link: true,
|
|
104
|
+
onClickLink: () => {
|
|
105
|
+
goTo(
|
|
106
|
+
`/app/view/incidents/${item.datastakeId}/identification${getSourceParam(
|
|
107
|
+
item?.sourceId
|
|
108
|
+
)}`
|
|
109
|
+
);
|
|
110
|
+
},
|
|
111
|
+
items: [
|
|
112
|
+
{ label: t("nashiriki::Source"), value: item?.source || "--" },
|
|
113
|
+
item.severity
|
|
114
|
+
? { label: t("Severity"), value: renderSeverity(item.severity) }
|
|
115
|
+
: null,
|
|
116
|
+
].filter(Boolean),
|
|
117
|
+
};
|
|
118
|
+
},
|
|
119
|
+
[t, goTo, getSourceParam, renderSeverity]
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
return (
|
|
123
|
+
<Widget
|
|
124
|
+
loading={loading}
|
|
125
|
+
filtersConfig={filtersConfig}
|
|
126
|
+
title={t("nashiriki::Incidents Timeline")}
|
|
127
|
+
className="with-border-header"
|
|
128
|
+
>
|
|
129
|
+
<div className="mb-4 flex-1 flex flex-column justify-content-center">
|
|
130
|
+
<StackChart
|
|
131
|
+
data={chartData}
|
|
132
|
+
xFieldKey="label"
|
|
133
|
+
categories={categories}
|
|
134
|
+
seriesField="severity"
|
|
135
|
+
colors={severityColors}
|
|
136
|
+
doConstraints={false}
|
|
137
|
+
renderTooltip={getTooltipContent}
|
|
138
|
+
/>
|
|
139
|
+
</div>
|
|
140
|
+
</Widget>
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
IncidentsTimeline.propTypes = {
|
|
145
|
+
selectedRange: PropTypes.string,
|
|
146
|
+
selectedPartners: PropTypes.object,
|
|
147
|
+
t: PropTypes.func.isRequired,
|
|
148
|
+
language: PropTypes.string,
|
|
149
|
+
goTo: PropTypes.func.isRequired,
|
|
150
|
+
user: PropTypes.object,
|
|
151
|
+
options: PropTypes.shape({
|
|
152
|
+
severityOptions: PropTypes.array,
|
|
153
|
+
}),
|
|
154
|
+
};
|