@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.
Files changed (128) hide show
  1. package/README.MD +192 -0
  2. package/dist/components/Attributions/Attribution.test.d.ts +1 -0
  3. package/dist/components/Attributions/Attribution.test.js +19 -0
  4. package/dist/components/Attributions/Attributions.d.ts +17 -0
  5. package/dist/components/Attributions/Attributions.js +30 -0
  6. package/dist/components/Charts/ChartEcharts.d.ts +7 -0
  7. package/dist/components/Charts/ChartEcharts.js +35 -0
  8. package/dist/components/Charts/Pie.d.ts +10 -0
  9. package/dist/components/Charts/Pie.js +35 -0
  10. package/dist/components/Charts/YearSerie.d.ts +16 -0
  11. package/dist/components/Charts/YearSerie.js +70 -0
  12. package/dist/components/Control/Control.d.ts +21 -0
  13. package/dist/components/Control/Control.js +84 -0
  14. package/dist/components/Control/Radio.d.ts +19 -0
  15. package/dist/components/Control/Radio.js +27 -0
  16. package/dist/components/Control/Select.d.ts +15 -0
  17. package/dist/components/Control/Select.js +25 -0
  18. package/dist/components/DashboardChart/DashboardChart.d.ts +11 -0
  19. package/dist/components/DashboardChart/DashboardChart.js +42 -0
  20. package/dist/components/DashboardElement/DashboardElement.d.ts +21 -0
  21. package/dist/components/DashboardElement/DashboardElement.js +108 -0
  22. package/dist/components/DashboardElement/hooks.d.ts +28 -0
  23. package/dist/components/DashboardElement/hooks.js +29 -0
  24. package/dist/components/DashboardPage/Block.d.ts +15 -0
  25. package/dist/components/DashboardPage/Block.js +40 -0
  26. package/dist/components/DashboardPage/DashboardPage.test.d.ts +1 -0
  27. package/dist/components/DashboardPage/DashboardPage.test.js +40 -0
  28. package/dist/components/DashboardPage/Page.d.ts +42 -0
  29. package/dist/components/DashboardPage/Page.js +80 -0
  30. package/dist/components/Dataset/DataPreview.d.ts +12 -0
  31. package/dist/components/Dataset/DataPreview.js +21 -0
  32. package/dist/components/Dataset/Dataset.d.ts +17 -0
  33. package/dist/components/Dataset/Dataset.js +94 -0
  34. package/dist/components/Dataset/Filter.d.ts +9 -0
  35. package/dist/components/Dataset/Filter.js +7 -0
  36. package/dist/components/Dataset/Join.d.ts +8 -0
  37. package/dist/components/Dataset/Join.js +7 -0
  38. package/dist/components/Dataset/Producer.d.ts +18 -0
  39. package/dist/components/Dataset/Producer.js +27 -0
  40. package/dist/components/Dataset/Provider.d.ts +21 -0
  41. package/dist/components/Dataset/Provider.js +22 -0
  42. package/dist/components/Dataset/Transform.d.ts +6 -0
  43. package/dist/components/Dataset/Transform.js +7 -0
  44. package/dist/components/Dataset/hooks.d.ts +24 -0
  45. package/dist/components/Dataset/hooks.js +19 -0
  46. package/dist/components/Debug/Debug.d.ts +1 -0
  47. package/dist/components/Debug/Debug.js +24 -0
  48. package/dist/components/FlipCard/FlipCard.d.ts +12 -0
  49. package/dist/components/FlipCard/FlipCard.js +38 -0
  50. package/dist/components/FlipCard/FlipCard.test.d.ts +1 -0
  51. package/dist/components/FlipCard/FlipCard.test.js +36 -0
  52. package/dist/components/KeyFigure/KeyFigure.d.ts +18 -0
  53. package/dist/components/KeyFigure/KeyFigure.js +13 -0
  54. package/dist/components/Layout/DashboardApp.d.ts +18 -0
  55. package/dist/components/Layout/DashboardApp.js +46 -0
  56. package/dist/components/Layout/Error.d.ts +2 -0
  57. package/dist/components/Layout/Error.js +6 -0
  58. package/dist/components/Layout/Footer.d.ts +6 -0
  59. package/dist/components/Layout/Footer.js +47 -0
  60. package/dist/components/Layout/Sider.d.ts +9 -0
  61. package/dist/components/Layout/Sider.js +48 -0
  62. package/dist/components/LoadingContainer/LoadingContainer.d.ts +17 -0
  63. package/dist/components/LoadingContainer/LoadingContainer.js +33 -0
  64. package/dist/components/MapLegend/MapLegend.d.ts +12 -0
  65. package/dist/components/MapLegend/MapLegend.js +19 -0
  66. package/dist/components/NextPrevSelect/NextPrevSelect.d.ts +17 -0
  67. package/dist/components/NextPrevSelect/NextPrevSelect.js +49 -0
  68. package/dist/components/Palette/Palette.d.ts +18 -0
  69. package/dist/components/Palette/Palette.js +29 -0
  70. package/dist/data_providers/datafair/datafair.test.d.ts +1 -0
  71. package/dist/data_providers/datafair/datafair.test.js +39 -0
  72. package/dist/data_providers/datafair/index.d.ts +15 -0
  73. package/dist/data_providers/datafair/index.js +33 -0
  74. package/dist/data_providers/datafair/utils/axios.d.ts +2 -0
  75. package/dist/data_providers/datafair/utils/axios.js +13 -0
  76. package/dist/data_providers/datafair/utils/generateFilter.d.ts +1 -0
  77. package/dist/data_providers/datafair/utils/generateFilter.js +40 -0
  78. package/dist/data_providers/datafair/utils/generateSort.d.ts +1 -0
  79. package/dist/data_providers/datafair/utils/generateSort.js +19 -0
  80. package/dist/data_providers/datafair/utils/index.d.ts +4 -0
  81. package/dist/data_providers/datafair/utils/index.js +4 -0
  82. package/dist/data_providers/datafair/utils/mapOperator.d.ts +1 -0
  83. package/dist/data_providers/datafair/utils/mapOperator.js +13 -0
  84. package/dist/data_providers/file/index.d.ts +6 -0
  85. package/dist/data_providers/file/index.js +25 -0
  86. package/dist/data_providers/file/utils/axios.d.ts +2 -0
  87. package/dist/data_providers/file/utils/axios.js +26 -0
  88. package/dist/data_providers/types.d.ts +52 -0
  89. package/dist/data_providers/types.js +2 -0
  90. package/dist/data_providers/wfs/index.d.ts +3 -0
  91. package/dist/data_providers/wfs/index.js +43 -0
  92. package/dist/data_providers/wfs/utils/axios.d.ts +2 -0
  93. package/dist/data_providers/wfs/utils/axios.js +26 -0
  94. package/dist/data_providers/wfs/utils/generateFilter.d.ts +4 -0
  95. package/dist/data_providers/wfs/utils/generateFilter.js +45 -0
  96. package/dist/data_providers/wfs/utils/generateSort.d.ts +1 -0
  97. package/dist/data_providers/wfs/utils/generateSort.js +20 -0
  98. package/dist/data_providers/wfs/utils/index.d.ts +4 -0
  99. package/dist/data_providers/wfs/utils/index.js +4 -0
  100. package/dist/data_providers/wfs/utils/mapOperator.d.ts +1 -0
  101. package/dist/data_providers/wfs/utils/mapOperator.js +36 -0
  102. package/dist/data_providers/wfs/wfs.test.d.ts +1 -0
  103. package/dist/data_providers/wfs/wfs.test.js +60 -0
  104. package/dist/dsl/index.d.ts +19 -0
  105. package/dist/dsl/index.js +19 -0
  106. package/dist/index.d.ts +29 -0
  107. package/dist/index.js +33 -0
  108. package/dist/types.d.ts +15 -0
  109. package/dist/types.js +1 -0
  110. package/dist/utils/baserecordtogeojsonpoint.d.ts +13 -0
  111. package/dist/utils/baserecordtogeojsonpoint.js +17 -0
  112. package/dist/utils/cardStyles.d.ts +2 -0
  113. package/dist/utils/cardStyles.js +12 -0
  114. package/dist/utils/deepmerge.d.ts +2 -0
  115. package/dist/utils/deepmerge.js +24 -0
  116. package/dist/utils/route_utils.d.ts +6 -0
  117. package/dist/utils/route_utils.js +14 -0
  118. package/dist/utils/useApi.d.ts +12 -0
  119. package/dist/utils/useApi.js +14 -0
  120. package/dist/utils/useMapControl.d.ts +8 -0
  121. package/dist/utils/useMapControl.js +24 -0
  122. package/dist/utils/useSearchParamsState.d.ts +11 -0
  123. package/dist/utils/useSearchParamsState.js +18 -0
  124. package/dist/utils/usechartexports.d.ts +17 -0
  125. package/dist/utils/usechartexports.js +39 -0
  126. package/dist/utils/usecharthightlight.d.ts +25 -0
  127. package/dist/utils/usecharthightlight.js +44 -0
  128. package/package.json +98 -0
