territories-dashboard-lib 0.1.1__py3-none-any.whl → 0.1.2__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 (76) 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-0.1.1.dist-info → territories_dashboard_lib-0.1.2.dist-info}/METADATA +1 -1
  73. territories_dashboard_lib-0.1.2.dist-info/RECORD +138 -0
  74. territories_dashboard_lib-0.1.1.dist-info/RECORD +0 -67
  75. {territories_dashboard_lib-0.1.1.dist-info → territories_dashboard_lib-0.1.2.dist-info}/WHEEL +0 -0
  76. {territories_dashboard_lib-0.1.1.dist-info → territories_dashboard_lib-0.1.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,98 @@
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(minDate, maxDate, maxValue) {
11
+ return {
12
+ x: {
13
+ beginAtZero: false,
14
+ suggestedMax: maxDate,
15
+ suggestedMin: minDate,
16
+ type: "linear",
17
+ ticks: {
18
+ callback: function (value) {
19
+ if (typeof value === "string") {
20
+ return value;
21
+ }
22
+ return value % 1 === 0 ? value.toString() : "";
23
+ },
24
+ },
25
+ },
26
+ y: {
27
+ beginAtZero: true,
28
+ suggestedMax: Math.ceil(maxValue * 1.2),
29
+ // stacked: true,
30
+ type: "linear",
31
+ ticks: {
32
+ callback: function (value) {
33
+ if (typeof value === "string") {
34
+ return value;
35
+ }
36
+ return formatIndicatorValue(value);
37
+ },
38
+ },
39
+ },
40
+ };
41
+ }
42
+
43
+ function getMaxValue(history, comparedHistory) {
44
+ history.map((v) => v.valeur);
45
+ return Math.max(
46
+ ...history.map((v) => v.valeur),
47
+ ...comparedHistory.map((v) => v.valeur)
48
+ );
49
+ }
50
+
51
+ function makeHistoryChart(indicator, history, comparedHistory) {
52
+ const maxValue = getMaxValue(history, comparedHistory);
53
+ const { minDate, maxDate } = getDates(history);
54
+
55
+ const ctx = document.querySelector(`#card-${indicator.id} .history-chart`);
56
+ const params = getParams();
57
+ const datasets = [
58
+ getDataset(params.territory_name, history, indicator),
59
+ getDataset(params.cmp_territory_name, comparedHistory, indicator),
60
+ ];
61
+ const chartType = history.length > 1 ? "line" : "bar";
62
+ setBackgroundInDatasets(datasets, true, chartType);
63
+ const data = { datasets };
64
+ const options = {
65
+ layout: {
66
+ padding: {
67
+ top: 30,
68
+ },
69
+ },
70
+ interaction: {
71
+ intersect: false,
72
+ mode: "x",
73
+ },
74
+ maintainAspectRatio: false,
75
+ plugins: {
76
+ legend: {
77
+ display: true,
78
+ },
79
+ datalabels: {
80
+ anchor: "end",
81
+ align: "end",
82
+ color: "black",
83
+ },
84
+ },
85
+ scales: getScales(minDate, maxDate, maxValue),
86
+ };
87
+
88
+ makeChart(ctx, chartType, data, options);
89
+ }
90
+
91
+ function updateHistoryDOM(indicator) {
92
+ const history = getIndicatorDataScript(indicator, "values");
93
+ if (history) {
94
+ makeHistoryChart(indicator, history.values, history.cmp_values);
95
+ }
96
+ }
97
+
98
+ export { updateHistoryDOM };
@@ -0,0 +1,30 @@
1
+ import {
2
+ getIndicatorDataScript,
3
+ getParams,
4
+ removeDelaySpinner,
5
+ } from "../dom.mjs";
6
+ import { formatIndicatorValue } from "../format.mjs";
7
+
8
+ function updateMainValues(indicator) {
9
+ const params = getParams();
10
+ const data = getIndicatorDataScript(indicator, "values");
11
+ if (!data) {
12
+ return;
13
+ }
14
+ removeDelaySpinner(`#card-${indicator.id} .delay-spinner`);
15
+
16
+ const element = document.querySelector(
17
+ `#card-${indicator.id} .territory-value > span:first-child`
18
+ );
19
+
20
+ const value = formatIndicatorValue(data.values[0].valeur);
21
+ element.innerHTML = `<strong>${params.territory_name} : </strong>${value}`;
22
+
23
+ const cmpElement = document.querySelector(
24
+ `#card-${indicator.id} .compared-territory-value > span:first-child`
25
+ );
26
+ const cmpValue = formatIndicatorValue(data.cmp_values[0].valeur);
27
+ cmpElement.innerHTML = `<strong>${params.cmp_territory_name} : </strong>${cmpValue}`;
28
+ }
29
+
30
+ export { updateMainValues };
@@ -0,0 +1,105 @@
1
+ /* globals Chart, ChartDataLabels */
2
+ import { callData, getSearchParams } from "./data.mjs";
3
+ import { delaySpinner, getClosestIndicator } from "../dom.mjs";
4
+ import { handleFilterClick, initializeFilters } from "../filters.mjs";
5
+ import { addSidePanelListener, openMethodoSidePanel } from "../side_panel.mjs";
6
+
7
+ import { exportImageAsync } from "../export-graph.mjs";
8
+ import { exportToCSV } from "../export.mjs";
9
+
10
+ Chart.register(
11
+ Chart.CategoryScale,
12
+ Chart.LinearScale,
13
+ Chart.BarElement,
14
+ Chart.PointElement,
15
+ Chart.LineElement,
16
+ Chart.Title,
17
+ Chart.Tooltip,
18
+ Chart.Legend,
19
+ Chart.LogarithmicScale,
20
+ ChartDataLabels
21
+ );
22
+
23
+ function makeIndicatorCards() {
24
+ const subThemes = JSON.parse(
25
+ document.getElementById("sub-themes-js").textContent
26
+ );
27
+ subThemes.forEach((subTheme) => {
28
+ subTheme.indicators.forEach((indicator) => {
29
+ initializeFilters(indicator);
30
+ callData(indicator);
31
+ });
32
+ });
33
+ }
34
+
35
+ delaySpinner();
36
+ makeIndicatorCards();
37
+ document.querySelectorAll(".indicator-card").forEach((indicatorCard) => {
38
+ const indicator = getClosestIndicator(indicatorCard);
39
+
40
+ indicatorCard.querySelectorAll(".filter-tag").forEach((button) => {
41
+ button.addEventListener("click", async () => {
42
+ await handleFilterClick(indicator);
43
+ callData(indicator);
44
+ });
45
+ });
46
+
47
+ indicatorCard
48
+ .querySelectorAll('button[aria-controls="slide-panel-methodo"]')
49
+ .forEach((button) => {
50
+ button.addEventListener("click", () => {
51
+ openMethodoSidePanel(indicator, button);
52
+ });
53
+ });
54
+ });
55
+
56
+ document
57
+ .querySelectorAll('button[data-type="export-csv"]')
58
+ .forEach((button) => {
59
+ const indicator = getClosestIndicator(button);
60
+ button.addEventListener("click", () => {
61
+ button.setAttribute("disabled", "true");
62
+ const searchParams = getSearchParams(indicator);
63
+ exportToCSV(button, indicator, button.dataset.route, searchParams);
64
+ });
65
+ });
66
+
67
+ document
68
+ .querySelectorAll('button[data-type="export-png"]')
69
+ .forEach((button) => {
70
+ const indicator = getClosestIndicator(button);
71
+ button.addEventListener("click", async () => {
72
+ button.setAttribute("disabled", "true");
73
+ // need to wait a small amount of time for DOM update
74
+ await new Promise((resolve) => setTimeout(resolve, 50));
75
+ await exportImageAsync(
76
+ button.parentElement.previousElementSibling,
77
+ `${indicator.name} - ${button.dataset.title}`
78
+ );
79
+ button.removeAttribute("disabled");
80
+ });
81
+ });
82
+
83
+ document.addEventListener("DOMContentLoaded", () => {
84
+ const withPattern = localStorage.getItem("pattern") === "true";
85
+ document.querySelectorAll(".pattern-toggle").forEach((button) => {
86
+ button.checked = withPattern;
87
+ button.addEventListener("click", () => {
88
+ localStorage.setItem("pattern", button.checked ? "true" : "false");
89
+ setTimeout(() => {
90
+ document
91
+ .querySelectorAll(".indicator-card")
92
+ .forEach((indicatorCard) => {
93
+ const indicator = getClosestIndicator(indicatorCard);
94
+ callData(indicator);
95
+ });
96
+ }, 100);
97
+ document.querySelectorAll(".pattern-toggle").forEach((b) => {
98
+ const withUpdatedPattern =
99
+ localStorage.getItem("pattern") === "true";
100
+ b.checked = withUpdatedPattern;
101
+ });
102
+ });
103
+ });
104
+ addSidePanelListener();
105
+ });
@@ -0,0 +1,141 @@
1
+ import { getIndicatorDataScript, getParams } from "../dom.mjs";
2
+ import { MAX_TERRITORIES_BEFORE_HIDE } from "../enums.mjs";
3
+ import { formatIndicatorValue } from "../format.mjs";
4
+ import { makeChart, setBackgroundInDatasets } from "../utils.mjs";
5
+
6
+ function getChartData(histogram, params) {
7
+ const labels = histogram.buckets.map(
8
+ (bucket) =>
9
+ `${formatIndicatorValue(bucket[0])}-${formatIndicatorValue(
10
+ bucket[1]
11
+ )}`
12
+ );
13
+ const dataMain = Object.entries(histogram.values).map((entries) => ({
14
+ x: labels[Number(entries[0]) - 1],
15
+ y: entries[1].length,
16
+ territories: entries[1],
17
+ }));
18
+ const dataCompared = Object.entries(histogram.comparedValues).map(
19
+ (entries) => ({
20
+ x: labels[Number(entries[0]) - 1],
21
+ y: entries[1].length * -1,
22
+ territories: entries[1],
23
+ })
24
+ );
25
+ const datasets = [
26
+ {
27
+ label: params.territory_name.split(" - ")[0],
28
+ data: dataMain,
29
+ backgroundColor: "#6A6AF4",
30
+ barPercentage: 1.0,
31
+ },
32
+ {
33
+ label: params.cmp_territory_name.split(" - ")[0],
34
+ data: dataCompared,
35
+ backgroundColor: "#000091",
36
+ barPercentage: 1.0,
37
+ },
38
+ ];
39
+ setBackgroundInDatasets(datasets);
40
+ return {
41
+ labels: labels,
42
+ datasets,
43
+ };
44
+ }
45
+
46
+ function getScales() {
47
+ const zeroLineWidth = 2;
48
+ return {
49
+ x: {
50
+ beginAtZero: false,
51
+ display: true,
52
+ type: "category",
53
+ stacked: true,
54
+ },
55
+ y: {
56
+ beginAtZero: true,
57
+ display: true,
58
+ stacked: true,
59
+ ticks: {
60
+ callback: function (value) {
61
+ if (typeof value === "number") {
62
+ return formatIndicatorValue(Math.abs(value));
63
+ }
64
+ return value;
65
+ },
66
+ },
67
+ grid: {
68
+ drawBorder: true,
69
+ color: (context) =>
70
+ // Couleur distincte pour la ligne du zéro
71
+ context.tick.value === 0 ? "#000" : "#ccc",
72
+ // Épaisseur de la ligne zéro
73
+ lineWidth: (context) =>
74
+ context.tick.value === 0 ? zeroLineWidth : 1,
75
+ },
76
+ },
77
+ };
78
+ }
79
+
80
+ function getOptions(params) {
81
+ const { mesh } = params;
82
+
83
+ return {
84
+ responsive: true,
85
+ maintainAspectRatio: false,
86
+ minBarLength: 8,
87
+ layout: {
88
+ padding: {
89
+ top: 40,
90
+ right: 100,
91
+ },
92
+ },
93
+ plugins: {
94
+ legend: {
95
+ display: true,
96
+ },
97
+ title: {
98
+ display: true,
99
+ text: "Comparaison des valeurs",
100
+ },
101
+ datalabels: {
102
+ display: false,
103
+ },
104
+ tooltip: {
105
+ callbacks: {
106
+ label: function (context) {
107
+ const multiplier = context.datasetIndex === 0 ? 1 : -1;
108
+ const numberOfTerritories = context.raw.y * multiplier;
109
+ return numberOfTerritories > MAX_TERRITORIES_BEFORE_HIDE
110
+ ? `${numberOfTerritories} ${mesh}${
111
+ numberOfTerritories > 1 ? "s" : ""
112
+ }`
113
+ : context.raw.territories;
114
+ },
115
+ },
116
+ },
117
+ },
118
+ scales: getScales(),
119
+ };
120
+ }
121
+
122
+ function makeComparedTerritoryChart(indicator) {
123
+ const indicatorData = getIndicatorDataScript(
124
+ indicator,
125
+ "comparison-histogram"
126
+ );
127
+ if (!indicatorData) {
128
+ return;
129
+ }
130
+ const params = getParams();
131
+
132
+ const ctx = document.querySelector(
133
+ `#card-${indicator.id} .comparison-chart`
134
+ );
135
+ const chartData = getChartData(indicatorData, params);
136
+ const options = getOptions(params);
137
+
138
+ makeChart(ctx, "bar", chartData, options);
139
+ }
140
+
141
+ export { makeComparedTerritoryChart };
@@ -0,0 +1,59 @@
1
+ import { getApiUrls, getParams, makeIndicatorDataScript } from "../dom.mjs";
2
+ import { getIndicatorFilters } from "../filters.mjs";
3
+
4
+ import { makeHistogramChart } from "./histogram.mjs";
5
+ import { makeProportionsChart } from "./proportions.mjs";
6
+ import { makeTables } from "./table.mjs";
7
+ import { makeTop10Chart } from "./top10.mjs";
8
+
9
+ async function fetchHistogram(indicator, apiUrls, searchParams) {
10
+ const response = await fetch(`${apiUrls.histogram}?${searchParams}`);
11
+ if (response.ok) {
12
+ const data = await response.json();
13
+ makeIndicatorDataScript(indicator, "histogram", data);
14
+ makeHistogramChart(indicator);
15
+ }
16
+ }
17
+
18
+ async function fetchTop10(indicator, apiUrls, searchParams) {
19
+ const response = await fetch(`${apiUrls["top-10"]}?${searchParams}`);
20
+ if (response.ok) {
21
+ const data = await response.json();
22
+ makeIndicatorDataScript(indicator, "top-10", data);
23
+ makeTop10Chart(indicator);
24
+ }
25
+ }
26
+
27
+ async function fetchProportions(indicator, apiUrls, searchParams) {
28
+ if (indicator.filters.length > 0) {
29
+ const response = await fetch(`${apiUrls.proportions}?${searchParams}`);
30
+ if (response.ok) {
31
+ const data = await response.json();
32
+ makeIndicatorDataScript(indicator, "proportions", data);
33
+ makeProportionsChart(indicator);
34
+ }
35
+ }
36
+ }
37
+
38
+ function getSearchParams(indicator) {
39
+ const params = getParams();
40
+ const filters = getIndicatorFilters(indicator);
41
+ const filtersQuery = filters
42
+ .map(([dimension, filter]) => `&${dimension}=${filter}`)
43
+ .join("");
44
+ const searchParams = new URLSearchParams(
45
+ `territory=${params.territory_id}-${params.territory_mesh}&submesh=${params.mesh}${filtersQuery}`
46
+ ).toString();
47
+ return searchParams;
48
+ }
49
+
50
+ function callData(indicator) {
51
+ const apiUrls = getApiUrls(indicator);
52
+ const searchParams = getSearchParams(indicator);
53
+ fetchHistogram(indicator, apiUrls, searchParams);
54
+ fetchTop10(indicator, apiUrls, searchParams);
55
+ fetchProportions(indicator, apiUrls, searchParams);
56
+ makeTables();
57
+ }
58
+
59
+ export { callData, getSearchParams };
@@ -0,0 +1,130 @@
1
+ import { getIndicatorDataScript, getParams } from "../dom.mjs";
2
+ import {
3
+ getMeshLevelTitle,
4
+ MAX_TERRITORIES_BEFORE_HIDE,
5
+ MILLIONS,
6
+ SHORT_MESH_NUMBER_OF_LETTERS,
7
+ THOUSANDS,
8
+ } from "../enums.mjs";
9
+ import { makeChart, setBackgroundInDatasets } from "../utils.mjs";
10
+
11
+ import { addEmptyGraphMessage } from "./utils.mjs";
12
+ import { formatIndicatorValue } from "../format.mjs";
13
+
14
+ function getDatalabels(dataset, mesh) {
15
+ return {
16
+ anchor: "end",
17
+ align: "end",
18
+ color: "black",
19
+ font: {
20
+ weight: "bold",
21
+ },
22
+ formatter: function (value, context) {
23
+ const formatted = formatIndicatorValue(value.y, true);
24
+ if (!formatted) {
25
+ return "";
26
+ }
27
+ if (
28
+ context.active &&
29
+ dataset.comments.length > context.dataIndex &&
30
+ dataset.comments[context.dataIndex] !== "" &&
31
+ dataset.comments[context.dataIndex].split("\n").length <=
32
+ MAX_TERRITORIES_BEFORE_HIDE
33
+ ) {
34
+ return dataset.comments[context.dataIndex];
35
+ }
36
+ return `${formatted} ${getMeshLevelTitle(mesh).slice(
37
+ 0,
38
+ SHORT_MESH_NUMBER_OF_LETTERS
39
+ )}.${value.y > 1 ? "s" : ""}`;
40
+ },
41
+ };
42
+ }
43
+
44
+ function getScales(labels, maxFromData) {
45
+ return {
46
+ x: {
47
+ beginAtZero: false,
48
+ grid: {
49
+ display: false,
50
+ },
51
+ ticks: {
52
+ callback: function (value) {
53
+ function formatLabel(v) {
54
+ if (
55
+ [THOUSANDS, MILLIONS].some((s) =>
56
+ labels[v].includes(s)
57
+ )
58
+ ) {
59
+ return labels[v];
60
+ }
61
+ return formatIndicatorValue(
62
+ Number.parseFloat(labels[v]),
63
+ true
64
+ );
65
+ }
66
+ if (value === labels.length - 1) {
67
+ return `${formatLabel(value)} +`;
68
+ }
69
+ return `${formatLabel(value)} - ${formatLabel(value + 1)}`;
70
+ },
71
+ },
72
+ },
73
+ y: {
74
+ beginAtZero: true,
75
+ grid: {
76
+ display: false,
77
+ },
78
+ max:
79
+ maxFromData <= MAX_TERRITORIES_BEFORE_HIDE
80
+ ? maxFromData + 1
81
+ : maxFromData,
82
+ },
83
+ };
84
+ }
85
+
86
+ export function makeHistogramChart(indicator) {
87
+ const { mesh } = getParams();
88
+ const histogramData = getIndicatorDataScript(indicator, "histogram");
89
+ if (!histogramData) {
90
+ return;
91
+ }
92
+ const { datasetsHistogramBarChart: dataset, deciles } = histogramData;
93
+
94
+ const ctx = document.getElementById("histogramChart");
95
+ if (Object.keys(dataset).length === 0) {
96
+ addEmptyGraphMessage(ctx);
97
+ return;
98
+ }
99
+
100
+ const labels = deciles.map((decile) => formatIndicatorValue(decile));
101
+
102
+ setBackgroundInDatasets([dataset], false);
103
+
104
+ const data = {
105
+ labels: labels,
106
+ datasets: [dataset],
107
+ };
108
+ const maxFromData = Math.max(...dataset.data.map((data) => data.y));
109
+ const options = {
110
+ indexAxis: "x",
111
+ layout: {
112
+ padding: {
113
+ top: 30,
114
+ },
115
+ },
116
+ maintainAspectRatio: false,
117
+ plugins: {
118
+ legend: {
119
+ display: false,
120
+ },
121
+ tooltip: {
122
+ enabled: false,
123
+ },
124
+ datalabels: getDatalabels(dataset, mesh),
125
+ },
126
+ scales: getScales(labels, maxFromData),
127
+ };
128
+
129
+ makeChart(ctx, "bar", data, options);
130
+ }
@@ -0,0 +1,25 @@
1
+ /* globals ReactDOM, React, IndicatorMap */
2
+
3
+ import { getParams } from "../dom.mjs";
4
+
5
+ function makeMap(indicator) {
6
+ const params = getParams();
7
+ const container = document.getElementById("indicator-map");
8
+ const root = ReactDOM.createRoot(container);
9
+ const element = React.createElement(
10
+ IndicatorMap,
11
+ {
12
+ indicator,
13
+ mesh: params.mesh,
14
+ territory: {
15
+ geoId: params.territory_id,
16
+ geoLevel: params.territory_mesh,
17
+ label: params.territory_name,
18
+ },
19
+ },
20
+ null
21
+ );
22
+ root.render(element);
23
+ }
24
+
25
+ export { makeMap };
@@ -0,0 +1,96 @@
1
+ /* globals Chart, ChartDataLabels */
2
+
3
+ import { callData, getSearchParams } from "./data.mjs";
4
+ import {
5
+ handleFilterClick,
6
+ initializeFilters,
7
+ updateFiltersReminder,
8
+ updateUrlWithFilters,
9
+ } from "../filters.mjs";
10
+ import { addSidePanelListener, openMethodoSidePanel } from "../side_panel.mjs";
11
+
12
+ import { exportImageAsync } from "../export-graph.mjs";
13
+ import { exportToCSV } from "../export.mjs";
14
+ import { makeMap } from "./map.mjs";
15
+ import { makeProportionsChart } from "./proportions.mjs";
16
+ import { makeSankeyGraph } from "./sankey.mjs";
17
+ import { makeTop10Chart } from "./top10.mjs";
18
+
19
+ Chart.register(
20
+ Chart.CategoryScale,
21
+ Chart.LinearScale,
22
+ Chart.BarElement,
23
+ Chart.Title,
24
+ Chart.Tooltip,
25
+ Chart.Legend,
26
+ ChartDataLabels
27
+ );
28
+
29
+ const indicator = JSON.parse(
30
+ document.getElementById("indicator-js").textContent
31
+ );
32
+ initializeFilters(indicator);
33
+ callData(indicator);
34
+ makeMap(indicator);
35
+ makeSankeyGraph(indicator);
36
+ const openMethodoButton = document.querySelector(
37
+ 'button[aria-controls="slide-panel-methodo"]'
38
+ );
39
+ openMethodoButton.addEventListener("click", () => {
40
+ openMethodoSidePanel(indicator, openMethodoButton);
41
+ });
42
+ document.querySelectorAll(".filter-tag").forEach((button) => {
43
+ button.addEventListener("click", async () => {
44
+ await handleFilterClick(indicator);
45
+ updateUrlWithFilters();
46
+ updateFiltersReminder(indicator);
47
+ callData(indicator);
48
+ });
49
+ });
50
+ updateUrlWithFilters();
51
+ updateFiltersReminder(indicator);
52
+
53
+ document
54
+ .querySelectorAll('button[data-type="export-png"]')
55
+ .forEach((button) => {
56
+ button.addEventListener("click", async () => {
57
+ button.setAttribute("disabled", "true");
58
+ // need to wait a small amount of time for DOM update
59
+ await new Promise((resolve) => setTimeout(resolve, 50));
60
+ await exportImageAsync(
61
+ button.parentElement.previousElementSibling,
62
+ `${indicator.name} - ${button.dataset.title}`
63
+ );
64
+ button.removeAttribute("disabled");
65
+ });
66
+ });
67
+
68
+ document
69
+ .querySelectorAll('button[data-type="export-csv"]')
70
+ .forEach((button) => {
71
+ button.addEventListener("click", () => {
72
+ button.setAttribute("disabled", "true");
73
+ const searchParams = getSearchParams(indicator);
74
+ exportToCSV(button, indicator, button.dataset.route, searchParams);
75
+ });
76
+ });
77
+
78
+ document.addEventListener("DOMContentLoaded", () => {
79
+ const withPattern = localStorage.getItem("pattern") === "true";
80
+ document.querySelectorAll(".pattern-toggle").forEach((button) => {
81
+ button.checked = withPattern;
82
+ button.addEventListener("click", () => {
83
+ localStorage.setItem("pattern", button.checked ? "true" : "false");
84
+ setTimeout(() => {
85
+ makeProportionsChart(indicator);
86
+ makeTop10Chart(indicator);
87
+ }, 100);
88
+ document.querySelectorAll(".pattern-toggle").forEach((b) => {
89
+ const withUpdatedPattern =
90
+ localStorage.getItem("pattern") === "true";
91
+ b.checked = withUpdatedPattern;
92
+ });
93
+ });
94
+ });
95
+ addSidePanelListener();
96
+ });