@geo2france/api-dashboard 1.11.2 → 1.13.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.
@@ -1,11 +1,13 @@
1
1
  import { ReactElement } from "react";
2
2
  import { SimpleRecord } from "../../types";
3
3
  type comparwithType = "first" | "previous";
4
- interface annotation_params_type {
4
+ interface ICallbackParams {
5
5
  /** Valeur principale */
6
6
  value: number;
7
7
  /** Jeu de données utilisé */
8
8
  data: SimpleRecord[] | undefined;
9
+ /** Ligne courante (pour accéder aux autres champs) */
10
+ row: SimpleRecord | undefined;
9
11
  /** Valeur de comparaison */
10
12
  compareValue: number;
11
13
  }
@@ -33,7 +35,9 @@ interface StatisticsProps {
33
35
  /** Comparer la valeur avec la précédente ou la première du jeu de données */
34
36
  compareWith?: comparwithType;
35
37
  /** Texte d'annotation (remplace evolution si définie) */
36
- annotation?: React.ReactNode | ((param: annotation_params_type) => React.ReactNode);
38
+ annotation?: React.ReactNode | ((param: ICallbackParams) => React.ReactNode);
39
+ /** Fonction a appliquer avant rendu */
40
+ valueFormatter?: ((param: ICallbackParams) => React.ReactNode);
37
41
  }
38
42
  /**
39
43
  * Composant `Statistics` affichant une valeur d'un dataset avec son évolution.
@@ -20,19 +20,20 @@ const { Text, Paragraph } = Typography;
20
20
  * @param {StatisticsProps} props - Propriétés du composant
21
21
  * @returns {ReactElement} Carte statistique
22
22
  */
23
- export const Statistics = ({ dataset: dataset_id, dataKey, unit, evolutionSuffix, title, icon: icon_input, color, invertColor = false, help, compareWith, relativeEvolution = false, annotation }) => {
23
+ export const Statistics = ({ dataset: dataset_id, dataKey, unit, evolutionSuffix, title, icon: icon_input, color, invertColor = false, help, compareWith, relativeEvolution = false, valueFormatter = (param) => (param.value.toLocaleString()), annotation }) => {
24
24
  const icon = typeof icon_input === "string" ? _jsx(Icon, { icon: icon_input }) : icon_input;
25
25
  const dataset = useDataset(dataset_id);
26
- const value = dataset?.data?.slice(-1)[0][dataKey]; // Dernière valeur du dataset. Caster en Number ?
26
+ const row = dataset?.data?.slice(-1)[0];
27
+ const value = row?.[dataKey]; // Dernière valeur du dataset. Caster en Number ?
27
28
  const compare_value = compareWith === 'previous' ? dataset?.data?.slice(-2)[0][dataKey] : dataset?.data?.slice(0, 1)[0][dataKey]; //Première ou avant dernière
28
29
  const evolution = relativeEvolution ? 100 * ((value - compare_value) / compare_value) : value - compare_value;
29
30
  const evolution_unit = relativeEvolution ? '%' : unit;
30
31
  const evolution_is_good = invertColor ? evolution < 0 : evolution > 0;
31
32
  const tooltip = help && _jsx(Tooltip, { title: help, children: _jsx(QuestionCircleOutlined, {}) });
32
- const annotation_params = { value: value || NaN, compareValue: compare_value || NaN, data: dataset?.data || [] };
33
+ const CallbackParams = { value: value || NaN, compareValue: compare_value || NaN, data: dataset?.data || [], row: row };
33
34
  let subtitle;
34
35
  if (annotation !== undefined) {
35
- subtitle = typeof annotation === 'function' ? annotation(annotation_params) : annotation;
36
+ subtitle = typeof annotation === 'function' ? annotation(CallbackParams) : annotation;
36
37
  }
37
38
  else if (evolution) {
38
39
  subtitle = (_jsxs(Paragraph, { style: { marginBottom: "0.5rem" }, children: [_jsxs(Text, { strong: true, type: evolution_is_good ? "success" : "danger", style: { fontSize: "120%" }, children: [evolution < 0.1 ? '' : '+', evolution.toLocaleString(undefined, { maximumFractionDigits: 1 }), "\u00A0", evolution_unit] }), " ", _jsx(Text, { italic: true, type: "secondary", children: evolutionSuffix })] }));
@@ -52,7 +53,7 @@ export const Statistics = ({ dataset: dataset_id, dataKey, unit, evolutionSuffix
52
53
  fontSize: 14,
53
54
  minHeight: 35,
54
55
  },
55
- }, extra: tooltip, children: _jsxs(Flex, { vertical: true, children: [_jsxs(Flex, { justify: "space-between", align: "center", children: [_jsxs(Text, { style: { fontSize: "150%", paddingTop: 8, paddingBottom: 8, paddingLeft: 0 }, children: [value?.toLocaleString(), " ", unit] }), icon && _jsx(Avatar, { size: 32 + 8, icon: icon, style: { backgroundColor: color } })] }), typeof subtitle == 'string' ?
56
+ }, extra: tooltip, children: _jsxs(Flex, { vertical: true, children: [_jsxs(Flex, { justify: "space-between", align: "center", children: [_jsxs(Text, { style: { fontSize: "150%", paddingTop: 8, paddingBottom: 8, paddingLeft: 0 }, children: [valueFormatter(CallbackParams), " ", unit] }), icon && _jsx(Avatar, { size: 32 + 8, icon: icon, style: { backgroundColor: color } })] }), typeof subtitle == 'string' ?
56
57
  _jsx(Text, { italic: true, type: "secondary", children: subtitle })
57
58
  :
58
59
  _jsx("div", { children: subtitle })] }) }));
@@ -2,6 +2,7 @@ import { RowProps } from "antd";
2
2
  import DashboardElement from "../DashboardElement/DashboardElement";
3
3
  import React from "react";
4
4
  import { SimpleRecord } from "../../types";
5
+ import { Section } from "./Section";
5
6
  type Section = {
6
7
  key: string;
7
8
  libel?: string;
@@ -1,13 +1,15 @@
1
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";
2
+ import { Button, Col, Dropdown, Flex, Grid, Layout, Radio, Row, Tabs, theme } from "antd";
3
3
  import React, { isValidElement, useState, createContext, } from "react";
4
4
  import { Helmet } from "react-helmet-async";
5
5
  import { useSearchParamsState } from "../../utils/useSearchParamsState";
6
6
  import Control, { DSL_Control } from "../Control/Control";
7
7
  import { Dataset, Debug, Provider } from "../../dsl";
8
- import { DSL_ChartBlock } from "./Block";
9
8
  import { DEFAULT_PALETTE, Palette, PaletteContext } from "../Palette/Palette";
9
+ import { Section } from "./Section";
10
+ import { Icon } from "@iconify/react";
10
11
  const { Header } = Layout;
12
+ const { useToken } = theme;
11
13
  const getSection = (child) => React.isValidElement(child) ? child.props.section : undefined;
12
14
  const DashboardPage = ({ children: children_input, control, row_gutter = [8, 8], sections }) => {
13
15
  let sections_std = [];
@@ -41,6 +43,7 @@ export const DatasetContext = createContext({});
41
43
  export const DatasetRegistryContext = createContext(() => { }); // A modifier, utiliser un seul context
42
44
  export const ControlContext = createContext(undefined);
43
45
  export const DSL_DashboardPage = ({ name = 'Tableau de bord', columns = 2, children, debug = false }) => {
46
+ const { token } = useToken();
44
47
  const [datasets, setdatasets] = useState({});
45
48
  const [palette, setPalette] = useState(DEFAULT_PALETTE);
46
49
  //const allDatasetLoaded = Object.values(datasets).every(d => !d.isFetching);
@@ -61,6 +64,9 @@ export const DSL_DashboardPage = ({ name = 'Tableau de bord', columns = 2, child
61
64
  else if (typeof (c.type) != 'string' && c.type.name == DSL_Control.name) {
62
65
  return "control";
63
66
  }
67
+ else if (typeof (c.type) != 'string' && c.type.name == Section.name) {
68
+ return "section";
69
+ }
64
70
  else {
65
71
  return "other";
66
72
  }
@@ -68,9 +74,23 @@ export const DSL_DashboardPage = ({ name = 'Tableau de bord', columns = 2, child
68
74
  const visible_components = childrenArray.filter((c) => c && getComponentKind(c) == 'other');
69
75
  const logic_components = childrenArray.filter((c) => getComponentKind(c) == 'logical');
70
76
  const control_components = childrenArray.filter((c) => getComponentKind(c) == 'control');
77
+ const section_components = childrenArray.filter((c) => getComponentKind(c) == 'section');
71
78
  if (debug && !logic_components.some((c) => typeof c.type !== "string" && c.type.name === Debug.name)) {
72
79
  logic_components.push(_jsx(Debug, {}, "debug_property"));
73
80
  }
81
+ const items = section_components.map((s) => ({
82
+ key: s.props.title,
83
+ label: s.props.title,
84
+ children: s,
85
+ icon: typeof (s.props.icon) === 'string' ? (_jsx(Icon, { icon: s.props.icon, fontSize: 18, style: { marginInlineEnd: -6 } })) : s.props.icon,
86
+ }));
87
+ if (visible_components.length > 0) {
88
+ items.push({
89
+ key: "99 - Autres",
90
+ label: '-',
91
+ children: _jsx(Section, { title: 'Autres', children: visible_components })
92
+ });
93
+ }
74
94
  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: {
75
95
  padding: 12,
76
96
  position: "sticky",
@@ -79,5 +99,12 @@ export const DSL_DashboardPage = ({ name = 'Tableau de bord', columns = 2, child
79
99
  backgroundColor: "#fff",
80
100
  height: "auto",
81
101
  width: "100%",
82
- }, children: control_components }), _jsx(Row, { gutter: [8, 8], style: { margin: 16 }, children: visible_components.map((component, idx) => _jsx(Col, { xl: 24 / columns, xs: 24, children: _jsx(DSL_ChartBlock, { children: component }) }, idx)) }), logic_components] }) }) })] }));
102
+ }, children: control_components }), items.length > 1 ?
103
+ _jsx(Tabs, { defaultActiveKey: "1", items: items, centered: true, tabBarStyle: { margin: 6,
104
+ padding: 4,
105
+ background: token.colorBgContainer,
106
+ borderRadius: token.borderRadiusLG }, style: { margin: 4 } })
107
+ :
108
+ _jsxs("div", { style: { margin: 4 }, children: [" ", items?.[0].children, " "] }) //Show content without tabs if only one
109
+ , logic_components] }) }) })] }));
83
110
  };
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+ export interface SectionProps {
3
+ title: string;
4
+ children?: React.ReactElement | React.ReactElement[];
5
+ icon?: React.ReactElement | string;
6
+ }
7
+ export declare const Section: React.FC<SectionProps>;
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Col, Row } from "antd";
3
+ import React, { isValidElement } from "react";
4
+ import { DSL_ChartBlock } from "./Block";
5
+ export const Section = ({ children }) => {
6
+ const columns = 2;
7
+ const childrenArray = React.Children.toArray(children).filter(isValidElement);
8
+ return (_jsx(Row, { gutter: [8, 8], style: { margin: 0 }, children: childrenArray.map((component, idx) => (_jsx(Col, { xl: 24 / columns, xs: 24, children: _jsx(DSL_ChartBlock, { children: component }) }, idx))) }));
9
+ };
@@ -19,4 +19,5 @@ import { ChartEcharts } from "../components/Charts/ChartEcharts";
19
19
  import { useBlockConfig } from "../components/DashboardPage/Block";
