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,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
|
+
});
|