territories-dashboard-lib 0.1.1__py3-none-any.whl → 0.1.3__py3-none-any.whl

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.

Potentially problematic release.


This version of territories-dashboard-lib might be problematic. Click here for more details.

Files changed (77) hide show
  1. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/css/website.css +956 -0
  2. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/chart.js +13 -0
  3. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/chartjs-plugin-datalabels.js +1 -0
  4. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/html2canvas.js +20 -0
  5. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/comparaison/data.mjs +62 -0
  6. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/comparaison/history.mjs +98 -0
  7. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/comparaison/main-values.mjs +30 -0
  8. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/comparaison/page.mjs +105 -0
  9. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/comparaison/territory-chart.mjs +141 -0
  10. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/details/data.mjs +59 -0
  11. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/details/histogram.mjs +130 -0
  12. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/details/map.mjs +25 -0
  13. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/details/page.mjs +96 -0
  14. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/details/proportions.mjs +77 -0
  15. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/details/sankey.mjs +27 -0
  16. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/details/table.mjs +229 -0
  17. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/details/top10.mjs +76 -0
  18. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/details/utils.mjs +8 -0
  19. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/dom.mjs +92 -0
  20. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/enums.mjs +104 -0
  21. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/export-graph.mjs +15 -0
  22. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/export.mjs +20 -0
  23. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/filters.mjs +159 -0
  24. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/format.mjs +54 -0
  25. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/side_panel.mjs +103 -0
  26. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/theme/history.mjs +89 -0
  27. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/theme/main-value.mjs +22 -0
  28. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/theme/page.mjs +162 -0
  29. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/theme/statistics.mjs +42 -0
  30. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/utils.mjs +93 -0
  31. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/static/page.mjs +35 -0
  32. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/patternomaly.js +1452 -0
  33. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/react18.js +31 -0
  34. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/reactdom18.js +267 -0
  35. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/supersetEmbed.js +355 -0
  36. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/react/indicatorMap.bundle.js +2 -0
  37. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/react/sankeyGraph.bundle.js +2 -0
  38. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/react/vendors-node_modules_mapbox-gl_dist_mapbox-gl_js.bundle.js +2 -0
  39. territories_dashboard_lib/website_lib/templates/admin/indicators_lib/indicator/change_form.html +8 -0
  40. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/404.html +10 -0
  41. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/500.html +10 -0
  42. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/base.html +42 -0
  43. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/base.js +47 -0
  44. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/footer.html +96 -0
  45. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/header.html +101 -0
  46. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/header.js +102 -0
  47. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/comparaison/[theme]/components/indicateur-card.html +48 -0
  48. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/comparaison/[theme]/page.html +52 -0
  49. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/chart-buttons.html +29 -0
  50. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/geo_params.html +71 -0
  51. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/indicator-card.html +52 -0
  52. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/loader.html +28 -0
  53. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/side_panel.html +27 -0
  54. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/side_panel_geo.html +80 -0
  55. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/side_panel_geo.js +85 -0
  56. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/side_panel_methodo.html +45 -0
  57. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/side_panel_methodo.js +19 -0
  58. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/themes-list.html +9 -0
  59. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/themes-nav.html +33 -0
  60. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/title.html +28 -0
  61. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/components/filters-reminder.html +19 -0
  62. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/components/table.html +123 -0
  63. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/page.html +166 -0
  64. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/themes/components/extremum.html +15 -0
  65. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/themes/components/indicateur-card.html +76 -0
  66. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/themes/page.html +66 -0
  67. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/lexique/page.html +17 -0
  68. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/page.html +14 -0
  69. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/sitemap/page.html +71 -0
  70. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/static/page.html +16 -0
  71. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/superset/page.html +55 -0
  72. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/svg/delete-back.svg +1 -0
  73. {territories_dashboard_lib-0.1.1.dist-info → territories_dashboard_lib-0.1.3.dist-info}/METADATA +1 -1
  74. territories_dashboard_lib-0.1.3.dist-info/RECORD +139 -0
  75. territories_dashboard_lib-0.1.1.dist-info/RECORD +0 -67
  76. {territories_dashboard_lib-0.1.1.dist-info → territories_dashboard_lib-0.1.3.dist-info}/WHEEL +0 -0
  77. {territories_dashboard_lib-0.1.1.dist-info → territories_dashboard_lib-0.1.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,159 @@
1
+ function getIndicatorFilters(indicator) {
2
+ return Array.from(
3
+ document.querySelectorAll(
4
+ `.filter-tag[aria-pressed="true"][data-indicator="${indicator.id}"]`
5
+ )
6
+ ).map((button) => [button.dataset.dimension, button.innerText]);
7
+ }
8
+
9
+ function getCurrentFiltersForIndicatorAndDimension(indicator, dimension) {
10
+ return Array.from(
11
+ document.querySelectorAll(
12
+ `.filter-tag[aria-pressed="true"][data-indicator="${indicator.id}"][data-dimension="${dimension}"]`
13
+ )
14
+ ).map((button) => button.innerText);
15
+ }
16
+
17
+ function arrayAreSameSet(arr1, arr2) {
18
+ const xs = new Set(arr1);
19
+ const ys = new Set(arr2);
20
+ return xs.size === ys.size && [...xs].every((x) => ys.has(x));
21
+ }
22
+
23
+ async function handleFilterClick(indicator) {
24
+ // need for DOM to update
25
+ const smallAmountOfTime = 10;
26
+ await new Promise((resolve) => {
27
+ setTimeout(resolve, smallAmountOfTime);
28
+ });
29
+
30
+ let indicatorStorage = localStorage.getItem(indicator.name);
31
+ if (indicatorStorage === null) {
32
+ localStorage.setItem(indicator.name, "{}");
33
+ indicatorStorage = localStorage.getItem(indicator.name);
34
+ }
35
+ const indicatorLocalData = JSON.parse(indicatorStorage);
36
+
37
+ const filtersToSet = {};
38
+ indicator.filters.forEach(([dimensionObj, filtersObj]) => {
39
+ const filters = filtersObj.map((filterOb) => filterOb.db_name);
40
+ const dimension = dimensionObj.db_name;
41
+ const currentFilters = getCurrentFiltersForIndicatorAndDimension(
42
+ indicator,
43
+ dimension
44
+ );
45
+ filtersToSet[dimension] = arrayAreSameSet(filters, currentFilters)
46
+ ? null
47
+ : currentFilters;
48
+ });
49
+ indicatorLocalData.filtersByDimension = filtersToSet;
50
+
51
+ localStorage.setItem(indicator.name, JSON.stringify(indicatorLocalData));
52
+ }
53
+
54
+ function updateUrlWithFilters() {
55
+ const excludeFilters = Array.from(
56
+ document.querySelectorAll(
57
+ '.filter-tag[data-default="true"][aria-pressed="false"]'
58
+ )
59
+ ).map((b) => [b.dataset.dimension, `!${b.innerText}`]);
60
+ const includeFilters = Array.from(
61
+ document.querySelectorAll(
62
+ '.filter-tag[data-default="false"][aria-pressed="true"]'
63
+ )
64
+ ).map((b) => [b.dataset.dimension, b.innerText]);
65
+ const stringFilters = includeFilters.concat(excludeFilters);
66
+ const dimensions = new Set(
67
+ Array.from(document.querySelectorAll(".filter-tag")).map(
68
+ (b) => b.dataset.dimension
69
+ )
70
+ );
71
+ const currentUrl = new URL(window.location);
72
+ dimensions.forEach((dimension) => {
73
+ currentUrl.searchParams.delete(dimension);
74
+ });
75
+ stringFilters.forEach((f) => {
76
+ currentUrl.searchParams.append(f[0], f[1]);
77
+ });
78
+ window.history.replaceState({}, "", currentUrl.toString());
79
+ }
80
+
81
+ function initialFiltersByDimension(indicator, dimension) {
82
+ let initialFilters = [];
83
+ let initializedLocally = false;
84
+ const localRawData = localStorage.getItem(indicator.name);
85
+ if (localRawData) {
86
+ const localData = JSON.parse(localRawData);
87
+ if (
88
+ localData.filtersByDimension &&
89
+ localData.filtersByDimension[dimension] !== null
90
+ ) {
91
+ initialFilters = localData.filtersByDimension[dimension];
92
+ initializedLocally = true;
93
+ }
94
+ }
95
+ if (initializedLocally === false) {
96
+ initialFilters = Array.from(
97
+ document.querySelectorAll(
98
+ `.filter-tag[data-indicator="${indicator.id}"][data-default="true"][data-dimension="${dimension}"]`
99
+ )
100
+ ).map((button) => button.innerText);
101
+ }
102
+ Array.from(
103
+ document.querySelectorAll(
104
+ `.filter-tag[data-indicator="${indicator.id}"][data-dimension="${dimension}"]`
105
+ )
106
+ ).forEach((button) => {
107
+ if (button.dataset.setfromurl === "true") {
108
+ return;
109
+ }
110
+ const pressed = initialFilters.includes(button.innerText)
111
+ ? "true"
112
+ : "false";
113
+ button.setAttribute("aria-pressed", pressed);
114
+ });
115
+ }
116
+
117
+ function initializeFilters(indicator) {
118
+ indicator.filters.forEach(([dimension]) => {
119
+ initialFiltersByDimension(indicator, dimension.db_name);
120
+ });
121
+ }
122
+
123
+ function updateFiltersReminder(indicator) {
124
+ if (indicator.filters.length > 1) {
125
+ indicator.filters.forEach(([dimension]) => {
126
+ if (!dimension.is_breakdown) {
127
+ const currentFilters = Array.from(
128
+ document.querySelectorAll(
129
+ `.filters-dimension button[data-dimension="${dimension.db_name}"][aria-pressed="true"]`
130
+ )
131
+ );
132
+ const currentFiltersHtml =
133
+ currentFilters.length > 0
134
+ ? currentFilters
135
+ .map(
136
+ (filter) =>
137
+ `<p class="fr-tag">${filter.textContent.trim()}</p>`
138
+ )
139
+ .join("")
140
+ : "<p class=fr-tag>Aucun filtre</p>";
141
+ Array.from(
142
+ document.querySelectorAll(
143
+ `.filters-reminder-dimension[data-dimension="${dimension.db_name}"]`
144
+ )
145
+ ).forEach((container) => {
146
+ container.innerHTML = currentFiltersHtml;
147
+ });
148
+ }
149
+ });
150
+ }
151
+ }
152
+
153
+ export {
154
+ initializeFilters,
155
+ handleFilterClick,
156
+ getIndicatorFilters,
157
+ updateUrlWithFilters,
158
+ updateFiltersReminder,
159
+ };
@@ -0,0 +1,54 @@
1
+ /* eslint-disable no-magic-numbers */
2
+ import { MILLIONS, THOUSANDS } from "./enums.mjs";
3
+
4
+ function removeUseless0(value) {
5
+ let newValue = value;
6
+ if (newValue.indexOf(".") > 0) {
7
+ if (newValue.slice(-2) === "00") {
8
+ newValue = newValue.slice(0, -2);
9
+ }
10
+ if (newValue.slice(-1) === "0") {
11
+ newValue = newValue.slice(0, -1);
12
+ }
13
+ if (newValue.slice(-1) === ".") {
14
+ newValue = newValue.slice(0, -1);
15
+ }
16
+ }
17
+ return newValue;
18
+ }
19
+
20
+ function getPrecision(value, forceInteger) {
21
+ if (forceInteger) {
22
+ return value.toFixed(0);
23
+ }
24
+ return value.toFixed(1);
25
+ }
26
+
27
+ function formatIndicatorValue(value, forceInteger) {
28
+ if (value === undefined || isNaN(value) || value === null) {
29
+ return "-";
30
+ }
31
+ let nb = null;
32
+ if (Math.abs(value) > 999999) {
33
+ nb =
34
+ removeUseless0(
35
+ getPrecision(
36
+ (Math.sign(value) * Math.abs(value)) / 1000000,
37
+ forceInteger
38
+ )
39
+ ) + MILLIONS;
40
+ } else if (Math.abs(value) > 999) {
41
+ nb =
42
+ removeUseless0(
43
+ getPrecision(
44
+ (Math.sign(value) * Math.abs(value)) / 1000,
45
+ forceInteger
46
+ )
47
+ ) + THOUSANDS;
48
+ } else {
49
+ nb = removeUseless0(getPrecision(value, forceInteger));
50
+ }
51
+ return nb.replace(".", ",");
52
+ }
53
+
54
+ export { formatIndicatorValue };
@@ -0,0 +1,103 @@
1
+ import { fillMethodoSidePanel } from "./dom.mjs";
2
+
3
+ let buttonWhichOpenedPanel = null;
4
+
5
+ function closeSidePanel() {
6
+ const sidePanelGeo = document.getElementById("slide-panel-geo");
7
+ const sidePanelMethodo = document.getElementById("slide-panel-methodo");
8
+ sidePanelGeo.classList.remove("tdbmd-slide-panel--show");
9
+ sidePanelMethodo.classList.remove("tdbmd-slide-panel--show");
10
+ if (sidePanelGeo.style.display === "block") {
11
+ setTimeout(() => {
12
+ sidePanelGeo.style.display = "none";
13
+ }, 500);
14
+ }
15
+ if (sidePanelMethodo.style.display === "block") {
16
+ setTimeout(() => {
17
+ sidePanelMethodo.style.display = "none";
18
+ }, 500);
19
+ }
20
+ document.querySelectorAll(".validate-territory-btn").forEach((btn) => {
21
+ delete btn.dataset.comparison;
22
+ });
23
+ releaseFocusTrap();
24
+ if (buttonWhichOpenedPanel) {
25
+ buttonWhichOpenedPanel.focus();
26
+ } else {
27
+ document.getElementById("contenu").focus();
28
+ }
29
+ }
30
+
31
+ function openSidePanel(button, type, comparison = false) {
32
+ buttonWhichOpenedPanel = button;
33
+ const panelId = `slide-panel-${type}`;
34
+ const sidePanel = document.getElementById(panelId);
35
+ sidePanel.style.display = "block";
36
+ setTimeout(() => sidePanel.classList.add("tdbmd-slide-panel--show"), 100);
37
+ if (comparison) {
38
+ document.querySelectorAll(".validate-territory-btn").forEach((btn) => {
39
+ btn.dataset.comparison = "true";
40
+ });
41
+ }
42
+ sidePanel.querySelector("button").focus();
43
+ trapFocus(sidePanel);
44
+ }
45
+
46
+ let focusTrapListener;
47
+
48
+ function trapFocus(container) {
49
+ const focusableSelectors =
50
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
51
+ const focusableElements = container.querySelectorAll(focusableSelectors);
52
+ const firstElement = focusableElements[0];
53
+ const lastElement = focusableElements[focusableElements.length - 1];
54
+
55
+ focusTrapListener = function (e) {
56
+ if (e.key === "Tab") {
57
+ if (e.shiftKey && document.activeElement === firstElement) {
58
+ e.preventDefault();
59
+ lastElement.focus();
60
+ } else if (!e.shiftKey && document.activeElement === lastElement) {
61
+ e.preventDefault();
62
+ firstElement.focus();
63
+ }
64
+ } else if (e.key === "Escape") {
65
+ closeSidePanel();
66
+ }
67
+ };
68
+
69
+ document.addEventListener("keydown", focusTrapListener);
70
+ }
71
+
72
+ function releaseFocusTrap() {
73
+ document.removeEventListener("keydown", focusTrapListener);
74
+ }
75
+
76
+ function openMethodoSidePanel(indicator, button) {
77
+ fillMethodoSidePanel(indicator);
78
+ openSidePanel(button, "methodo");
79
+ }
80
+
81
+ function addSidePanelListener() {
82
+ const button = document.querySelector(
83
+ 'button[aria-controls="slide-panel-geo"][data-comparison="false"]'
84
+ );
85
+ if (button) {
86
+ button.addEventListener("click", () => openSidePanel(button, "geo"));
87
+ }
88
+ const cmpButton = document.querySelector(
89
+ 'button[aria-controls="slide-panel-geo"][data-comparison="true"]'
90
+ );
91
+ if (cmpButton) {
92
+ cmpButton.addEventListener("click", () =>
93
+ openSidePanel(cmpButton, "geo", true)
94
+ );
95
+ }
96
+ document
97
+ .querySelectorAll('button[data-side-panel-close="true"]')
98
+ .forEach((closeButton) => {
99
+ closeButton.addEventListener("click", () => closeSidePanel());
100
+ });
101
+ }
102
+
103
+ export { openMethodoSidePanel, addSidePanelListener };
@@ -0,0 +1,89 @@
1
+ import {
2
+ getDataset,
3
+ getDates,
4
+ makeChart,
5
+ setBackgroundInDatasets,
6
+ } from "../utils.mjs";
7
+ import { getIndicatorDataScript, getParams } from "../dom.mjs";
8
+ import { formatIndicatorValue } from "../format.mjs";
9
+
10
+ function getScales(indicatorData) {
11
+ const { minDate, maxDate } = getDates(indicatorData);
12
+
13
+ function xTicksCallback(value) {
14
+ if (typeof value === "string") {
15
+ return value;
16
+ }
17
+ return value % 1 === 0 ? value.toString() : "";
18
+ }
19
+ function yTicksCallback(value) {
20
+ if (typeof value === "string") {
21
+ return value;
22
+ }
23
+
24
+ return formatIndicatorValue(value);
25
+ }
26
+
27
+ return {
28
+ x: {
29
+ type: "linear",
30
+ position: "bottom",
31
+ suggestedMax: maxDate,
32
+ suggestedMin: minDate,
33
+ ticks: {
34
+ stepSize: 0.2,
35
+ callback: xTicksCallback,
36
+ },
37
+ },
38
+ y: {
39
+ beginAtZero: true,
40
+ ticks: {
41
+ callback: yTicksCallback,
42
+ },
43
+ },
44
+ };
45
+ }
46
+
47
+ function makeHistoryChart(indicator, indicatorData) {
48
+ const ctx = document.querySelector(`#card-${indicator.id} .history-chart`);
49
+ const params = getParams();
50
+ const datasets = [
51
+ getDataset(params.territory_name, indicatorData, indicator),
52
+ ];
53
+ setBackgroundInDatasets(datasets);
54
+ const data = {
55
+ datasets,
56
+ };
57
+ const options = {
58
+ layout: {
59
+ padding: {
60
+ top: 40,
61
+ right: 100,
62
+ },
63
+ },
64
+ maintainAspectRatio: false,
65
+ plugins: {
66
+ legend: {
67
+ display: false,
68
+ },
69
+ datalabels: {
70
+ align: "top",
71
+ anchor: "end",
72
+ color: "black",
73
+ },
74
+ },
75
+ scales: getScales(indicatorData),
76
+ };
77
+ const chartType = indicatorData.length > 1 ? "line" : "bar";
78
+ makeChart(ctx, chartType, data, options);
79
+ }
80
+
81
+ function updateHistoryDOM(indicator) {
82
+ const indicatorData = getIndicatorDataScript(indicator, "values");
83
+ if (!indicatorData) {
84
+ return;
85
+ }
86
+ makeHistoryChart(indicator, indicatorData.values);
87
+ }
88
+
89
+ export { updateHistoryDOM };
@@ -0,0 +1,22 @@
1
+ import {
2
+ getIndicatorDataScript,
3
+ getIsAlternativeUnit,
4
+ removeDelaySpinner,
5
+ } from "../dom.mjs";
6
+ import { formatIndicatorValue } from "../format.mjs";
7
+
8
+ function updateMainValueDOM(indicator) {
9
+ const mainData = getIndicatorDataScript(indicator, "values");
10
+ if (!mainData) {
11
+ return;
12
+ }
13
+ const data = mainData.values[0];
14
+ const displayAlternative = getIsAlternativeUnit(indicator.id);
15
+ const val = displayAlternative ? data.valeur_alternative : data.valeur;
16
+ removeDelaySpinner(`#card-${indicator.id} .delay-spinner`);
17
+ document.querySelector(
18
+ `#card-${indicator.id} .main-value span:first-child`
19
+ ).textContent = `${formatIndicatorValue(val)}`;
20
+ }
21
+
22
+ export { updateMainValueDOM };
@@ -0,0 +1,162 @@
1
+ /* globals Chart, ChartDataLabels */
2
+
3
+ import {
4
+ delaySpinner,
5
+ getApiUrls,
6
+ getClosestIndicator,
7
+ getParams,
8
+ makeIndicatorDataScript,
9
+ } from "../dom.mjs";
10
+
11
+ import {
12
+ getIndicatorFilters,
13
+ handleFilterClick,
14
+ initializeFilters,
15
+ } from "../filters.mjs";
16
+ import { addSidePanelListener, openMethodoSidePanel } from "../side_panel.mjs";
17
+
18
+ import { exportImageAsync } from "../export-graph.mjs";
19
+ import { exportToCSV } from "../export.mjs";
20
+
21
+ import { updateHistoryDOM } from "./history.mjs";
22
+ import { updateMainValueDOM } from "./main-value.mjs";
23
+ import { updateStatisticsDOM } from "./statistics.mjs";
24
+
25
+ Chart.register(
26
+ Chart.CategoryScale,
27
+ Chart.LinearScale,
28
+ Chart.BarElement,
29
+ Chart.Title,
30
+ Chart.Tooltip,
31
+ Chart.Legend,
32
+ ChartDataLabels
33
+ );
34
+
35
+ function getSearchParams(indicator) {
36
+ const params = getParams();
37
+ const filters = getIndicatorFilters(indicator);
38
+ const filtersQuery = filters
39
+ .map(([dimension, filter]) => `&${dimension}=${filter}`)
40
+ .join("");
41
+ const searchParams = new URLSearchParams(
42
+ `territory=${params.territory_id}-${params.territory_mesh}&submesh=${params.mesh}${filtersQuery}`
43
+ ).toString();
44
+ return searchParams;
45
+ }
46
+
47
+ function callData(indicator) {
48
+ const apiUrls = getApiUrls(indicator);
49
+ const searchParams = getSearchParams(indicator);
50
+ [
51
+ [
52
+ "values",
53
+ (ind) => {
54
+ updateMainValueDOM(ind);
55
+ updateHistoryDOM(ind);
56
+ },
57
+ ],
58
+ ["statistics", updateStatisticsDOM],
59
+ ].forEach(async ([key, callbackUpdateDOM]) => {
60
+ const response = await fetch(`${apiUrls[key]}?${searchParams}`);
61
+ if (response.ok) {
62
+ const data = await response.json();
63
+ makeIndicatorDataScript(indicator, key, data);
64
+ callbackUpdateDOM(indicator);
65
+ }
66
+ });
67
+ }
68
+
69
+ function makeIndicatorCards() {
70
+ const subThemes = JSON.parse(
71
+ document.getElementById("sub-themes-js").textContent
72
+ );
73
+ subThemes.forEach((subTheme) => {
74
+ subTheme.indicators.forEach((indicator) => {
75
+ initializeFilters(indicator);
76
+ callData(indicator);
77
+ });
78
+ });
79
+ }
80
+
81
+ function toggleIndicatorUnit(input) {
82
+ const indicator = getClosestIndicator(input);
83
+ const unity = input.checked ? indicator.unite_alternative : indicator.unite;
84
+ const accessibleName = input.checked
85
+ ? indicator.unite_alternative_nom_accessible
86
+ : indicator.unite_nom_accessible;
87
+ Array.from(
88
+ document.querySelectorAll(`#card-${indicator.id} .unite`)
89
+ ).forEach((node) => {
90
+ node.innerText = unity;
91
+ node.setAttribute("aria-label", accessibleName);
92
+ });
93
+ const ariaLiveMessage = input.checked
94
+ ? `L'unité affichée est : ${indicator.unite_alternative_nom_accessible}`
95
+ : `L'unité affichée est : ${indicator.unite_nom_accessible}`;
96
+ document.getElementById(`${indicator.id}-toggle-unit-messages`).innerText =
97
+ ariaLiveMessage;
98
+ updateMainValueDOM(indicator);
99
+ updateStatisticsDOM(indicator);
100
+ updateHistoryDOM(indicator);
101
+ }
102
+
103
+ delaySpinner();
104
+ makeIndicatorCards();
105
+ document.querySelectorAll(".indicator-card").forEach((indicatorCard) => {
106
+ const indicator = getClosestIndicator(indicatorCard);
107
+
108
+ indicatorCard.querySelectorAll(".filter-tag").forEach((button) => {
109
+ button.addEventListener("click", async () => {
110
+ await handleFilterClick(indicator);
111
+ callData(indicator);
112
+ });
113
+ });
114
+
115
+ indicatorCard.querySelectorAll(".toggle-unite").forEach((input) => {
116
+ input.addEventListener("input", (event) => {
117
+ toggleIndicatorUnit(event.target);
118
+ });
119
+ });
120
+
121
+ indicatorCard
122
+ .querySelectorAll('button[aria-controls="slide-panel-methodo"]')
123
+ .forEach((button) => {
124
+ button.addEventListener("click", () => {
125
+ openMethodoSidePanel(indicator, button);
126
+ });
127
+ });
128
+ });
129
+
130
+ document.addEventListener("DOMContentLoaded", () => {
131
+ document.querySelectorAll(".toggle-unite").forEach((input) => {
132
+ toggleIndicatorUnit(input);
133
+ });
134
+ addSidePanelListener();
135
+ });
136
+
137
+ document
138
+ .querySelectorAll('button[data-type="export-csv"]')
139
+ .forEach((button) => {
140
+ const indicator = getClosestIndicator(button);
141
+ button.addEventListener("click", () => {
142
+ button.setAttribute("disabled", "true");
143
+ const searchParams = getSearchParams(indicator);
144
+ exportToCSV(button, indicator, button.dataset.route, searchParams);
145
+ });
146
+ });
147
+
148
+ document
149
+ .querySelectorAll('button[data-type="export-png"]')
150
+ .forEach((button) => {
151
+ const indicator = getClosestIndicator(button);
152
+ button.addEventListener("click", async () => {
153
+ button.setAttribute("disabled", "true");
154
+ // need to wait a small amount of time for DOM update
155
+ await new Promise((resolve) => setTimeout(resolve, 50));
156
+ await exportImageAsync(
157
+ button.parentElement.previousElementSibling,
158
+ `${indicator.name} - ${button.dataset.title}`
159
+ );
160
+ button.removeAttribute("disabled");
161
+ });
162
+ });
@@ -0,0 +1,42 @@
1
+ import {
2
+ getIndicatorDataScript,
3
+ getIsAlternativeUnit,
4
+ removeDelaySpinner,
5
+ } from "../dom.mjs";
6
+ import { formatIndicatorValue } from "../format.mjs";
7
+
8
+ function updateStatisticsDOM(indicator) {
9
+ const data = getIndicatorDataScript(indicator, "statistics");
10
+ if (!data) {
11
+ return;
12
+ }
13
+ const displayAlternative = getIsAlternativeUnit(indicator.id);
14
+ const alternative = displayAlternative ? "_alternative" : "";
15
+ ["min", "med", "max"].forEach((prefix) => {
16
+ removeDelaySpinner(`#card-${indicator.id} .delay-spinner`);
17
+ const key = `${prefix}${alternative}`;
18
+ const name = data[`code_${key}_name`];
19
+ if (name !== undefined) {
20
+ document.querySelector(
21
+ `#card-${indicator.id} .${prefix}-name`
22
+ ).textContent = name;
23
+ }
24
+ const value = data[key];
25
+ document.querySelector(
26
+ `#card-${indicator.id} .${prefix}-value > span:first-child`
27
+ ).textContent =
28
+ value === undefined ? "-" : `${formatIndicatorValue(value)}`;
29
+ const count = data[`count_${key}`];
30
+ if (count !== undefined) {
31
+ const text =
32
+ count > 1
33
+ ? `+${count - 1} autre${count - 1 > 1 ? "s" : ""}`
34
+ : "";
35
+ document.querySelector(
36
+ `#card-${indicator.id} .${prefix}-count`
37
+ ).textContent = text;
38
+ }
39
+ });
40
+ }
41
+
42
+ export { updateStatisticsDOM };