20
20
  import { Statistics, StatisticsCollection } from "../components/Charts/Statistics";
21
21
  import { MapLayer, Map } from "../components/Map/Map";
22
- export { Dashboard, Dataset, Provider, Transform, Join, Filter, DataPreview, ChartEcharts, ChartPie, ChartYearSerie, Statistics, StatisticsCollection, useDataset, useDatasets, useAllDatasets, useBlockConfig, Producer, Control, useControl, useAllControls, Radio, Select, Input, Palette, usePalette, PalettePreview, Debug, Map, MapLayer };
22
+ import { Section } from "../components/DashboardPage/Section";
23
+ export { Dashboard, Dataset, Provider, Transform, Join, Filter, Section, DataPreview, ChartEcharts, ChartPie, ChartYearSerie, Statistics, StatisticsCollection, useDataset, useDatasets, useAllDatasets, useBlockConfig, Producer, Control, useControl, useAllControls, Radio, Select, Input, Palette, usePalette, PalettePreview, Debug, Map, MapLayer };
package/dist/dsl/index.js CHANGED
@@ -19,4 +19,5 @@ import { ChartEcharts } from "../components/Charts/ChartEcharts";
19
19
  import { useBlockConfig } from "../components/DashboardPage/Block";
20
20
  import { Statistics, StatisticsCollection } from "../components/Charts/Statistics";
21
21
  import { MapLayer, Map } from "../components/Map/Map";
22
- export { Dashboard, Dataset, Provider, Transform, Join, Filter, DataPreview, ChartEcharts, ChartPie, ChartYearSerie, Statistics, StatisticsCollection, useDataset, useDatasets, useAllDatasets, useBlockConfig, Producer, Control, useControl, useAllControls, Radio, Select, Input, Palette, usePalette, PalettePreview, Debug, Map, MapLayer };
22
+ import { Section } from "../components/DashboardPage/Section";
23
+ export { Dashboard, Dataset, Provider, Transform, Join, Filter, Section, DataPreview, ChartEcharts, ChartPie, ChartYearSerie, Statistics, StatisticsCollection, useDataset, useDatasets, useAllDatasets, useBlockConfig, Producer, Control, useControl, useAllControls, Radio, Select, Input, Palette, usePalette, PalettePreview, Debug, Map, MapLayer };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geo2france/api-dashboard",
3
- "version": "1.11.2",
3
+ "version": "1.13.0",
4
4
  "private": false,
5
5
  "description": "Build dashboards with JSX/TSX",
6
6
  "main": "dist/index.js",