@geo2france/api-dashboard 1.5.0
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/README.MD +192 -0
- package/dist/components/Attributions/Attribution.test.d.ts +1 -0
- package/dist/components/Attributions/Attribution.test.js +19 -0
- package/dist/components/Attributions/Attributions.d.ts +17 -0
- package/dist/components/Attributions/Attributions.js +30 -0
- package/dist/components/Charts/ChartEcharts.d.ts +7 -0
- package/dist/components/Charts/ChartEcharts.js +35 -0
- package/dist/components/Charts/Pie.d.ts +10 -0
- package/dist/components/Charts/Pie.js +35 -0
- package/dist/components/Charts/YearSerie.d.ts +16 -0
- package/dist/components/Charts/YearSerie.js +70 -0
- package/dist/components/Control/Control.d.ts +21 -0
- package/dist/components/Control/Control.js +84 -0
- package/dist/components/Control/Radio.d.ts +19 -0
- package/dist/components/Control/Radio.js +27 -0
- package/dist/components/Control/Select.d.ts +15 -0
- package/dist/components/Control/Select.js +25 -0
- package/dist/components/DashboardChart/DashboardChart.d.ts +11 -0
- package/dist/components/DashboardChart/DashboardChart.js +42 -0
- package/dist/components/DashboardElement/DashboardElement.d.ts +21 -0
- package/dist/components/DashboardElement/DashboardElement.js +108 -0
- package/dist/components/DashboardElement/hooks.d.ts +28 -0
- package/dist/components/DashboardElement/hooks.js +29 -0
- package/dist/components/DashboardPage/Block.d.ts +15 -0
- package/dist/components/DashboardPage/Block.js +40 -0
- package/dist/components/DashboardPage/DashboardPage.test.d.ts +1 -0
- package/dist/components/DashboardPage/DashboardPage.test.js +40 -0
- package/dist/components/DashboardPage/Page.d.ts +42 -0
- package/dist/components/DashboardPage/Page.js +80 -0
- package/dist/components/Dataset/DataPreview.d.ts +12 -0
- package/dist/components/Dataset/DataPreview.js +21 -0
- package/dist/components/Dataset/Dataset.d.ts +17 -0
- package/dist/components/Dataset/Dataset.js +94 -0
- package/dist/components/Dataset/Filter.d.ts +9 -0
- package/dist/components/Dataset/Filter.js +7 -0
- package/dist/components/Dataset/Join.d.ts +8 -0
- package/dist/components/Dataset/Join.js +7 -0
- package/dist/components/Dataset/Producer.d.ts +18 -0
- package/dist/components/Dataset/Producer.js +27 -0
- package/dist/components/Dataset/Provider.d.ts +21 -0
- package/dist/components/Dataset/Provider.js +22 -0
- package/dist/components/Dataset/Transform.d.ts +6 -0
- package/dist/components/Dataset/Transform.js +7 -0
- package/dist/components/Dataset/hooks.d.ts +24 -0
- package/dist/components/Dataset/hooks.js +19 -0
- package/dist/components/Debug/Debug.d.ts +1 -0
- package/dist/components/Debug/Debug.js +24 -0
- package/dist/components/FlipCard/FlipCard.d.ts +12 -0
- package/dist/components/FlipCard/FlipCard.js +38 -0
- package/dist/components/FlipCard/FlipCard.test.d.ts +1 -0
- package/dist/components/FlipCard/FlipCard.test.js +36 -0
- package/dist/components/KeyFigure/KeyFigure.d.ts +18 -0
- package/dist/components/KeyFigure/KeyFigure.js +13 -0
- package/dist/components/Layout/DashboardApp.d.ts +18 -0
- package/dist/components/Layout/DashboardApp.js +46 -0
- package/dist/components/Layout/Error.d.ts +2 -0
- package/dist/components/Layout/Error.js +6 -0
- package/dist/components/Layout/Footer.d.ts +6 -0
- package/dist/components/Layout/Footer.js +47 -0
- package/dist/components/Layout/Sider.d.ts +9 -0
- package/dist/components/Layout/Sider.js +48 -0
- package/dist/components/LoadingContainer/LoadingContainer.d.ts +17 -0
- package/dist/components/LoadingContainer/LoadingContainer.js +33 -0
- package/dist/components/MapLegend/MapLegend.d.ts +12 -0
- package/dist/components/MapLegend/MapLegend.js +19 -0
- package/dist/components/NextPrevSelect/NextPrevSelect.d.ts +17 -0
- package/dist/components/NextPrevSelect/NextPrevSelect.js +49 -0
- package/dist/components/Palette/Palette.d.ts +18 -0
- package/dist/components/Palette/Palette.js +29 -0
- package/dist/data_providers/datafair/datafair.test.d.ts +1 -0
- package/dist/data_providers/datafair/datafair.test.js +39 -0
- package/dist/data_providers/datafair/index.d.ts +15 -0
- package/dist/data_providers/datafair/index.js +33 -0
- package/dist/data_providers/datafair/utils/axios.d.ts +2 -0
- package/dist/data_providers/datafair/utils/axios.js +13 -0
- package/dist/data_providers/datafair/utils/generateFilter.d.ts +1 -0
- package/dist/data_providers/datafair/utils/generateFilter.js +40 -0
- package/dist/data_providers/datafair/utils/generateSort.d.ts +1 -0
- package/dist/data_providers/datafair/utils/generateSort.js +19 -0
- package/dist/data_providers/datafair/utils/index.d.ts +4 -0
- package/dist/data_providers/datafair/utils/index.js +4 -0
- package/dist/data_providers/datafair/utils/mapOperator.d.ts +1 -0
- package/dist/data_providers/datafair/utils/mapOperator.js +13 -0
- package/dist/data_providers/file/index.d.ts +6 -0
- package/dist/data_providers/file/index.js +25 -0
- package/dist/data_providers/file/utils/axios.d.ts +2 -0
- package/dist/data_providers/file/utils/axios.js +26 -0
- package/dist/data_providers/types.d.ts +52 -0
- package/dist/data_providers/types.js +2 -0
- package/dist/data_providers/wfs/index.d.ts +3 -0
- package/dist/data_providers/wfs/index.js +43 -0
- package/dist/data_providers/wfs/utils/axios.d.ts +2 -0
- package/dist/data_providers/wfs/utils/axios.js +26 -0
- package/dist/data_providers/wfs/utils/generateFilter.d.ts +4 -0
- package/dist/data_providers/wfs/utils/generateFilter.js +45 -0
- package/dist/data_providers/wfs/utils/generateSort.d.ts +1 -0
- package/dist/data_providers/wfs/utils/generateSort.js +20 -0
- package/dist/data_providers/wfs/utils/index.d.ts +4 -0
- package/dist/data_providers/wfs/utils/index.js +4 -0
- package/dist/data_providers/wfs/utils/mapOperator.d.ts +1 -0
- package/dist/data_providers/wfs/utils/mapOperator.js +36 -0
- package/dist/data_providers/wfs/wfs.test.d.ts +1 -0
- package/dist/data_providers/wfs/wfs.test.js +60 -0
- package/dist/dsl/index.d.ts +19 -0
- package/dist/dsl/index.js +19 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +33 -0
- package/dist/types.d.ts +15 -0
- package/dist/types.js +1 -0
- package/dist/utils/baserecordtogeojsonpoint.d.ts +13 -0
- package/dist/utils/baserecordtogeojsonpoint.js +17 -0
- package/dist/utils/cardStyles.d.ts +2 -0
- package/dist/utils/cardStyles.js +12 -0
- package/dist/utils/deepmerge.d.ts +2 -0
- package/dist/utils/deepmerge.js +24 -0
- package/dist/utils/route_utils.d.ts +6 -0
- package/dist/utils/route_utils.js +14 -0
- package/dist/utils/useApi.d.ts +12 -0
- package/dist/utils/useApi.js +14 -0
- package/dist/utils/useMapControl.d.ts +8 -0
- package/dist/utils/useMapControl.js +24 -0
- package/dist/utils/useSearchParamsState.d.ts +11 -0
- package/dist/utils/useSearchParamsState.js +18 -0
- package/dist/utils/usechartexports.d.ts +17 -0
- package/dist/utils/usechartexports.js +39 -0
- package/dist/utils/usecharthightlight.d.ts +25 -0
- package/dist/utils/usecharthightlight.js +44 -0
- package/package.json +98 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import alasql from "alasql";
|
|
3
|
+
import ReactECharts from 'echarts-for-react';
|
|
4
|
+
import { useRef } from "react";
|
|
5
|
+
import { useChartData, useDashboardElement } from "../DashboardElement/hooks";
|
|
6
|
+
import deepMerge from "../../utils/deepmerge";
|
|
7
|
+
// Les données doivent être de la forme {axeA : axeB : } ?
|
|
8
|
+
const DashboardChart = ({ data, chart_type = 'line', reverse_axies = false, echarts_option = {}, sql }) => {
|
|
9
|
+
const chartRef = useRef();
|
|
10
|
+
useDashboardElement({ chartRef });
|
|
11
|
+
const data_xy = sql ? alasql(sql, [data]) : data;
|
|
12
|
+
useChartData({ data: data_xy });
|
|
13
|
+
const keys = Object.keys(data_xy[0]);
|
|
14
|
+
const axis0 = {
|
|
15
|
+
type: typeof data_xy[0][keys[0]] === 'number' ? 'value' : 'category',
|
|
16
|
+
name: keys[0]
|
|
17
|
+
};
|
|
18
|
+
const axis1 = {
|
|
19
|
+
type: typeof data_xy[0][keys[1]] === 'number' ? 'value' : 'category',
|
|
20
|
+
name: keys[1]
|
|
21
|
+
};
|
|
22
|
+
const options = {
|
|
23
|
+
series: [
|
|
24
|
+
{
|
|
25
|
+
type: chart_type,
|
|
26
|
+
data: data_xy.map((e) => reverse_axies ?
|
|
27
|
+
[e[keys[1]], e[keys[0]]]
|
|
28
|
+
: [e[keys[0]], e[keys[1]]])
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
//@ts-ignore
|
|
32
|
+
xAxis: {
|
|
33
|
+
...reverse_axies ? axis1 : axis0
|
|
34
|
+
},
|
|
35
|
+
//@ts-ignore
|
|
36
|
+
yAxis: {
|
|
37
|
+
...reverse_axies ? axis0 : axis1
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
return (_jsx(ReactECharts, { option: deepMerge(options, echarts_option), ref: chartRef }));
|
|
41
|
+
};
|
|
42
|
+
export default DashboardChart;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React, { ReactElement, ReactNode } from "react";
|
|
2
|
+
import { SourceMakerProps, SourceProps } from "../Attributions/Attributions";
|
|
3
|
+
import { License } from "../../types";
|
|
4
|
+
export declare const chartContext: React.Context<any>;
|
|
5
|
+
export interface IDashboardElementProps {
|
|
6
|
+
title: string;
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
isFetching?: boolean;
|
|
9
|
+
header?: boolean;
|
|
10
|
+
attributions?: SourceProps[] | SourceMakerProps;
|
|
11
|
+
toolbox?: boolean;
|
|
12
|
+
fullscreen?: boolean;
|
|
13
|
+
exportPNG?: boolean;
|
|
14
|
+
exportData?: boolean;
|
|
15
|
+
description?: ReactElement | string;
|
|
16
|
+
licenses?: License[];
|
|
17
|
+
section?: string;
|
|
18
|
+
virtual?: boolean;
|
|
19
|
+
}
|
|
20
|
+
declare const DashboardElement: React.FC<IDashboardElementProps>;
|
|
21
|
+
export default DashboardElement;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { DownloadOutlined, FileImageOutlined, FullscreenOutlined, MoreOutlined, } from "@ant-design/icons";
|
|
3
|
+
import { HiQuestionMarkCircle } from "react-icons/hi2";
|
|
4
|
+
import { Card, theme, Modal, Dropdown, Flex, Button, Popover, Typography } from "antd";
|
|
5
|
+
import React, { createContext, useEffect, useState } from "react";
|
|
6
|
+
import Attribution from "../Attributions/Attributions";
|
|
7
|
+
import { useChartExport } from "../../utils/usechartexports";
|
|
8
|
+
import LoadingContainer from "../LoadingContainer/LoadingContainer";
|
|
9
|
+
import { cardStyles } from "../../utils/cardStyles";
|
|
10
|
+
const { useToken } = theme;
|
|
11
|
+
const { Text } = Typography;
|
|
12
|
+
export const chartContext = createContext({
|
|
13
|
+
setchartRef: () => { },
|
|
14
|
+
setData: () => { },
|
|
15
|
+
setNodata: () => { }
|
|
16
|
+
});
|
|
17
|
+
const DashboardElement = ({ children, title, header = true, attributions, isFetching = false, toolbox = true, fullscreen = true, exportPNG = true, exportData = true, description, licenses = ['CC', 'BY'], virtual = false, }) => {
|
|
18
|
+
const { token } = useToken();
|
|
19
|
+
const [modalIsOpen, setModalIsOpen] = useState(false);
|
|
20
|
+
const [chartRef, setchartRef] = useState(undefined);
|
|
21
|
+
const [data, setData] = useState(undefined);
|
|
22
|
+
const [nodata, setNodata] = useState(false);
|
|
23
|
+
const [requestDlImage, setRequestDlImage] = useState(false);
|
|
24
|
+
const [requestDlData, setrequestDlData] = useState(null);
|
|
25
|
+
const { img64, exportImage } = useChartExport({ chartRef: chartRef });
|
|
26
|
+
const downloadImage = () => {
|
|
27
|
+
exportImage();
|
|
28
|
+
setRequestDlImage(true);
|
|
29
|
+
};
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
if (img64 && requestDlImage) {
|
|
32
|
+
const link = document.createElement("a");
|
|
33
|
+
link.href = img64;
|
|
34
|
+
link.download = `${title}.png`;
|
|
35
|
+
link.style.display = "none";
|
|
36
|
+
document.body.appendChild(link);
|
|
37
|
+
link.click();
|
|
38
|
+
document.body.removeChild(link);
|
|
39
|
+
setRequestDlImage(false);
|
|
40
|
+
}
|
|
41
|
+
}, [img64]);
|
|
42
|
+
const downloadData = (filetype) => {
|
|
43
|
+
setrequestDlData(filetype);
|
|
44
|
+
};
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
if (data && requestDlData) {
|
|
47
|
+
const handleDl = async () => {
|
|
48
|
+
const XLSX = await import("xlsx");
|
|
49
|
+
const worksheet = XLSX.utils.json_to_sheet(data);
|
|
50
|
+
const workbook = XLSX.utils.book_new();
|
|
51
|
+
XLSX.utils.book_append_sheet(workbook, worksheet, "data");
|
|
52
|
+
XLSX.writeFile(workbook, `${title}.${requestDlData}`, {
|
|
53
|
+
compression: true,
|
|
54
|
+
});
|
|
55
|
+
setrequestDlData(null);
|
|
56
|
+
};
|
|
57
|
+
handleDl();
|
|
58
|
+
}
|
|
59
|
+
}, [requestDlData]);
|
|
60
|
+
const fullscreenChildren = React.Children.map(children, (child, index) => {
|
|
61
|
+
if (index === 0 && React.isValidElement(child)) {
|
|
62
|
+
return React.cloneElement(child, {
|
|
63
|
+
...child.props?.style,
|
|
64
|
+
style: { height: "80vh" },
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return child;
|
|
68
|
+
});
|
|
69
|
+
const dd_items = [
|
|
70
|
+
{
|
|
71
|
+
key: "fullscreen",
|
|
72
|
+
label: (_jsxs("a", { onClick: () => setModalIsOpen(true), children: [_jsx(FullscreenOutlined, {}), " Plein \u00E9cran"] })),
|
|
73
|
+
disabled: !fullscreen,
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
key: "export_img",
|
|
77
|
+
label: (_jsxs("a", { onClick: downloadImage, children: [_jsx(FileImageOutlined, {}), " PNG"] })),
|
|
78
|
+
disabled: !chartRef || !exportPNG,
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
key: "export_data_csv",
|
|
82
|
+
label: (_jsxs("a", { onClick: () => downloadData("csv"), children: [_jsx(DownloadOutlined, {}), " CSV"] })),
|
|
83
|
+
disabled: !data || !exportData,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
key: "export_data_xls",
|
|
87
|
+
label: (_jsxs("a", { onClick: () => downloadData("xlsx"), children: [_jsx(DownloadOutlined, {}), " XLSX"] })),
|
|
88
|
+
disabled: !data || !exportData,
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
key: "export_data_ods",
|
|
92
|
+
label: (_jsxs("a", { onClick: () => downloadData("ods"), children: [_jsx(DownloadOutlined, {}), " ODS"] })),
|
|
93
|
+
disabled: !data || !exportData,
|
|
94
|
+
},
|
|
95
|
+
];
|
|
96
|
+
const dropdown_toolbox = (_jsx(Dropdown, { menu: { items: dd_items }, children: _jsx("a", { style: { color: token.colorTextBase }, children: _jsx(MoreOutlined, { style: { marginLeft: 10 } }) }) }));
|
|
97
|
+
return (_jsxs(_Fragment, { children: [_jsx(Card, { className: "dashboard-element", styles: cardStyles, style: {
|
|
98
|
+
backgroundColor: virtual ? 'transparent' : undefined,
|
|
99
|
+
boxShadow: virtual ? 'none' : undefined,
|
|
100
|
+
height: "100%",
|
|
101
|
+
display: "flex",
|
|
102
|
+
flexDirection: "column",
|
|
103
|
+
}, variant: virtual ? 'borderless' : 'outlined', title: header && !virtual &&
|
|
104
|
+
_jsxs(Flex, { justify: "space-between", align: "center", children: [_jsx("span", { style: { overflow: "hidden", paddingRight: 15 }, children: title }), _jsx("div", { style: { marginRight: 5, fontSize: 16 }, children: toolbox && dropdown_toolbox })] }), children: _jsxs(Flex, { vertical: true, justify: "space-between", style: { height: "100%" }, children: [_jsx(chartContext.Provider, { value: { chartRef, setchartRef, setData, setNodata }, children: _jsx(LoadingContainer, { isFetching: isFetching, noData: nodata, children: children }) }), _jsxs(Flex, { justify: "flex-end", align: "flex-end", style: { marginRight: 5 }, children: [attributions && (_jsx("div", { style: { marginTop: "auto" }, children: _jsx(Attribution, { licenses: licenses, data: attributions }) })), description && (_jsx(Popover, { content: _jsx("div", { style: { maxWidth: 800 }, children: typeof description === "string" ?
|
|
105
|
+
_jsxs(Text, { italic: true, type: "secondary", children: [" ", description, " "] })
|
|
106
|
+
: _jsx(_Fragment, { children: description }) }), children: _jsx(Button, { type: "link", icon: _jsx(HiQuestionMarkCircle, {}), style: { fontSize: "150%" } }) }))] })] }) }), toolbox && fullscreen && (_jsxs(Modal, { forceRender: true, title: title, open: modalIsOpen, onCancel: () => setModalIsOpen(false), onOk: () => setModalIsOpen(false), footer: null, wrapClassName: "modal-fullscreen", children: [fullscreenChildren, attributions && _jsx(Attribution, { data: attributions })] }))] }));
|
|
107
|
+
};
|
|
108
|
+
export default DashboardElement;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { MutableRefObject } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Hook permettant de faire remonter la référence du graphique dans le composant DashboardElement
|
|
4
|
+
* Ceci est nécessaire pour les fonctionnalités d'export graphique
|
|
5
|
+
* @example
|
|
6
|
+
* useDashboardElement({chartRef:chartRef})
|
|
7
|
+
*/
|
|
8
|
+
export interface useDashboardElementProps {
|
|
9
|
+
chartRef?: MutableRefObject<any>;
|
|
10
|
+
}
|
|
11
|
+
export declare const useDashboardElement: ({ chartRef }: useDashboardElementProps) => void;
|
|
12
|
+
/**
|
|
13
|
+
* Hook permettant de remonter les données au Dashboard Element
|
|
14
|
+
* @param {any} props.data - Les données à proposer au téléchargement.
|
|
15
|
+
* @param {Array<any>} [props.dependencies=[]] - Les dépendances suspeptibles de modifier les données
|
|
16
|
+
*/
|
|
17
|
+
export interface useChartDataProps {
|
|
18
|
+
data?: any[];
|
|
19
|
+
dependencies?: any[];
|
|
20
|
+
}
|
|
21
|
+
export declare const useChartData: ({ data, dependencies }: useChartDataProps) => void;
|
|
22
|
+
/**
|
|
23
|
+
* Hook permettant d'indiquer au DashboardElement que aucune données n'est disponible
|
|
24
|
+
* Il est aussi possible d'avoir ce comportement en passant un tableau vide dans useChartData
|
|
25
|
+
* Deprécié (utilisez useChartData avec un tableau vide)
|
|
26
|
+
* @param {boolean} noData - True si aucune donnée n'est disponible.
|
|
27
|
+
*/
|
|
28
|
+
export declare const useNoData: (noData: boolean) => void;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { chartContext } from "./DashboardElement";
|
|
2
|
+
import { useContext, useEffect } from "react";
|
|
3
|
+
export const useDashboardElement = ({ chartRef }) => {
|
|
4
|
+
const { setchartRef } = useContext(chartContext); //Gérer les cas où ce contexte n'existe pas
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
if (setchartRef) {
|
|
7
|
+
setchartRef(chartRef);
|
|
8
|
+
}
|
|
9
|
+
}, [chartRef]);
|
|
10
|
+
};
|
|
11
|
+
export const useChartData = ({ data, dependencies = [] }) => {
|
|
12
|
+
const { setData, setNodata } = useContext(chartContext);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
setData(data);
|
|
15
|
+
data === undefined || data.length < 1 ? setNodata(true) : setNodata(false);
|
|
16
|
+
}, dependencies);
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Hook permettant d'indiquer au DashboardElement que aucune données n'est disponible
|
|
20
|
+
* Il est aussi possible d'avoir ce comportement en passant un tableau vide dans useChartData
|
|
21
|
+
* Deprécié (utilisez useChartData avec un tableau vide)
|
|
22
|
+
* @param {boolean} noData - True si aucune donnée n'est disponible.
|
|
23
|
+
*/
|
|
24
|
+
export const useNoData = (noData) => {
|
|
25
|
+
const { setNodata } = useContext(chartContext);
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
setNodata(noData);
|
|
28
|
+
}, [noData]); // !
|
|
29
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { SimpleRecord } from "../../types";
|
|
2
|
+
export interface ChartBlockConfig {
|
|
3
|
+
title?: string;
|
|
4
|
+
dataExport?: SimpleRecord[];
|
|
5
|
+
}
|
|
6
|
+
type ChartBlockContextType = {
|
|
7
|
+
config: ChartBlockConfig;
|
|
8
|
+
setConfig: (config: ChartBlockConfig) => void;
|
|
9
|
+
};
|
|
10
|
+
export declare const ChartBlockContext: import("react").Context<ChartBlockContextType | undefined>;
|
|
11
|
+
interface IChartBlockProps {
|
|
12
|
+
children: React.ReactElement;
|
|
13
|
+
}
|
|
14
|
+
export declare const DSL_ChartBlock: React.FC<IChartBlockProps>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Card, Dropdown, theme } from "antd";
|
|
3
|
+
import { createContext, useId, useState } from "react";
|
|
4
|
+
import { FaFileCsv } from "react-icons/fa";
|
|
5
|
+
import { AiOutlineMore } from "react-icons/ai";
|
|
6
|
+
import { ProducersFooter } from "../Dataset/Producer";
|
|
7
|
+
const { useToken } = theme;
|
|
8
|
+
export const ChartBlockContext = createContext(undefined);
|
|
9
|
+
export const DSL_ChartBlock = ({ children }) => {
|
|
10
|
+
const id = useId();
|
|
11
|
+
const [config, setConfig] = useState({});
|
|
12
|
+
const { token } = useToken();
|
|
13
|
+
const menu_items = [
|
|
14
|
+
{
|
|
15
|
+
key: "export_data_csv",
|
|
16
|
+
label: (_jsxs("a", { onClick: () => handleExportData(), children: [_jsx(FaFileCsv, {}), " CSV"] })),
|
|
17
|
+
disabled: config.dataExport === undefined
|
|
18
|
+
},
|
|
19
|
+
];
|
|
20
|
+
const has_action = menu_items.some(item => !item.disabled);
|
|
21
|
+
const dropdown_toolbox = (_jsx(Dropdown, { menu: { items: menu_items }, children: _jsx("a", { style: { color: token.colorTextBase }, children: _jsx(AiOutlineMore, {}) }) }));
|
|
22
|
+
const handleExportData = () => {
|
|
23
|
+
console.log('datadl');
|
|
24
|
+
console.log(config.dataExport);
|
|
25
|
+
const DL = async () => {
|
|
26
|
+
if (config.dataExport === undefined) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const XLSX = await import("xlsx");
|
|
30
|
+
const worksheet = XLSX.utils.json_to_sheet(config.dataExport);
|
|
31
|
+
const workbook = XLSX.utils.book_new();
|
|
32
|
+
XLSX.utils.book_append_sheet(workbook, worksheet, "data");
|
|
33
|
+
XLSX.writeFile(workbook, `${config.title || id}.csv`, {
|
|
34
|
+
compression: true,
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
DL();
|
|
38
|
+
};
|
|
39
|
+
return (_jsx(ChartBlockContext.Provider, { value: { config: config, setConfig: (e) => setConfig(e) }, children: _jsxs(Card, { style: { height: '100%' }, extra: has_action && dropdown_toolbox, title: config.title, children: [children, _jsx(ProducersFooter, { component: children })] }) }));
|
|
40
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import '@testing-library/jest-dom';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import '@testing-library/jest-dom';
|
|
4
|
+
import DashboardPage from './Page';
|
|
5
|
+
import DashboardElement from '../DashboardElement/DashboardElement';
|
|
6
|
+
import { MemoryRouter } from 'react-router-dom';
|
|
7
|
+
// TODO : test l'affichage des DashboardElement et les filtres radio
|
|
8
|
+
// TOFIX : DashboardElement sans rien a l'intérieur n'affiche rien
|
|
9
|
+
describe("DashboardPage Component", () => {
|
|
10
|
+
beforeAll(() => {
|
|
11
|
+
Object.defineProperty(window, 'matchMedia', {
|
|
12
|
+
writable: true,
|
|
13
|
+
value: jest.fn().mockImplementation((query) => ({
|
|
14
|
+
matches: false,
|
|
15
|
+
media: query,
|
|
16
|
+
onchange: null,
|
|
17
|
+
addListener: jest.fn(), // Deprecated
|
|
18
|
+
removeListener: jest.fn(), // Deprecated
|
|
19
|
+
addEventListener: jest.fn(),
|
|
20
|
+
removeEventListener: jest.fn(),
|
|
21
|
+
dispatchEvent: jest.fn(),
|
|
22
|
+
})),
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
test("initial state", async () => {
|
|
26
|
+
// Génération DOM virtuel et sélection des noeuds
|
|
27
|
+
render(_jsx(MemoryRouter, { children: _jsxs(DashboardPage, { children: [_jsx(DashboardElement, { title: "Graphique 1", section: 'Section 1', children: _jsx(_Fragment, {}) }), _jsx(DashboardElement, { title: "Graphique 2", section: 'Section 2', children: _jsx(_Fragment, {}) })] }) }));
|
|
28
|
+
// Assertions
|
|
29
|
+
expect(screen.getByRole('radio', { name: "Section 1" })).toBeInTheDocument();
|
|
30
|
+
expect(screen.queryByRole('radio', { name: "Section 3" })).not.toBeInTheDocument();
|
|
31
|
+
expect(screen.queryByRole('radio', { name: "Autres" })).not.toBeInTheDocument();
|
|
32
|
+
expect(screen.getAllByRole('radio')).toHaveLength(2);
|
|
33
|
+
});
|
|
34
|
+
test("Others section", async () => {
|
|
35
|
+
render(_jsx(MemoryRouter, { children: _jsxs(DashboardPage, { children: [_jsx(DashboardElement, { title: "Graphique 1", section: 'Section 1', children: _jsx(_Fragment, {}) }), _jsx(DashboardElement, { title: "Graphique 2", section: 'Section 2', children: _jsx(_Fragment, {}) }), _jsx(DashboardElement, { title: "Graphique 3", children: _jsx(_Fragment, {}) })] }) }));
|
|
36
|
+
// Assertions
|
|
37
|
+
expect(screen.queryByRole('radio', { name: "Autres" })).toBeInTheDocument();
|
|
38
|
+
expect(screen.getAllByRole('radio')).toHaveLength(3);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { RowProps } from "antd";
|
|
2
|
+
import DashboardElement from "../DashboardElement/DashboardElement";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { SimpleRecord } from "../../types";
|
|
5
|
+
type Section = {
|
|
6
|
+
key: string;
|
|
7
|
+
libel?: string;
|
|
8
|
+
order?: number;
|
|
9
|
+
hide?: boolean;
|
|
10
|
+
disable?: boolean;
|
|
11
|
+
};
|
|
12
|
+
interface IDashboardPageProps {
|
|
13
|
+
control?: React.ReactElement | React.ReactElement[];
|
|
14
|
+
children: React.ReactElement<typeof DashboardElement>[] | React.ReactElement<typeof DashboardElement>;
|
|
15
|
+
row_gutter?: RowProps['gutter'];
|
|
16
|
+
sections?: string[] | Section[];
|
|
17
|
+
}
|
|
18
|
+
declare const DashboardPage: React.FC<IDashboardPageProps>;
|
|
19
|
+
export default DashboardPage;
|
|
20
|
+
type dataset = {
|
|
21
|
+
id: string;
|
|
22
|
+
resource: string;
|
|
23
|
+
data?: SimpleRecord[];
|
|
24
|
+
isFetching: boolean;
|
|
25
|
+
isError: boolean;
|
|
26
|
+
producers?: any[];
|
|
27
|
+
};
|
|
28
|
+
type ControlContextType = {
|
|
29
|
+
values: Record<string, any>;
|
|
30
|
+
pushValue: (control: {
|
|
31
|
+
name: string;
|
|
32
|
+
value: any;
|
|
33
|
+
}) => void;
|
|
34
|
+
};
|
|
35
|
+
export declare const DatasetContext: React.Context<Record<string, dataset>>;
|
|
36
|
+
export declare const DatasetRegistryContext: React.Context<(dataset: dataset) => void>;
|
|
37
|
+
export declare const ControlContext: React.Context<ControlContextType | undefined>;
|
|
38
|
+
interface IDSLDashboardPageProps {
|
|
39
|
+
children: React.ReactNode;
|
|
40
|
+
name?: string;
|
|
41
|
+
}
|
|
42
|
+
export declare const DSL_DashboardPage: React.FC<IDSLDashboardPageProps>;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { Button, Col, Dropdown, Flex, Grid, Layout, Radio, Row } from "antd";
|
|
3
|
+
import React, { isValidElement, useState, createContext, } from "react";
|
|
4
|
+
import { Helmet } from "react-helmet-async";
|
|
5
|
+
import { useSearchParamsState } from "../../utils/useSearchParamsState";
|
|
6
|
+
import Control, { DSL_Control } from "../Control/Control";
|
|
7
|
+
import { Dataset, Debug, Provider } from "../../dsl";
|
|
8
|
+
import { DSL_ChartBlock } from "./Block";
|
|
9
|
+
import { DEFAULT_PALETTE, Palette, PaletteContext } from "../Palette/Palette";
|
|
10
|
+
const { Header } = Layout;
|
|
11
|
+
const getSection = (child) => React.isValidElement(child) ? child.props.section : undefined;
|
|
12
|
+
const DashboardPage = ({ children: children_input, control, row_gutter = [8, 8], sections }) => {
|
|
13
|
+
let sections_std = [];
|
|
14
|
+
const screens = Grid.useBreakpoint();
|
|
15
|
+
const children = React.Children.toArray(children_input).filter((child) => React.isValidElement(child));
|
|
16
|
+
if (sections && typeof (sections[0]) === 'string') {
|
|
17
|
+
sections_std = sections.map((s) => ({ key: s }));
|
|
18
|
+
}
|
|
19
|
+
else if (sections && typeof (sections[0]) === 'object') {
|
|
20
|
+
sections_std = sections;
|
|
21
|
+
}
|
|
22
|
+
else { //Automatic section based on children properties
|
|
23
|
+
sections_std = [...new Set(children.map((child) => getSection(child) ?? 'Autres'))].map((s) => ({ key: s }));
|
|
24
|
+
}
|
|
25
|
+
const [activeTab, setActiveTab] = useSearchParamsState('tab', sections_std[0].key);
|
|
26
|
+
sections_std.sort((a, b) => (a?.order || Infinity) - (b?.order || Infinity));
|
|
27
|
+
return (_jsxs(_Fragment, { children: [_jsx(Control, { children: _jsxs(Flex, { wrap: true, justify: "flex-start", align: "flex-start", gap: "small", children: [_jsx("div", { children: sections_std.length > 1 && !screens.md &&
|
|
28
|
+
_jsx(Dropdown.Button, { menu: { selectedKeys: [activeTab],
|
|
29
|
+
items: sections_std.map((section) => ({
|
|
30
|
+
label: section.libel || section.key,
|
|
31
|
+
key: section.key,
|
|
32
|
+
onClick: () => setActiveTab(section.key)
|
|
33
|
+
})) }, trigger: ['click'], buttonsRender: ([_lb, rb]) => [_jsx(Button, { type: 'primary', children: activeTab }), rb] }) }), sections_std.length > 1 && screens.md &&
|
|
34
|
+
_jsx(Radio.Group, { optionType: "button", buttonStyle: "solid", options: sections_std.map((section) => ({
|
|
35
|
+
label: section.libel || section.key,
|
|
36
|
+
value: section.key
|
|
37
|
+
})), value: activeTab, onChange: (e) => setActiveTab(e.target.value) }), control] }) }), _jsx(Row, { gutter: row_gutter, style: { margin: 16 }, children: children.map((child, idx) => ({ child, idx })).filter(({ child }) => (getSection(child) ?? 'Autres') == activeTab).map(({ child, idx }) => _jsx(Col, { xl: 12, xs: 24, children: child }, idx)) })] }));
|
|
38
|
+
};
|
|
39
|
+
export default DashboardPage;
|
|
40
|
+
export const DatasetContext = createContext({});
|
|
41
|
+
export const DatasetRegistryContext = createContext(() => { }); // A modifier, utiliser un seul context
|
|
42
|
+
export const ControlContext = createContext(undefined);
|
|
43
|
+
export const DSL_DashboardPage = ({ name = 'Tableau de bord', children }) => {
|
|
44
|
+
const [datasets, setdatasets] = useState({});
|
|
45
|
+
const [palette, setPalette] = useState(DEFAULT_PALETTE);
|
|
46
|
+
//const allDatasetLoaded = Object.values(datasets).every(d => !d.isFetching);
|
|
47
|
+
//const isDatasetError = Object.values(datasets).some(d => d.isError);
|
|
48
|
+
// Ajouter ou mettre à jour un dataset
|
|
49
|
+
const pushDataset = (d) => {
|
|
50
|
+
setdatasets(prev => ({
|
|
51
|
+
...prev,
|
|
52
|
+
[d.id]: d
|
|
53
|
+
}));
|
|
54
|
+
};
|
|
55
|
+
const childrenArray = React.Children.toArray(children).filter(isValidElement);
|
|
56
|
+
const logicalComponents = [Dataset.name, Provider.name, Palette.name, Debug.name]; //Composant logiques, a ne pas mettre dans la grid
|
|
57
|
+
const getComponentKind = (c) => {
|
|
58
|
+
if (typeof (c.type) != 'string' && logicalComponents.includes(c.type.name)) {
|
|
59
|
+
return "logical";
|
|
60
|
+
}
|
|
61
|
+
else if (typeof (c.type) != 'string' && c.type.name == DSL_Control.name) {
|
|
62
|
+
return "control";
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
return "other";
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
const visible_components = childrenArray.filter((c) => c && getComponentKind(c) == 'other');
|
|
69
|
+
const logic_components = childrenArray.filter((c) => getComponentKind(c) == 'logical');
|
|
70
|
+
const control_components = childrenArray.filter((c) => getComponentKind(c) == 'control');
|
|
71
|
+
return (_jsxs(_Fragment, { children: [_jsx(Helmet, { children: _jsx("title", { children: name }) }), _jsx(DatasetRegistryContext.Provider, { value: pushDataset, children: _jsx(DatasetContext.Provider, { value: datasets, children: _jsxs(PaletteContext.Provider, { value: { palette, setPalette }, children: [control_components.length > 0 && _jsx(Header, { style: {
|
|
72
|
+
padding: 12,
|
|
73
|
+
position: "sticky",
|
|
74
|
+
top: 0,
|
|
75
|
+
zIndex: 600, // maplibre top zIndex if 500
|
|
76
|
+
backgroundColor: "#fff",
|
|
77
|
+
height: "auto",
|
|
78
|
+
width: "100%",
|
|
79
|
+
}, children: control_components }), _jsx(Row, { gutter: [8, 8], style: { margin: 16 }, children: visible_components.map((component, idx) => _jsx(Col, { xl: 12, xs: 24, children: _jsx(DSL_ChartBlock, { children: component }) }, idx)) }), logic_components] }) }) })] }));
|
|
80
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface DatasetBadgeStatusProps {
|
|
2
|
+
isError?: boolean;
|
|
3
|
+
isFetching?: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare const DatasetBadgeStatus: React.FC<DatasetBadgeStatusProps>;
|
|
6
|
+
interface DSL_DataPreviewProps {
|
|
7
|
+
dataset?: string;
|
|
8
|
+
pageSize?: number;
|
|
9
|
+
rowKey?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare const DSL_DataPreview: React.FC<DSL_DataPreviewProps>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import Table from "antd/es/table";
|
|
3
|
+
import { Badge } from "antd";
|
|
4
|
+
import { useDataset } from "./hooks";
|
|
5
|
+
export const DatasetBadgeStatus = ({ isError, isFetching }) => {
|
|
6
|
+
return _jsx(Badge, { status: isError ? "error" : isFetching ? 'processing' : 'success' });
|
|
7
|
+
};
|
|
8
|
+
export const DSL_DataPreview = ({ dataset: dataset_id, pageSize, rowKey }) => {
|
|
9
|
+
const dataset = useDataset(dataset_id);
|
|
10
|
+
const data = dataset?.data;
|
|
11
|
+
if (data === undefined) { // TODO : Afficher Empty si les données ont fini de fetcher et data est null ou lenght==0
|
|
12
|
+
return _jsx(_Fragment, {});
|
|
13
|
+
}
|
|
14
|
+
const columns = Object.keys(data[0] || {}).map((key) => ({
|
|
15
|
+
title: key,
|
|
16
|
+
dataIndex: key,
|
|
17
|
+
key,
|
|
18
|
+
ellipsis: true,
|
|
19
|
+
}));
|
|
20
|
+
return (_jsxs(_Fragment, { children: [_jsxs("h3", { children: [_jsx(DatasetBadgeStatus, { isError: dataset?.isError, isFetching: dataset?.isFetching }), " ", dataset?.resource] }), _jsx(Table, { pagination: { pageSize: pageSize }, dataSource: data, columns: columns, rowKey: (row) => rowKey ? row[rowKey] : JSON.stringify(row) })] }));
|
|
21
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { CrudFilters, DataProvider } from "../../data_providers/types";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { ProviderType } from "./Provider";
|
|
5
|
+
interface IDatasetProps {
|
|
6
|
+
id: string;
|
|
7
|
+
provider?: DataProvider;
|
|
8
|
+
url?: string;
|
|
9
|
+
type?: ProviderType;
|
|
10
|
+
resource: string;
|
|
11
|
+
filters?: CrudFilters;
|
|
12
|
+
children?: ReactNode;
|
|
13
|
+
pageSize?: number;
|
|
14
|
+
meta?: any;
|
|
15
|
+
}
|
|
16
|
+
export declare const DSL_Dataset: React.FC<IDatasetProps>;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useContext, useEffect } from "react";
|
|
3
|
+
import { useApi } from "../..";
|
|
4
|
+
import { ControlContext, DatasetRegistryContext } from "../DashboardPage/Page";
|
|
5
|
+
import { Producer } from "./Producer";
|
|
6
|
+
import React from "react";
|
|
7
|
+
import { Filter, Transform, useAllDatasets } from "../../dsl";
|
|
8
|
+
import alasql from "alasql";
|
|
9
|
+
import { DataProviderContext, getProviderFromType } from "./Provider";
|
|
10
|
+
import { Join } from "./Join";
|
|
11
|
+
import { from } from "arquero";
|
|
12
|
+
export const DSL_Dataset = ({ children, id, provider: provider_input, type: providerType = 'file', url: providerUrl, resource, pageSize, meta }) => {
|
|
13
|
+
const getTransformerFn = (component) => {
|
|
14
|
+
/*
|
|
15
|
+
* Génére une fonction transformer soit
|
|
16
|
+
* - A partir d'un composant Transform (string ou fonction js)
|
|
17
|
+
* - A partir d'un composant Join
|
|
18
|
+
*/
|
|
19
|
+
if (typeof component.type != 'string' && component.type == Transform) {
|
|
20
|
+
const children = component.props.children;
|
|
21
|
+
if (typeof children === "string") {
|
|
22
|
+
// Transformation via une requête SQL
|
|
23
|
+
return (data) => data && alasql(children, [data]);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
return (data) => data && children(data);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
else if (typeof component.type != 'string' && component.type === Join) {
|
|
30
|
+
const props = component.props;
|
|
31
|
+
const funct = (data) => {
|
|
32
|
+
const join_type = props.joinType || 'inner';
|
|
33
|
+
const aq_join_option = {
|
|
34
|
+
left: { left: true, right: false },
|
|
35
|
+
right: { left: false, right: true },
|
|
36
|
+
full: { left: true, right: true },
|
|
37
|
+
inner: { left: false, right: false },
|
|
38
|
+
}[join_type] ?? { left: false, right: false };
|
|
39
|
+
const otherData = allDatasets?.find((d) => d.id === props.dataset)?.data;
|
|
40
|
+
if (!otherData)
|
|
41
|
+
return undefined; // ou [] ou data selon la logique souhaitée
|
|
42
|
+
return from(data).join(from(otherData), props.joinKey, undefined, aq_join_option).objects();
|
|
43
|
+
};
|
|
44
|
+
return funct;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
throw new Error(`Unknown transformer component: ${component.type}`);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const datasetRegistryContext = useContext(DatasetRegistryContext);
|
|
51
|
+
const allDatasets = useAllDatasets();
|
|
52
|
+
const someFetching = !!allDatasets?.some(d => d.isFetching);
|
|
53
|
+
const controlContext = useContext(ControlContext);
|
|
54
|
+
const controls = controlContext?.values;
|
|
55
|
+
const providerContext = useContext(DataProviderContext);
|
|
56
|
+
const provider = (providerUrl && getProviderFromType(providerType)(providerUrl)) || providerContext || provider_input;
|
|
57
|
+
if (provider === undefined) {
|
|
58
|
+
throw new Error("Error : No dataProvider, please use one of : <Provider> parent, providerUrl/providerType properties or provider property");
|
|
59
|
+
}
|
|
60
|
+
/* Récupérer les props des filtres depuis les composants enfant Filter */
|
|
61
|
+
const filters = [];
|
|
62
|
+
React.Children.toArray(children)
|
|
63
|
+
.filter((c) => React.isValidElement(c))
|
|
64
|
+
.filter((c) => typeof c.type != 'string' && c.type.name == Filter.name).forEach((c) => {
|
|
65
|
+
const value = String(c.props.children).trim() || controls?.[c.props.control];
|
|
66
|
+
filters.push({
|
|
67
|
+
operator: c.props.operator || 'eq',
|
|
68
|
+
value: value,
|
|
69
|
+
field: c.props.field
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
const { data, isFetching, isError } = useApi({ dataProvider: provider, resource: resource, filters: filters, pagination: { pageSize: pageSize }, meta: meta });
|
|
73
|
+
const transformers = [];
|
|
74
|
+
/* Récuperer les fonctions transformers */
|
|
75
|
+
React.Children.toArray(children)
|
|
76
|
+
.filter((c) => React.isValidElement(c))
|
|
77
|
+
.filter((c) => typeof c.type != 'string' && (c.type.name == Transform.name || c.type.name == Join.name)).forEach((c) => {
|
|
78
|
+
transformers.push(getTransformerFn(c));
|
|
79
|
+
});
|
|
80
|
+
const producers = [];
|
|
81
|
+
React.Children.toArray(children)
|
|
82
|
+
.filter((c) => React.isValidElement(c))
|
|
83
|
+
.filter((c) => typeof c.type != 'string' && c.type.name == Producer.name).forEach((c) => {
|
|
84
|
+
producers.push({ nom: c.props.children, url: c.props.url });
|
|
85
|
+
});
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
const finalData = data?.data && transformers.reduce((datat, fn) => fn(datat), data.data);
|
|
88
|
+
if (datasetRegistryContext) {
|
|
89
|
+
datasetRegistryContext({ id: id, resource: resource, data: finalData, isFetching: isFetching, isError: isError, producers: producers });
|
|
90
|
+
//Ajouter une info pour distinguer les erreurs du fourniseurs et celles des transformers ?
|
|
91
|
+
}
|
|
92
|
+
}, [resource, data, isFetching, someFetching, children]);
|
|
93
|
+
return (_jsx(_Fragment, { children: children }));
|
|
94
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { CrudOperators } from "../../data_providers/types";
|
|
2
|
+
interface IFilterProps {
|
|
3
|
+
field: string;
|
|
4
|
+
children?: string;
|
|
5
|
+
control?: string;
|
|
6
|
+
operator?: Exclude<CrudOperators, "or" | "and">;
|
|
7
|
+
}
|
|
8
|
+
export declare const DSL_Filter: React.FC<IFilterProps>;
|
|
9
|
+
export {};
|