territories-dashboard-lib 0.1.0__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.
- territories_dashboard_lib/commons/__init__.py +0 -0
- territories_dashboard_lib/commons/decorators.py +36 -0
- territories_dashboard_lib/commons/models.py +9 -0
- territories_dashboard_lib/geo_lib/__init__.py +0 -0
- territories_dashboard_lib/geo_lib/admin.py +64 -0
- territories_dashboard_lib/geo_lib/enums.py +7 -0
- territories_dashboard_lib/geo_lib/migrations/0001_initial.py +51 -0
- territories_dashboard_lib/geo_lib/migrations/__init__.py +0 -0
- territories_dashboard_lib/geo_lib/models.py +58 -0
- territories_dashboard_lib/geo_lib/urls.py +27 -0
- territories_dashboard_lib/geo_lib/views.py +239 -0
- territories_dashboard_lib/indicators_lib/__init__.py +0 -0
- territories_dashboard_lib/indicators_lib/admin.py +140 -0
- territories_dashboard_lib/indicators_lib/enums.py +59 -0
- territories_dashboard_lib/indicators_lib/export.py +29 -0
- territories_dashboard_lib/indicators_lib/format.py +34 -0
- territories_dashboard_lib/indicators_lib/methodo_pdf.py +99 -0
- territories_dashboard_lib/indicators_lib/migrations/0001_initial.py +138 -0
- territories_dashboard_lib/indicators_lib/migrations/__init__.py +0 -0
- territories_dashboard_lib/indicators_lib/models.py +230 -0
- territories_dashboard_lib/indicators_lib/payloads.py +54 -0
- territories_dashboard_lib/indicators_lib/query/commons.py +223 -0
- territories_dashboard_lib/indicators_lib/query/comparison.py +70 -0
- territories_dashboard_lib/indicators_lib/query/details.py +64 -0
- territories_dashboard_lib/indicators_lib/query/histogram.py +82 -0
- territories_dashboard_lib/indicators_lib/query/indicator_card.py +102 -0
- territories_dashboard_lib/indicators_lib/query/top_10.py +100 -0
- territories_dashboard_lib/indicators_lib/query/utils.py +20 -0
- territories_dashboard_lib/indicators_lib/refresh_filters.py +17 -0
- territories_dashboard_lib/indicators_lib/table.py +154 -0
- territories_dashboard_lib/indicators_lib/urls.py +97 -0
- territories_dashboard_lib/indicators_lib/views.py +490 -0
- territories_dashboard_lib/superset_lib/__init__.py +0 -0
- territories_dashboard_lib/superset_lib/admin.py +22 -0
- territories_dashboard_lib/superset_lib/guest_token.py +64 -0
- territories_dashboard_lib/superset_lib/logic.py +67 -0
- territories_dashboard_lib/superset_lib/migrations/0001_initial.py +45 -0
- territories_dashboard_lib/superset_lib/migrations/__init__.py +0 -0
- territories_dashboard_lib/superset_lib/models.py +52 -0
- territories_dashboard_lib/superset_lib/serializers.py +10 -0
- territories_dashboard_lib/superset_lib/urls.py +10 -0
- territories_dashboard_lib/superset_lib/views.py +19 -0
- territories_dashboard_lib/tracking_lib/__init__.py +0 -0
- territories_dashboard_lib/tracking_lib/enums.py +7 -0
- territories_dashboard_lib/tracking_lib/logic.py +78 -0
- territories_dashboard_lib/tracking_lib/migrations/0001_initial.py +45 -0
- territories_dashboard_lib/tracking_lib/migrations/__init__.py +0 -0
- territories_dashboard_lib/tracking_lib/models.py +79 -0
- territories_dashboard_lib/website_lib/__init__.py +0 -0
- territories_dashboard_lib/website_lib/admin.py +40 -0
- territories_dashboard_lib/website_lib/context_processors.py +27 -0
- territories_dashboard_lib/website_lib/forms.py +47 -0
- territories_dashboard_lib/website_lib/migrations/0001_initial.py +91 -0
- territories_dashboard_lib/website_lib/migrations/__init__.py +0 -0
- territories_dashboard_lib/website_lib/models.py +148 -0
- territories_dashboard_lib/website_lib/navigation.py +124 -0
- territories_dashboard_lib/website_lib/params.py +268 -0
- territories_dashboard_lib/website_lib/serializers.py +105 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/css/website.css +956 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/chart.js +13 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/chartjs-plugin-datalabels.js +1 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/html2canvas.js +20 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/comparaison/data.mjs +62 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/comparaison/history.mjs +98 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/comparaison/main-values.mjs +30 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/comparaison/page.mjs +105 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/comparaison/territory-chart.mjs +141 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/details/data.mjs +59 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/details/histogram.mjs +130 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/details/map.mjs +25 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/details/page.mjs +96 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/details/proportions.mjs +77 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/details/sankey.mjs +27 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/details/table.mjs +229 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/details/top10.mjs +76 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/details/utils.mjs +8 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/dom.mjs +92 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/enums.mjs +104 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/export-graph.mjs +15 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/export.mjs +20 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/filters.mjs +159 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/format.mjs +54 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/side_panel.mjs +103 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/theme/history.mjs +89 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/theme/main-value.mjs +22 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/theme/page.mjs +162 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/theme/statistics.mjs +42 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/utils.mjs +93 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/static/page.mjs +35 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/patternomaly.js +1452 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/react18.js +31 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/reactdom18.js +267 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/supersetEmbed.js +355 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/react/indicatorMap.bundle.js +2 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/react/sankeyGraph.bundle.js +2 -0
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/react/vendors-node_modules_mapbox-gl_dist_mapbox-gl_js.bundle.js +2 -0
- territories_dashboard_lib/website_lib/static_content.py +20 -0
- territories_dashboard_lib/website_lib/templates/admin/indicators_lib/indicator/change_form.html +8 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/404.html +10 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/500.html +10 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/base.html +42 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/base.js +47 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/footer.html +96 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/header.html +101 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/header.js +102 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/comparaison/[theme]/components/indicateur-card.html +48 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/comparaison/[theme]/page.html +52 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/chart-buttons.html +29 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/geo_params.html +71 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/indicator-card.html +52 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/loader.html +28 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/side_panel.html +27 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/side_panel_geo.html +80 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/side_panel_geo.js +85 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/side_panel_methodo.html +45 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/side_panel_methodo.js +19 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/themes-list.html +9 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/themes-nav.html +33 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/title.html +28 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/components/filters-reminder.html +19 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/components/table.html +123 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/page.html +166 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/themes/components/extremum.html +15 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/themes/components/indicateur-card.html +76 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/themes/page.html +66 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/lexique/page.html +17 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/page.html +14 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/sitemap/page.html +71 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/static/page.html +16 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/superset/page.html +55 -0
- territories_dashboard_lib/website_lib/templatetags/htmlparams.py +75 -0
- territories_dashboard_lib/website_lib/templatetags/other_filters.py +30 -0
- territories_dashboard_lib/website_lib/views.py +212 -0
- {territories_dashboard_lib-0.1.0.dist-info → territories_dashboard_lib-0.1.2.dist-info}/METADATA +1 -1
- territories_dashboard_lib-0.1.2.dist-info/RECORD +138 -0
- territories_dashboard_lib-0.1.0.dist-info/RECORD +0 -5
- {territories_dashboard_lib-0.1.0.dist-info → territories_dashboard_lib-0.1.2.dist-info}/WHEEL +0 -0
- {territories_dashboard_lib-0.1.0.dist-info → territories_dashboard_lib-0.1.2.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 };
|