@@ -0,0 +1,60 @@
1
+ //import {render, screen} from '@testing-library/react'
2
+ import '@testing-library/jest-dom';
3
+ //import userEvent from '@testing-library/user-event'
4
+ import { QueryClient } from '@tanstack/react-query';
5
+ import { /*useApi,*/ WfsProvider } from '../..';
6
+ const test_provider_url = "https://www.geo2france.fr/geoserver/ows";
7
+ const test_page_size = 3;
8
+ const test_filter_field = "siren_epci";
9
+ const test_filter_value = "200067999";
10
+ const resource = "odema:destination_dma_epci";
11
+ const filters = [
12
+ {
13
+ field: test_filter_field,
14
+ operator: "eq",
15
+ value: test_filter_value,
16
+ },
17
+ ];
18
+ const pagination = {
19
+ mode: "server",
20
+ pageSize: test_page_size,
21
+ };
22
+ const sorters = [{ field: "fid", order: "asc" }];
23
+ const queryClient = new QueryClient();
24
+ //TODO tester dans un composant
25
+ /*const component_using_api:React.FC = () => {
26
+ const provider = WfsProvider("https://www.geo2france.fr/geoserver/ows")
27
+ const data = useApi({
28
+ dataProvider:provider,
29
+ resource:"odema:destination_dma_epci ",
30
+ pagination:{
31
+ mode:"off"
32
+ },
33
+ filters:[
34
+ {
35
+ field:"siren_epci",
36
+ operator:"eq",
37
+ value:"200067999"
38
+ }]
39
+ })
40
+
41
+ return <></>
42
+ }*/
43
+ describe("WFS Provider", () => {
44
+ test("basic filter & pagination", async () => {
45
+ const provider = WfsProvider(test_provider_url);
46
+ const queryKey = [provider.getApiUrl, resource, filters, pagination, sorters, undefined];
47
+ const result = await queryClient.fetchQuery({
48
+ queryKey: queryKey,
49
+ queryFn: () => provider.getList({
50
+ resource: resource,
51
+ filters: filters,
52
+ pagination: pagination,
53
+ sorters: sorters
54
+ }),
55
+ });
56
+ expect(result).toHaveProperty('data');
57
+ expect(result.data).toHaveLength(test_page_size);
58
+ expect(result.data[0][test_filter_field]).toEqual(test_filter_value);
59
+ });
60
+ });
@@ -0,0 +1,19 @@
1
+ import { DSL_DashboardPage as Dashboard } from "../components/DashboardPage/Page";
2
+ import { DSL_Dataset as Dataset } from "../components/Dataset/Dataset";
3
+ import { DSL_DataPreview as DataPreview } from "../components/Dataset/DataPreview";
4
+ import { DSL_Transform as Transform } from "../components/Dataset/Transform";
5
+ import { DSL_Filter as Filter } from "../components/Dataset/Filter";
6
+ import { Provider } from "../components/Dataset/Provider";
7
+ import { useAllDatasets, useDataset, useDatasets } from "../components/Dataset/hooks";
8
+ import { ChartPie } from "../components/Charts/Pie";
9
+ import { ChartYearSerie } from "../components/Charts/YearSerie";
10
+ import { Producer } from "../components/Dataset/Producer";
11
+ import { DSL_Control as Control, useAllControls, useControl } from "../components/Control/Control";
12
+ import { Radio } from "../components/Control/Radio";
13
+ import { Select } from "../components/Control/Select";
14
+ import { Input } from "antd";
15
+ import { Palette, usePalette, PalettePreview } from "../components/Palette/Palette";
16
+ import { Debug } from "../components/Debug/Debug";
17
+ import { Join } from "../components/Dataset/Join";
18
+ import { ChartEcharts } from "../components/Charts/ChartEcharts";
19
+ export { Dashboard, Dataset, Provider, Transform, Join, Filter, DataPreview, ChartEcharts, ChartPie, ChartYearSerie, useDataset, useDatasets, useAllDatasets, Producer, Control, useControl, useAllControls, Radio, Select, Input, Palette, usePalette, PalettePreview, Debug, };
@@ -0,0 +1,19 @@
1
+ import { DSL_DashboardPage as Dashboard } from "../components/DashboardPage/Page";
2
+ import { DSL_Dataset as Dataset } from "../components/Dataset/Dataset";
3
+ import { DSL_DataPreview as DataPreview } from "../components/Dataset/DataPreview";
4
+ import { DSL_Transform as Transform } from "../components/Dataset/Transform";
5
+ import { DSL_Filter as Filter } from "../components/Dataset/Filter";
6
+ import { Provider } from "../components/Dataset/Provider";
7
+ import { useAllDatasets, useDataset, useDatasets } from "../components/Dataset/hooks";
8
+ import { ChartPie } from "../components/Charts/Pie";
9
+ import { ChartYearSerie } from "../components/Charts/YearSerie";
10
+ import { Producer } from "../components/Dataset/Producer";
11
+ import { DSL_Control as Control, useAllControls, useControl } from "../components/Control/Control";
12
+ import { Radio } from "../components/Control/Radio";
13
+ import { Select } from "../components/Control/Select";
14
+ import { Input } from "antd";
15
+ import { Palette, usePalette, PalettePreview } from "../components/Palette/Palette";
16
+ import { Debug } from "../components/Debug/Debug";
17
+ import { Join } from "../components/Dataset/Join";
18
+ import { ChartEcharts } from "../components/Charts/ChartEcharts";
19
+ export { Dashboard, Dataset, Provider, Transform, Join, Filter, DataPreview, ChartEcharts, ChartPie, ChartYearSerie, useDataset, useDatasets, useAllDatasets, Producer, Control, useControl, useAllControls, Radio, Select, Input, Palette, usePalette, PalettePreview, Debug, };
@@ -0,0 +1,29 @@
1
+ export { useChartEvents, useChartActionHightlight } from "./utils/usecharthightlight";
2
+ export { useSearchParamsState } from "./utils/useSearchParamsState";
3
+ export { useChartExport } from "./utils/usechartexports";
4
+ export { useApi } from "./utils/useApi";
5
+ export { useChartData, useDashboardElement, useNoData } from "./components/DashboardElement/hooks";
6
+ export { useMapControl } from "./utils/useMapControl";
7
+ export { BaseRecordToGeojsonPoint } from "./utils/baserecordtogeojsonpoint";
8
+ export { cardStyles } from "./utils/cardStyles";
9
+ import KeyFigure from "./components/KeyFigure/KeyFigure";
10
+ import LoadingContainer from "./components/LoadingContainer/LoadingContainer";
11
+ import FlipCard from "./components/FlipCard/FlipCard";
12
+ import Attribution from "./components/Attributions/Attributions";
13
+ import NextPrevSelect from "./components/NextPrevSelect/NextPrevSelect";
14
+ import Control from "./components/Control/Control";
15
+ import DashboardChart from "./components/DashboardChart/DashboardChart";
16
+ import MapLegend from "./components/MapLegend/MapLegend";
17
+ import DashboardApp from "./components/Layout/DashboardApp";
18
+ import DashboardSider from "./components/Layout/Sider";
19
+ import DashboardPage from "./components/DashboardPage/Page";
20
+ import DashboardElement from "./components/DashboardElement/DashboardElement";
21
+ export { KeyFigure, DashboardElement, LoadingContainer, FlipCard, Attribution, NextPrevSelect, Control, DashboardChart, DashboardPage, MapLegend, DashboardSider, DashboardApp, };
22
+ import { dataProvider as WfsProvider } from "./data_providers/wfs";
23
+ import { dataProvider as DatafairProvider } from "./data_providers/datafair";
24
+ import { dataProvider as FileProvider } from "./data_providers/file";
25
+ export { WfsProvider, DatafairProvider, FileProvider };
26
+ export type { SimpleRecord, Partner, RouteConfig } from "./types";
27
+ export type { LegendItem } from "./components/MapLegend/MapLegend";
28
+ import * as DSL from './dsl';
29
+ export { DSL };
package/dist/index.js ADDED
@@ -0,0 +1,33 @@
1
+ // Hooks
2
+ export { useChartEvents, useChartActionHightlight } from "./utils/usecharthightlight";
3
+ export { useSearchParamsState } from "./utils/useSearchParamsState";
4
+ export { useChartExport } from "./utils/usechartexports";
5
+ export { useApi } from "./utils/useApi";
6
+ export { useChartData, useDashboardElement, useNoData } from "./components/DashboardElement/hooks";
7
+ export { useMapControl } from "./utils/useMapControl";
8
+ // Helpers
9
+ export { BaseRecordToGeojsonPoint } from "./utils/baserecordtogeojsonpoint";
10
+ export { cardStyles } from "./utils/cardStyles";
11
+ // Components
12
+ import KeyFigure from "./components/KeyFigure/KeyFigure";
13
+ import LoadingContainer from "./components/LoadingContainer/LoadingContainer";
14
+ import FlipCard from "./components/FlipCard/FlipCard";
15
+ import Attribution from "./components/Attributions/Attributions";
16
+ import NextPrevSelect from "./components/NextPrevSelect/NextPrevSelect";
17
+ import Control from "./components/Control/Control";
18
+ import DashboardChart from "./components/DashboardChart/DashboardChart";
19
+ import MapLegend from "./components/MapLegend/MapLegend";
20
+ // Layout
21
+ import DashboardApp from "./components/Layout/DashboardApp";
22
+ import DashboardSider from "./components/Layout/Sider";
23
+ import DashboardPage from "./components/DashboardPage/Page";
24
+ import DashboardElement from "./components/DashboardElement/DashboardElement";
25
+ export { KeyFigure, DashboardElement, LoadingContainer, FlipCard, Attribution, NextPrevSelect, Control, DashboardChart, DashboardPage, MapLegend, DashboardSider, DashboardApp, };
26
+ // DataProviders
27
+ import { dataProvider as WfsProvider } from "./data_providers/wfs";
28
+ import { dataProvider as DatafairProvider } from "./data_providers/datafair";
29
+ import { dataProvider as FileProvider } from "./data_providers/file";
30
+ export { WfsProvider, DatafairProvider, FileProvider };
31
+ // DSL
32
+ import * as DSL from './dsl';
33
+ export { DSL };
@@ -0,0 +1,15 @@
1
+ export type SimpleRecord = Record<string, any>;
2
+ export type License = ('CC' | 'BY' | 'SA' | 'NC' | 'ZERO' | 'PD' | 'NC');
3
+ export type RouteConfig = {
4
+ path: string;
5
+ label?: string;
6
+ icon?: React.ReactNode;
7
+ element: React.ReactNode;
8
+ children?: RouteConfig[];
9
+ hidden?: boolean;
10
+ };
11
+ export type Partner = {
12
+ logo: string;
13
+ name: string;
14
+ url?: string;
15
+ };
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
1
+ import { FeatureCollection } from "geojson";
2
+ export interface IBaseRecordToGeojsonPoint {
3
+ data: {
4
+ [key: string]: any;
5
+ }[];
6
+ x: string;
7
+ y: string;
8
+ crs_name?: string;
9
+ }
10
+ export interface FeatureCollection_crs extends FeatureCollection {
11
+ crs?: any;
12
+ }
13
+ export declare const BaseRecordToGeojsonPoint: ({ data, x, y, crs_name }: IBaseRecordToGeojsonPoint) => FeatureCollection_crs;
@@ -0,0 +1,17 @@
1
+ ;
2
+ export const BaseRecordToGeojsonPoint = ({ data, x, y, crs_name }) => {
3
+ //Tester maplibre avec CRS != 4326
4
+ const features = data.map((e) => ({
5
+ type: "Feature",
6
+ properties: { ...e },
7
+ geometry: {
8
+ type: "Point",
9
+ coordinates: [e[y], e[x]]
10
+ }
11
+ }));
12
+ const geojson = { "type": "FeatureCollection", features: features };
13
+ if (crs_name) {
14
+ geojson.crs = { type: "name", properties: { "name": crs_name } }; //no longer supported in geoJSON ? https://github.com/DefinitelyTyped/DefinitelyTyped/issues/21794
15
+ }
16
+ return geojson;
17
+ };
@@ -0,0 +1,2 @@
1
+ import { CardProps } from "antd";
2
+ export declare const cardStyles: CardProps["styles"];
@@ -0,0 +1,12 @@
1
+ export const cardStyles = {
2
+ body: {
3
+ padding: "0px",
4
+ height: "100%"
5
+ },
6
+ header: {
7
+ padding: "5px",
8
+ paddingLeft: "15px",
9
+ fontSize: 14,
10
+ minHeight: 35,
11
+ },
12
+ };
@@ -0,0 +1,2 @@
1
+ declare function deepMerge<T extends object>(target: T, ...sources: Array<Partial<T>>): T;
2
+ export default deepMerge;
@@ -0,0 +1,24 @@
1
+ // From https://www.geeksforgeeks.org/how-to-deep-merge-two-objects-in-typescript/
2
+ function isObject(item) {
3
+ return item !== null && typeof item === 'object' && !Array.isArray(item);
4
+ }
5
+ function deepMerge(target, ...sources) {
6
+ if (!sources.length)
7
+ return target;
8
+ const source = sources.shift();
9
+ if (isObject(target) && isObject(source)) {
10
+ for (const key in source) {
11
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
12
+ const sourceValue = source[key];
13
+ if (isObject(sourceValue) && isObject(target[key])) {
14
+ target[key] = deepMerge(target[key], sourceValue);
15
+ }
16
+ else {
17
+ target[key] = sourceValue;
18
+ }
19
+ }
20
+ }
21
+ }
22
+ return deepMerge(target, ...sources);
23
+ }
24
+ export default deepMerge;
@@ -0,0 +1,6 @@
1
+ import { RouteConfig } from "../types";
2
+ import type { MenuProps } from 'antd';
3
+ type MenuItem = Required<MenuProps>['items'][number];
4
+ export declare const generateRoutes: (routes: RouteConfig[]) => import("react/jsx-runtime").JSX.Element[];
5
+ export declare const generateMenuItems: (routes: RouteConfig[], parentPath?: string) => MenuItem[];
6
+ export {};
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ //Retourne les routes et le menu
3
+ import { NavLink, Route } from "react-router-dom";
4
+ export const generateRoutes = (routes) => routes.map((route) => (_jsx(Route, { path: route.path, element: !route.children && route.element, children: route.children && generateRoutes(route.children) }, route.path)));
5
+ export const generateMenuItems = (routes, parentPath = "") => routes.filter((route) => route.hidden != true).map((route) => {
6
+ const fullPath = `${parentPath}/${route.path}`;
7
+ const menuItem = {
8
+ key: fullPath,
9
+ label: route.children ? _jsxs(_Fragment, { children: [" ", route.label || route.path] }) : _jsx(NavLink, { to: fullPath, children: route.label || route.path }),
10
+ icon: route.icon,
11
+ ...(route.children && { children: generateMenuItems(route.children, fullPath) }), // Ajout conditionnel des enfants
12
+ };
13
+ return menuItem;
14
+ });
@@ -0,0 +1,12 @@
1
+ import { CrudFilters, CrudSorting, DataProvider, Pagination } from "../data_providers/types";
2
+ interface useApiProps {
3
+ dataProvider: DataProvider;
4
+ resource: string;
5
+ filters?: CrudFilters;
6
+ pagination?: Pagination;
7
+ sorters?: CrudSorting;
8
+ meta?: any;
9
+ enabled?: boolean;
10
+ }
11
+ export declare const useApi: ({ dataProvider, resource, filters, pagination, sorters, meta, enabled }: useApiProps) => import("@tanstack/react-query").UseQueryResult<import("../data_providers/types").GetListResponse, Error>;
12
+ export {};
@@ -0,0 +1,14 @@
1
+ import { useQuery } from "@tanstack/react-query";
2
+ export const useApi = ({ dataProvider, resource, filters, pagination, sorters, meta, enabled = true }) => (useQuery({
3
+ queryKey: [dataProvider.getApiUrl, resource, filters, pagination, sorters, meta],
4
+ queryFn: () => dataProvider.getList({
5
+ resource: resource,
6
+ filters: filters,
7
+ pagination: pagination,
8
+ sorters: sorters,
9
+ meta: meta
10
+ }),
11
+ enabled: enabled,
12
+ placeholderData: (prev) => prev,
13
+ staleTime: 5 * 60 * 1e3, //Default staletime 5min
14
+ }));
@@ -0,0 +1,8 @@
1
+ import { ControlPosition } from 'react-map-gl/maplibre';
2
+ interface useMapControlProps {
3
+ mapRef: React.MutableRefObject<any>;
4
+ legendElement: React.ReactElement;
5
+ position?: ControlPosition;
6
+ }
7
+ export declare const useMapControl: ({ mapRef, legendElement, position }: useMapControlProps) => void;
8
+ export {};
@@ -0,0 +1,24 @@
1
+ // Ajouter un control (element HTML) sur une carte
2
+ import { useEffect } from "react";
3
+ import { createRoot } from 'react-dom/client';
4
+ export const useMapControl = ({ mapRef, legendElement, position = 'top-right' }) => {
5
+ useEffect(() => {
6
+ if (mapRef?.current) {
7
+ const controlDiv = document.createElement('div');
8
+ const root = createRoot(controlDiv);
9
+ const customControl = {
10
+ onAdd: () => {
11
+ root.render(legendElement);
12
+ return controlDiv;
13
+ },
14
+ onRemove: () => {
15
+ controlDiv.parentNode?.removeChild(controlDiv);
16
+ }
17
+ };
18
+ mapRef?.current?.getMap().addControl(customControl, position);
19
+ return () => {
20
+ customControl.onRemove();
21
+ };
22
+ }
23
+ }, [mapRef?.current]);
24
+ };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * See https://blog.logrocket.com/use-state-url-persist-state-usesearchparams/
3
+ *
4
+ * @param searchParamName
5
+ * @param defaultValue
6
+ * @returns searchParamsState & setSearchParamsState
7
+ */
8
+ export declare function useSearchParamsState(searchParamName: string, defaultValue: string): readonly [
9
+ searchParamsState: string,
10
+ setSearchParamsState: (newState: string) => void
11
+ ];
@@ -0,0 +1,18 @@
1
+ import { useSearchParams } from "react-router-dom";
2
+ /**
3
+ * See https://blog.logrocket.com/use-state-url-persist-state-usesearchparams/
4
+ *
5
+ * @param searchParamName
6
+ * @param defaultValue
7
+ * @returns searchParamsState & setSearchParamsState
8
+ */
9
+ export function useSearchParamsState(searchParamName, defaultValue) {
10
+ const [searchParams, setSearchParams] = useSearchParams();
11
+ const acquiredSearchParam = searchParams.get(searchParamName);
12
+ const searchParamsState = acquiredSearchParam ?? defaultValue;
13
+ const setSearchParamsState = (newState) => {
14
+ const next = Object.assign({}, [...searchParams.entries()].reduce((o, [key, value]) => ({ ...o, [key]: value }), {}), { [searchParamName]: newState });
15
+ setSearchParams(next);
16
+ };
17
+ return [searchParamsState, setSearchParamsState];
18
+ }
@@ -0,0 +1,17 @@
1
+ import { MutableRefObject } from "react";
2
+ export interface useChartExportProps {
3
+ chartRef?: MutableRefObject<any>;
4
+ }
5
+ /**
6
+ * Hook personnalisé pour exporter une image à partir d'une instance ECharts.
7
+ * @param {Object} props - Les propriétés du hook.
8
+ * @param {MutableRefObject<any>} props.chartRef - La référence de l'instance ECharts.
9
+ * @returns {Object} - Un objet contenant l'URL de l'image générée et la fonction pour déclencher l'export.
10
+ *
11
+ * @exemple
12
+ * const {img64, exportImage} = useChartExport({chartRef:chartRef})
13
+ */
14
+ export declare const useChartExport: ({ chartRef }: useChartExportProps) => {
15
+ img64: undefined;
16
+ exportImage: () => void;
17
+ };
@@ -0,0 +1,39 @@
1
+ import { useEffect, useState } from "react";
2
+ /**
3
+ * Fonction pour obtenir l'export (img64) d'un echarts ou d'un maplibre
4
+ * @param ref - Référence de l'objet (echarts ou maplibre)
5
+ * @returns - L'image en base64
6
+ */
7
+ const getDataURL = (ref) => {
8
+ if ('getCanvas' in ref.current) { //maplibre
9
+ return ref.current.getCanvas().toDataURL();
10
+ }
11
+ else if ('getEchartsInstance' in ref.current) { //Echart
12
+ return ref.current.getEchartsInstance().getDataURL({ backgroundColor: '#fff' });
13
+ }
14
+ };
15
+ /**
16
+ * Hook personnalisé pour exporter une image à partir d'une instance ECharts.
17
+ * @param {Object} props - Les propriétés du hook.
18
+ * @param {MutableRefObject<any>} props.chartRef - La référence de l'instance ECharts.
19
+ * @returns {Object} - Un objet contenant l'URL de l'image générée et la fonction pour déclencher l'export.
20
+ *
21
+ * @exemple
22
+ * const {img64, exportImage} = useChartExport({chartRef:chartRef})
23
+ */
24
+ export const useChartExport = ({ chartRef }) => {
25
+ const [img64, setImage64] = useState();
26
+ const [exportRequested, setExportRequested] = useState(false); // Suivre l'état de l'export
27
+ useEffect(() => {
28
+ if (chartRef?.current && exportRequested) {
29
+ const dataURL = getDataURL(chartRef);
30
+ setImage64(dataURL);
31
+ setExportRequested(false);
32
+ }
33
+ }, [chartRef, exportRequested]);
34
+ const exportImage = () => {
35
+ console.log('called');
36
+ setExportRequested(true);
37
+ };
38
+ return { img64, exportImage };
39
+ };
@@ -0,0 +1,25 @@
1
+ import { MutableRefObject } from "react";
2
+ export interface useChartEventsProps {
3
+ /** La référence du graphique */
4
+ chartRef: MutableRefObject<any>;
5
+ /** Fonction appelée lors du click Généralement c'est un setStat() */
6
+ onClick?: Function;
7
+ /** Fonction appelée lors du mouse-over ET mouse-out (avec paramètre null pour le mouse-out). Généralement c'est un setStat() */
8
+ onFocus?: (e: any) => void;
9
+ }
10
+ /** Hook permettant de récupérer les évenements click et mouseover/mouseout d'un graphique ECharts
11
+ * @category Hook
12
+ */
13
+ export declare const useChartEvents: ({ chartRef, onClick, onFocus }: useChartEventsProps) => void;
14
+ export interface useChartActionProps {
15
+ /** La référence du graphique */
16
+ chartRef: MutableRefObject<any>;
17
+ /** La cible à focus (cf. https://echarts.apache.org/en/api.html#action.highlight). En general {name:value} pour les donut et sankey, {seriesName} pour les bar et line */
18
+ target: Partial<{
19
+ [key in 'seriesIndex' | 'seriesId' | 'seriesName' | 'name' | 'dataIndex']: any;
20
+ }>;
21
+ }
22
+ /** Hook permettant de highlight un élément d'un graphique ECharts
23
+ * @category Hook
24
+ */
25
+ export declare const useChartActionHightlight: ({ chartRef, target }: useChartActionProps) => void;
@@ -0,0 +1,44 @@
1
+ import { useEffect } from "react";
2
+ /** Hook permettant de récupérer les évenements click et mouseover/mouseout d'un graphique ECharts
3
+ * @category Hook
4
+ */
5
+ export const useChartEvents = ({ chartRef, onClick, onFocus }) => {
6
+ useEffect(() => {
7
+ if (chartRef.current) { //Factoriser pour les différents type d'évenment ?
8
+ const mychart = chartRef.current.getEchartsInstance();
9
+ const handleMouseOver = onFocus ? (e) => onFocus(e) : undefined;
10
+ const handleMouseOut = onFocus ? () => onFocus(null) : undefined; //Retourner plutôt un '' ?
11
+ const handleClick = onClick ? (e) => onClick(e) : undefined;
12
+ if (handleMouseOver) {
13
+ mychart.on('mouseover', handleMouseOver);
14
+ mychart.on('mouseout', handleMouseOut);
15
+ }
16
+ if (handleClick) {
17
+ mychart.on('click', handleClick);
18
+ }
19
+ return () => {
20
+ if (onFocus) {
21
+ mychart.off('mouseover', handleMouseOver);
22
+ mychart.off('mouseout', handleMouseOut);
23
+ }
24
+ if (onClick) {
25
+ mychart.off('mouseover', handleClick);
26
+ }
27
+ };
28
+ }
29
+ }, [chartRef, onClick, onFocus]);
30
+ };
31
+ /** Hook permettant de highlight un élément d'un graphique ECharts
32
+ * @category Hook
33
+ */
34
+ export const useChartActionHightlight = ({ chartRef, target }) => {
35
+ useEffect(() => {
36
+ if (chartRef.current) {
37
+ const mychart = chartRef.current.getEchartsInstance();
38
+ mychart.dispatchAction({ type: 'downplay' });
39
+ if (target.seriesIndex || target.seriesId || target.seriesName || target.name || target.dataIndex) {
40
+ mychart.dispatchAction({ type: 'highlight', ...target });
41
+ }
42
+ }
43
+ }, [chartRef, target]);
44
+ };
package/package.json ADDED
@@ -0,0 +1,98 @@
1
+ {
2
+ "name": "@geo2france/api-dashboard",
3
+ "version": "1.5.0",
4
+ "private": false,
5
+ "description": "Build dashboards with JSX/TSX",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+ssh://git@github.com/geo2france/api-dashboard.git"
11
+ },
12
+ "author": {
13
+ "name": "Jean-Baptiste Desbas",
14
+ "email": "jb@desbas.fr",
15
+ "url": "http://jb.desbas.fr"
16
+ },
17
+ "licence": "MIT",
18
+ "keywords": [
19
+ "dashboard",
20
+ "territories",
21
+ "dataviz"
22
+ ],
23
+ "files": [
24
+ "dist"
25
+ ],
26
+ "exports": {
27
+ ".": {
28
+ "import": "./dist/index.js",
29
+ "types": "./dist/index.d.ts"
30
+ },
31
+ "./dsl": {
32
+ "import": "./dist/dsl/index.js",
33
+ "types": "./dist/dsl/index.d.ts"
34
+ }
35
+ },
36
+ "typesVersions": {
37
+ "*": {
38
+ "dsl": [
39
+ "dist/dsl/index.d.ts"
40
+ ]
41
+ }
42
+ },
43
+ "scripts": {
44
+ "tsc": "tsc",
45
+ "test": "jest --watchAll"
46
+ },
47
+ "dependencies": {
48
+ "alasql": "^4.6.6",
49
+ "arquero": "^8.0.3",
50
+ "axios": "^1.7.4",
51
+ "chroma-js": "^3.1.2",
52
+ "echarts": "^5.5.1",
53
+ "echarts-for-react": "^3.0.2",
54
+ "query-string": "~7.1.3",
55
+ "react-helmet": "^6.1.0",
56
+ "react-helmet-async": "^2.0.5",
57
+ "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz"
58
+ },
59
+ "devDependencies": {
60
+ "@tanstack/react-query": "^5.51.11",
61
+ "@testing-library/dom": "^10.4.0",
62
+ "@testing-library/jest-dom": "^6.5.0",
63
+ "@testing-library/react": "^16.0.1",
64
+ "@testing-library/user-event": "^14.5.2",
65
+ "@types/chroma-js": "^3.1.1",
66
+ "@types/geojson": "^7946.0.14",
67
+ "@types/jest": "^29.5.13",
68
+ "@types/node": "^22.7.4",
69
+ "@types/react": "^18.3.10",
70
+ "@types/react-dom": "^18.3.0",
71
+ "@types/react-helmet-async": "^1.0.1",
72
+ "@types/react-icons": "^2.2.7",
73
+ "@typescript-eslint/eslint-plugin": "^7.16.1",
74
+ "@typescript-eslint/parser": "^7.16.1",
75
+ "@vitejs/plugin-react": "^4.3.1",
76
+ "antd": "^5.24.3",
77
+ "jest": "^29.7.0",
78
+ "jest-environment-jsdom": "^29.7.0",
79
+ "react": "^18.3.1",
80
+ "react-router-dom": "^6.25.1",
81
+ "ts-jest": "^29.2.5",
82
+ "ts-node": "^10.9.2",
83
+ "tsup": "^8.5.0",
84
+ "typescript": "^5.5.2",
85
+ "vite": "^5.3.4",
86
+ "vite-plugin-svgr": "^4.2.0"
87
+ },
88
+ "peerDependencies": {
89
+ "@tanstack/react-query": "^5.51.11",
90
+ "antd": "^5.18.3",
91
+ "react": "^18.3.1",
92
+ "react-dom": "^18.3.1",
93
+ "react-icons": "5.4",
94
+ "react-map-gl": "^7.1.7",
95
+ "react-router-dom": "^6.25.1",
96
+ "recharts": "^2.15.3"
97
+ }
98
+ }