territories-dashboard-lib 0.1.3__py3-none-any.whl → 0.1.4__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 (30) hide show
  1. territories_dashboard_lib/indicators_lib/enums.py +26 -0
  2. territories_dashboard_lib/indicators_lib/migrations/0002_filter_color_indicator_min_mesh_and_more.py +28 -0
  3. territories_dashboard_lib/indicators_lib/models.py +12 -2
  4. territories_dashboard_lib/indicators_lib/query/commons.py +8 -2
  5. territories_dashboard_lib/indicators_lib/query/details.py +11 -5
  6. territories_dashboard_lib/indicators_lib/query/top_10.py +6 -2
  7. territories_dashboard_lib/indicators_lib/refresh_filters.py +1 -1
  8. territories_dashboard_lib/website_lib/migrations/0002_mainconf_contact_email_mainconf_newsletter_link_and_more.py +28 -0
  9. territories_dashboard_lib/website_lib/models.py +14 -0
  10. territories_dashboard_lib/website_lib/params.py +26 -10
  11. territories_dashboard_lib/website_lib/serializers.py +2 -0
  12. territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/utils.mjs +3 -6
  13. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/footer.html +1 -1
  14. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/comparaison/[theme]/components/histogram.html +28 -0
  15. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/comparaison/[theme]/components/indicateur-card.html +1 -22
  16. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/components/histogram.html +21 -0
  17. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/components/map.html +10 -0
  18. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/components/proportions.html +21 -0
  19. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/components/sankey.html +17 -0
  20. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/components/table-flows.html +8 -0
  21. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/components/table-values.html +17 -0
  22. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/components/top10.html +19 -0
  23. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/page.html +7 -64
  24. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/themes/components/indicateur-card.html +22 -25
  25. territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/themes/components/stats.html +12 -0
  26. territories_dashboard_lib/website_lib/templatetags/other_filters.py +8 -0
  27. {territories_dashboard_lib-0.1.3.dist-info → territories_dashboard_lib-0.1.4.dist-info}/METADATA +113 -11
  28. {territories_dashboard_lib-0.1.3.dist-info → territories_dashboard_lib-0.1.4.dist-info}/RECORD +30 -19
  29. {territories_dashboard_lib-0.1.3.dist-info → territories_dashboard_lib-0.1.4.dist-info}/WHEEL +0 -0
  30. {territories_dashboard_lib-0.1.3.dist-info → territories_dashboard_lib-0.1.4.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,4 @@
1
+ from django.conf import settings
1
2
  from django.db import models
2
3
 
3
4
 
@@ -57,3 +58,28 @@ MESH_DB = {
57
58
  MeshLevel.Epci: "EPCI",
58
59
  MeshLevel.Town: "DEPCOM",
59
60
  }
61
+
62
+
63
+ def get_miminum_mesh():
64
+ try:
65
+ town_mesh_is_disabled = settings.DISABLE_TOWN_MESH
66
+ return MeshLevel.Epci if town_mesh_is_disabled else MeshLevel.Town
67
+ except AttributeError:
68
+ return MeshLevel.Town
69
+
70
+
71
+ def get_allow_same_mesh():
72
+ try:
73
+ return bool(settings.ALLOW_SAME_MESH)
74
+ except AttributeError:
75
+ return False
76
+
77
+
78
+ def get_all_meshes():
79
+ min_mesh = get_miminum_mesh()
80
+ meshes = []
81
+ for m in MeshLevel:
82
+ meshes.append(m)
83
+ if m == min_mesh:
84
+ break
85
+ return meshes
@@ -0,0 +1,28 @@
1
+ # Generated by Django 5.2.3 on 2025-06-19 12:59
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('indicators_lib', '0001_initial'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddField(
14
+ model_name='filter',
15
+ name='color',
16
+ field=models.TextField(blank=True, help_text='format hexadécimale : #FF11DD', null=True, verbose_name='Couleur'),
17
+ ),
18
+ migrations.AddField(
19
+ model_name='indicator',
20
+ name='min_mesh',
21
+ field=models.TextField(choices=[('fr', 'National'), ('reg', 'Region'), ('dep', 'Department'), ('epci', 'Epci'), ('com', 'Town')], default='com'),
22
+ ),
23
+ migrations.AlterField(
24
+ model_name='indicator',
25
+ name='show_evolution',
26
+ field=models.BooleanField(default=True),
27
+ ),
28
+ ]
@@ -2,7 +2,10 @@ from django.db import models
2
2
  from martor.models import MartorField
3
3
 
4
4
  from territories_dashboard_lib.commons.models import CommonModel
5
- from territories_dashboard_lib.indicators_lib.enums import AggregationFunctions
5
+ from territories_dashboard_lib.indicators_lib.enums import (
6
+ AggregationFunctions,
7
+ MeshLevel,
8
+ )
6
9
  from territories_dashboard_lib.indicators_lib.refresh_filters import refresh_filters
7
10
 
8
11
 
@@ -101,6 +104,7 @@ class Indicator(CommonModel):
101
104
  # Indicator's DB attributes
102
105
  db_table_prefix = models.CharField(max_length=128)
103
106
  db_table_prefix.verbose_name = "Préfixe dans la DB"
107
+ min_mesh = models.TextField(choices=MeshLevel.choices, default=MeshLevel.Town)
104
108
  is_composite = models.BooleanField(default=False)
105
109
  is_composite.verbose_name = "Indicateur composite"
106
110
  show_alternative = models.BooleanField(
@@ -158,7 +162,7 @@ class Indicator(CommonModel):
158
162
  help_text="Nom de la colonne des dimensions de la table des flux",
159
163
  )
160
164
  # Descriptive attributes
161
- show_evolution = models.BooleanField(default=False)
165
+ show_evolution = models.BooleanField(default=True)
162
166
  show_evolution.verbose_name = "Activer l'historique"
163
167
  source = models.TextField(default="", blank=True)
164
168
  description = models.TextField(default="", blank=True)
@@ -216,6 +220,12 @@ class Filter(CommonModel):
216
220
  order.verbose_name = "Ordre"
217
221
  default = models.BooleanField(default=True)
218
222
  default.verbose_name = "Sélectionné par défaut ?"
223
+ color = models.TextField(
224
+ null=True,
225
+ blank=True,
226
+ verbose_name="Couleur",
227
+ help_text="format hexadécimale : #FF11DD",
228
+ )
219
229
 
220
230
  def __str__(self):
221
231
  return self.db_name
@@ -1,4 +1,10 @@
1
- from ..enums import DEFAULT_MESH, FRANCE_DB_VALUES, GeoLevel, MeshLevel
1
+ from ..enums import (
2
+ DEFAULT_MESH,
3
+ FRANCE_DB_VALUES,
4
+ GeoLevel,
5
+ MeshLevel,
6
+ get_miminum_mesh,
7
+ )
2
8
  from ..models import AggregationFunctions, Indicator
3
9
  from .utils import get_breakdown_dimension, run_custom_query
4
10
 
@@ -156,7 +162,7 @@ def get_mesh_level_for_geo_level(mesh, submesh):
156
162
  else submesh
157
163
  )
158
164
  elif mesh in [GeoLevel.Epci, GeoLevel.Town]:
159
- return MeshLevel.Town
165
+ return get_miminum_mesh()
160
166
  else:
161
167
  return submesh or DEFAULT_MESH
162
168
 
@@ -14,21 +14,27 @@ from .utils import get_breakdown_dimension, run_custom_query
14
14
  def get_proportions_chart(indicator, territory, filters):
15
15
  where_territory = get_where_territory(territory)
16
16
  last_year = get_last_year(indicator, territory.mesh)
17
- breakdown_dimension = get_breakdown_dimension(indicator).db_name
17
+ breakdown_dimension = get_breakdown_dimension(indicator)
18
18
 
19
19
  query = f"""
20
- SELECT {calculate_aggregate_values(indicator, with_alternative=False)}, "{breakdown_dimension}" as dimension
20
+ SELECT {calculate_aggregate_values(indicator, with_alternative=False)}, "{breakdown_dimension.db_name}" as dimension
21
21
  FROM "{indicator.db_table_prefix}_{territory.mesh}" as indic
22
22
  WHERE {where_territory} AND annee = {last_year}
23
23
  {add_optional_filters(indicator, filters)}
24
- GROUP BY "{breakdown_dimension}"
24
+ GROUP BY "{breakdown_dimension.db_name}"
25
25
  """
26
26
 
27
27
  data = run_custom_query(query)
28
+ filters_color = {f.db_name: f.color for f in breakdown_dimension.filters.all()}
28
29
  data_dict = {
29
- d["dimension"]: {"label": d["dimension"], "data": [d["valeur"]]} for d in data
30
+ d["dimension"]: {
31
+ "label": d["dimension"],
32
+ "data": [d["valeur"]],
33
+ "color": filters_color.get(d["dimension"]),
34
+ }
35
+ for d in data
30
36
  }
31
- breakdown_filters = filters[breakdown_dimension]
37
+ breakdown_filters = filters[breakdown_dimension.db_name]
32
38
  sorted_data = (
33
39
  [data_dict[filter] for filter in breakdown_filters if filter in data_dict]
34
40
  if filters
@@ -47,8 +47,10 @@ def get_indicator_top_10_data(indicator, territory, submesh, filters):
47
47
  indicator_details = {}
48
48
 
49
49
  breakdown_dimension = get_breakdown_dimension(indicator)
50
- breakdown_dimension = breakdown_dimension.db_name if breakdown_dimension else None
51
- breakdown_filters = filters.get(breakdown_dimension, [])
50
+ breakdown_dimension_name = (
51
+ breakdown_dimension.db_name if breakdown_dimension else None
52
+ )
53
+ breakdown_filters = filters.get(breakdown_dimension_name, [])
52
54
 
53
55
  last_year = get_last_year(indicator, submesh)
54
56
 
@@ -63,6 +65,7 @@ def get_indicator_top_10_data(indicator, territory, submesh, filters):
63
65
  breakdown_by_geocode = defaultdict(dict)
64
66
  for row in breakdown:
65
67
  breakdown_by_geocode[row["code_geo"]][row["dimension"]] = row["valeur"]
68
+ filters_color = {f.db_name: f.color for f in breakdown_dimension.filters.all()}
66
69
  datasets_top_bar_chart = [
67
70
  {
68
71
  "label": f,
@@ -70,6 +73,7 @@ def get_indicator_top_10_data(indicator, territory, submesh, filters):
70
73
  breakdown_by_geocode[territory["code_geo"]][f]
71
74
  for territory in territories
72
75
  ],
76
+ "color": filters_color.get(f),
73
77
  }
74
78
  for f in breakdown_filters
75
79
  ]
@@ -7,7 +7,7 @@ def refresh_filters(dimension):
7
7
  if dimension:
8
8
  query = f'SELECT DISTINCT({dimension.db_name}) as filter FROM "{dimension.indicator.db_table_prefix}_reg"'
9
9
  results = run_custom_query(query)
10
- Filter = apps.get_model("tdbmd_indicators", "Filter")
10
+ Filter = apps.get_model("indicators_lib", "Filter")
11
11
  Filter.objects.filter(dimension=dimension).delete()
12
12
  Filter.objects.bulk_create(
13
13
  [
@@ -0,0 +1,28 @@
1
+ # Generated by Django 5.2.3 on 2025-06-19 14:03
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('website_lib', '0001_initial'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddField(
14
+ model_name='mainconf',
15
+ name='contact_email',
16
+ field=models.TextField(blank=True, default=None, null=True, verbose_name='Email de contact'),
17
+ ),
18
+ migrations.AddField(
19
+ model_name='mainconf',
20
+ name='newsletter_link',
21
+ field=models.TextField(blank=True, default=None, null=True, verbose_name="Lien d'inscription à la newsletter"),
22
+ ),
23
+ migrations.AddField(
24
+ model_name='mainconf',
25
+ name='show_footer_contact_banner',
26
+ field=models.BooleanField(default=False, help_text="Pour afficher la bannière, l'email de contact et le lien d'inscription à la newsletter doivent être renseignés.", verbose_name='Afficher une bannière de contact au-dessus du footer'),
27
+ ),
28
+ ]
@@ -48,6 +48,20 @@ class MainConf(CommonModel):
48
48
  """,
49
49
  default="",
50
50
  )
51
+ contact_email = models.TextField(
52
+ default=None, null=True, blank=True, verbose_name="Email de contact"
53
+ )
54
+ newsletter_link = models.TextField(
55
+ default=None,
56
+ null=True,
57
+ blank=True,
58
+ verbose_name="Lien d'inscription à la newsletter",
59
+ )
60
+ show_footer_contact_banner = models.BooleanField(
61
+ default=False,
62
+ verbose_name="Afficher une bannière de contact au-dessus du footer",
63
+ help_text="Pour afficher la bannière, l'email de contact et le lien d'inscription à la newsletter doivent être renseignés.",
64
+ )
51
65
 
52
66
  @property
53
67
  def entity_breaklines(self):
@@ -5,6 +5,8 @@ from territories_dashboard_lib.indicators_lib.enums import (
5
5
  MESH_TITLES,
6
6
  FranceGeoLevel,
7
7
  MeshLevel,
8
+ get_all_meshes,
9
+ get_allow_same_mesh,
8
10
  )
9
11
  from territories_dashboard_lib.indicators_lib.query.utils import run_custom_query
10
12
 
@@ -139,7 +141,7 @@ class ParamsHandler:
139
141
  ######################## Mesh
140
142
 
141
143
  def get_max_territory_mesh(self):
142
- meshes = [m for m in MeshLevel]
144
+ meshes = get_all_meshes()
143
145
  if self.comparison is False:
144
146
  return self.territory_mesh
145
147
  if meshes.index(self.cmp_territory_mesh) > meshes.index(self.territory_mesh):
@@ -149,18 +151,26 @@ class ParamsHandler:
149
151
  def is_not_valid_mesh(self, mesh):
150
152
  if mesh is None:
151
153
  return True
152
- meshes = [m for m in MeshLevel]
154
+ meshes = get_all_meshes()
153
155
  max_territory_mesh = self.get_max_territory_mesh()
154
- is_not_valid = meshes.index(max_territory_mesh) >= meshes.index(mesh)
156
+ allow_same_mesh = get_allow_same_mesh()
157
+ is_not_valid = (
158
+ meshes.index(max_territory_mesh) > meshes.index(mesh)
159
+ if allow_same_mesh
160
+ else meshes.index(max_territory_mesh) >= meshes.index(mesh)
161
+ )
155
162
  return is_not_valid
156
163
 
157
164
  def get_default_mesh(self):
158
165
  max_territory_mesh = self.get_max_territory_mesh()
159
- meshes = [m for m in MeshLevel]
166
+ meshes = get_all_meshes()
160
167
  if meshes.index(max_territory_mesh) == len(meshes) - 1:
161
168
  default_mesh = meshes[-1]
162
169
  else:
163
- default_mesh = meshes[meshes.index(max_territory_mesh) + 1]
170
+ mesh_index = meshes.index(max_territory_mesh)
171
+ if get_allow_same_mesh() is False:
172
+ mesh_index += 1
173
+ default_mesh = meshes[mesh_index]
164
174
  return default_mesh
165
175
 
166
176
  def get_cookie_mesh(self):
@@ -188,12 +198,17 @@ class ParamsHandler:
188
198
  max_territory_mesh = self.get_max_territory_mesh()
189
199
  meshes = [
190
200
  m
191
- for m in MeshLevel
201
+ for m in get_all_meshes()
192
202
  if not (m == MeshLevel.Town and max_territory_mesh == MeshLevel.National)
193
203
  ]
194
- self.meshes = meshes[
195
- min(meshes.index(max_territory_mesh) + 1, len(meshes) - 1) :
196
- ]
204
+ print("MESHES", meshes)
205
+ min_mesh_index = meshes.index(max_territory_mesh)
206
+ print("index", min_mesh_index)
207
+ if get_allow_same_mesh() is False:
208
+ min_mesh_index += 1
209
+ print("AGAIN", min_mesh_index)
210
+ print("Allow same mesh", get_allow_same_mesh())
211
+ self.meshes = meshes[min(min_mesh_index, len(meshes) - 1) :]
197
212
 
198
213
  ######################## Commons
199
214
 
@@ -245,7 +260,7 @@ class ParamsHandler:
245
260
  "mesh": self.mesh,
246
261
  "meshes": self.meshes,
247
262
  "meshes_titles": MESH_TITLES,
248
- "all_meshes": [m for m in MeshLevel],
263
+ "all_meshes": get_all_meshes(),
249
264
  "url_params": "&".join(url_params),
250
265
  }
251
266
 
@@ -263,6 +278,7 @@ def with_params(view_func):
263
278
 
264
279
  response = view_func(request, *args, context=context, **kwargs)
265
280
  handler.set_cookie(response)
281
+ print(context["params"])
266
282
  return response
267
283
 
268
284
  return wrapper
@@ -22,6 +22,8 @@ def serialize_indicator(indicator):
22
22
  "flows_dimension": indicator.flows_dimension,
23
23
  "theme": indicator.sub_theme.theme.title,
24
24
  "filters": serializer_filters(indicator),
25
+ "show_evolution": indicator.show_evolution,
26
+ "min_mesh": indicator.min_mesh,
25
27
  "secondary_indicator": {
26
28
  "name": indicator.secondary_indicator.name,
27
29
  "title": indicator.secondary_indicator.title,
@@ -62,15 +62,12 @@ export function setBackgroundInDatasets(
62
62
  const backgrounds = Object.keys(COLORS);
63
63
  const withPattern = localStorage.getItem("pattern") === "true";
64
64
  datasets.forEach((dataset, index) => {
65
+ const initialColor = dataset.color ?? backgrounds[index];
65
66
  // patternomaly library
66
67
  const color =
67
68
  pattern && chartType === "bar" && withPattern && window.pattern
68
- ? window.pattern.draw(
69
- PATTERNS[index],
70
- backgrounds[index],
71
- "white"
72
- )
73
- : backgrounds[index];
69
+ ? window.pattern.draw(PATTERNS[index], initialColor, "white")
70
+ : initialColor;
74
71
  dataset.backgroundColor = color;
75
72
  dataset.borderColor = color;
76
73
  if (chartType === "line" && pattern && withPattern && index % 2 === 1) {
@@ -1,5 +1,5 @@
1
1
  <footer role="contentinfo" id="page-footer">
2
- {% if view_name != "website:superset" %}
2
+ {% if view_name != "website:superset" and main_conf.show_footer_contact_banner and main_conf.newsletter_link and main_conf.contact_email %}
3
3
  <div class="fr-follow fr-pt-8w">
4
4
  <h2 class="fr-sr-only">Contact</h2>
5
5
  <div class="fr-container">
@@ -0,0 +1,28 @@
1
+ {% load other_filters %}
2
+
3
+ <section class="fr-accordion tdbmd-indicator-accordion tdbmd-indicator-accordion-comparison">
4
+ <h3 class="fr-accordion__title">
5
+ <button
6
+ class="fr-accordion__btn border-top"
7
+ aria-expanded="false"
8
+ aria-controls="accordion-{{indicator.id}}"
9
+ aria-label="Répartition des valeurs - {{ indicator.title }}"
10
+ >
11
+ Répartition des valeurs
12
+ </button>
13
+ </h3>
14
+ <div
15
+ class="fr-collapse"
16
+ id="accordion-{{indicator.id}}"
17
+ >
18
+ {% include "territories_dashboard_lib/website/pages/indicators/components/title.html" with title="Répartition des territoires selon les valeurs de l'indicateur (graphique en “miroir”)" key=indicator.name h4=True text="Survolez les barres du graphique pour afficher le nombre de territoires dans chaque classe de valeurs (le nom des territoires s'affiche s'il y a moins de 6 territoires). Le graphique du haut correspond à la répartition pour le territoire 1 sélectionné, alors que le graphique du bas (en “miroir”) correspond à la répartition pour le territoire 2 de comparaison. Précisions : Ce graphique varie selon la maille sélectionnée." %}
19
+ {% if params|should_mesh_analysis:indicator %}
20
+ <div style="width: 100%; height: 500px; margin-top: -1rem;">
21
+ <canvas class="comparison-chart" aria-describedby="{{indicator.id}}comparison-histogram-export-csv"></canvas>
22
+ </div>
23
+ {% include "territories_dashboard_lib/website/pages/indicators/components/chart-buttons.html" with name="Comparaison de la répartition" route="comparison-histogram" indicator=indicator pattern="show" %}
24
+ {% else %}
25
+ <div style="margin-top: 16px;">L'histogramme de comparaison n'est pas disponible à la maille sélectionnée.</div>
26
+ {% endif %}
27
+ </div>
28
+ </section>
@@ -20,28 +20,7 @@
20
20
  {% endhtmlparam %}
21
21
 
22
22
  {% htmlparam footer %}
23
- <section class="fr-accordion tdbmd-indicator-accordion tdbmd-indicator-accordion-comparison">
24
- <h3 class="fr-accordion__title">
25
- <button
26
- class="fr-accordion__btn border-top"
27
- aria-expanded="false"
28
- aria-controls="accordion-{{indicator.id}}"
29
- aria-label="Répartition des valeurs - {{ indicator.title }}"
30
- >
31
- Répartition des valeurs
32
- </button>
33
- </h3>
34
- <div
35
- class="fr-collapse"
36
- id="accordion-{{indicator.id}}"
37
- >
38
- {% include "territories_dashboard_lib/website/pages/indicators/components/title.html" with title="Répartition des territoires selon les valeurs de l'indicateur (graphique en “miroir”)" key=indicator.name h4=True text="Survolez les barres du graphique pour afficher le nombre de territoires dans chaque classe de valeurs (le nom des territoires s'affiche s'il y a moins de 6 territoires). Le graphique du haut correspond à la répartition pour le territoire 1 sélectionné, alors que le graphique du bas (en “miroir”) correspond à la répartition pour le territoire 2 de comparaison. Précisions : Ce graphique varie selon la maille sélectionnée." %}
39
- <div style="width: 100%; height: 500px; margin-top: -1rem;">
40
- <canvas class="comparison-chart" aria-describedby="{{indicator.id}}comparison-histogram-export-csv"></canvas>
41
- </div>
42
- {% include "territories_dashboard_lib/website/pages/indicators/components/chart-buttons.html" with name="Comparaison de la répartition" route="comparison-histogram" indicator=indicator pattern="show" %}
43
- </div>
44
- </section>
23
+ {% include "./histogram.html" %}
45
24
  {% endhtmlparam %}
46
25
 
47
26
  {% include "territories_dashboard_lib/website/pages/indicators/components/indicator-card.html" with indicator=indicator %}
@@ -0,0 +1,21 @@
1
+ {% load other_filters %}
2
+
3
+ {% if params.mesh != params.territory_mesh and params|should_mesh_analysis:indicator %}
4
+ <div id="histogramContainer" class="subtheme">
5
+ <div class="fr-px-md-4w fr-px-2w fr-py-2w">
6
+ {% include "territories_dashboard_lib/website/pages/indicators/components/title.html" with title="Répartition des territoires selon les valeurs de l'indicateur" key="repartition" text="Le nom des territoires s'affiche au survol ds'il y a moins de 6 territoires. Précisions : Ce graphique varie selon la maille sélectionnée." %}
7
+ <div style="width:100%; height: 400px;">
8
+ <canvas id="histogramChart" aria-describedby="histogram-export-csv"></canvas>
9
+ </div>
10
+ {% include "./filters-reminder.html" %}
11
+ </div>
12
+ {% include "territories_dashboard_lib/website/pages/indicators/components/chart-buttons.html" with name="Répartition par valeurs" route="histogram" one_indicator=True %}
13
+ </div>
14
+ {% else %}
15
+ <div class="subtheme">
16
+ <div class="fr-px-md-4w fr-px-2w fr-py-2w">
17
+ <h3 class="fr-mt-4w">Répartition par territoires</h3>
18
+ <div>La répartition n'est pas disponible pour la maille sélectionnée.</div>
19
+ </div>
20
+ </div>
21
+ {% endif %}
@@ -0,0 +1,10 @@
1
+ {% load other_filters %}
2
+
3
+ <div class="subtheme fr-px-md-4w fr-p-2w">
4
+ {% if params|should_mesh_analysis:indicator %}
5
+ <div id="indicator-map"></div>
6
+ {% else %}
7
+ <h3 class="fr-mt-4w">Carte</h3>
8
+ <div>La carte n'est pas disponible pour la maille sélectionnée.</div>
9
+ {% endif %}
10
+ </div>
@@ -0,0 +1,21 @@
1
+ {% load other_filters %}
2
+
3
+ {% if indicator.filters %}
4
+ <div class="subtheme">
5
+ {% if params|should_mesh_analysis:indicator %}
6
+ <div class="fr-px-md-4w fr-px-2w fr-py-2w">
7
+ {% include "territories_dashboard_lib/website/pages/indicators/components/title.html" with title="Répartition des valeurs de l'indicateur selon ses modalités" key="proportions" text="Survolez le graphique pour afficher les valeurs de l'indicateur pour chaque modalité. Cliquez sur les catégories de la légende pour afficher/masquer des modalités." %}
8
+ <div style="width:100%; height: auto;">
9
+ <canvas id="proportionsChart" aria-describedby="proportions-export-csv"></canvas>
10
+ </div>
11
+ {% include "./filters-reminder.html" %}
12
+ </div>
13
+ {% include "territories_dashboard_lib/website/pages/indicators/components/chart-buttons.html" with name="Répartition par dimensions" route="proportions" pattern="show" one_indicator=True %}
14
+ {% else %}
15
+ <div class="fr-px-md-4w fr-px-2w fr-py-2w">
16
+ <h3 class="fr-mt-4w">Proportions</h3>
17
+ <div>Le graphique de proporition n'est pas disponible pour la maille sélectionnée.</div>
18
+ </div>
19
+ {% endif %}
20
+ </div>
21
+ {% endif %}
@@ -0,0 +1,17 @@
1
+ {% load other_filters %}
2
+
3
+ {% if indicator.flows_db_table_prefix %}
4
+ <div class="subtheme">
5
+ <div class="fr-px-md-4w fr-px-2w fr-py-2w">
6
+ {% include "territories_dashboard_lib/website/pages/indicators/components/title.html" with title="Top 10 des flux par origine-destination (diagramme de Sankey)" key="sankey" text="Survolez les flux sur le graphique pour afficher les valeurs. Vous pouvez filtrer selon le mode de déplacement en sélectionnant les filtres disponibles sous le titre du graphique. Précisions : Seuls les flux entre les 10 territoires qui génèrent le plus de flux depuis/vers le territoire sélectionné sont affichés." %}
7
+ <div style="width:100%; height: auto;">
8
+ <div id="sankey-graph"></div>
9
+ </div>
10
+ </div>
11
+ <button
12
+ data-title="Sankey"
13
+ class="fr-btn fr-btn--secondary fr-btn--sm fr-icon-line-chart-line fr-btn--icon-right fr-mx-4w fr-mt-4w fr-mb-4w btn-download">
14
+ <span>Exporter le graphique</span>
15
+ </button>
16
+ </div>
17
+ {% endif %}
@@ -0,0 +1,8 @@
1
+ {% if indicator.flows_db_table_prefix %}
2
+ <div class="subtheme">
3
+ <div class="fr-px-md-4w fr-px-2w fr-py-2w">
4
+ <h3 class="fr-mt-4w">Tableau des flux</h3>
5
+ <div class="data-table" data-source="flows"></div>
6
+ </div>
7
+ </div>
8
+ {% endif %}
@@ -0,0 +1,17 @@
1
+ {% load other_filters %}
2
+
3
+ {% if params|should_mesh_analysis:indicator %}
4
+ <div class="subtheme" id="values-table-section">
5
+ <div class="fr-px-md-4w fr-px-2w fr-py-2w">
6
+ <h3 class="fr-mt-4w">Tableau des valeurs de l'indicateur</h3>
7
+ <div class="data-table" data-source="indicator"></div>
8
+ </div>
9
+ </div>
10
+ {% else %}
11
+ <div class="subtheme">
12
+ <div class="fr-px-md-4w fr-px-2w fr-py-2w">
13
+ <h3 class="fr-mt-4w">Tableau des valeurs de l'indicateur</h3>
14
+ <div>Le tableau n'est pas disponible pour la maille sélectionnée.</div>
15
+ </div>
16
+ </div>
17
+ {% endif %}
@@ -0,0 +1,19 @@
1
+ {% load other_filters %}
2
+
3
+ <div class="subtheme">
4
+ {% if params.mesh != params.territory_mesh and params|should_mesh_analysis:indicator %}
5
+ <div class="fr-px-md-4w fr-px-2w fr-py-2w">
6
+ {% include "territories_dashboard_lib/website/pages/indicators/components/title.html" with title="Top 10 des territoires" key="top10" text="Survolez les graphiques pour afficher les valeurs de l'indicateur pour chaque modalité. Cliquez sur les catégories de la légende pour afficher/masquer des modalités. Précisions : Ce graphique varie selon la maille sélectionnée." %}
7
+ <div style="width:100%; height: auto;">
8
+ <canvas id="top10Chart" aria-describedby="top-10-export-csv"></canvas>
9
+ </div>
10
+ {% include "./filters-reminder.html" %}
11
+ </div>
12
+ {% include "territories_dashboard_lib/website/pages/indicators/components/chart-buttons.html" with name="Top 10" route="top-10" pattern="show" one_indicator=True %}
13
+ {% else %}
14
+ <div class="fr-px-md-4w fr-px-2w fr-py-2w">
15
+ <h3 class="fr-mt-4w">Top 10</h3>
16
+ <div>Le top 10 n'est pas disponible pour la maille sélectionnée.</div>
17
+ </div>
18
+ {% endif %}
19
+ </div>
@@ -93,70 +93,13 @@
93
93
  {% endfor %}
94
94
  </div>
95
95
  </div>
96
- <div class="subtheme fr-px-md-4w fr-p-2w">
97
- <div id="indicator-map"></div>
98
- </div>
99
- {% if indicator.flows_db_table_prefix %}
100
- <div class="subtheme">
101
- <div class="fr-px-md-4w fr-px-2w fr-py-2w">
102
- {% include "territories_dashboard_lib/website/pages/indicators/components/title.html" with title="Top 10 des flux par origine-destination (diagramme de Sankey)" key="sankey" text="Survolez les flux sur le graphique pour afficher les valeurs. Vous pouvez filtrer selon le mode de déplacement en sélectionnant les filtres disponibles sous le titre du graphique. Précisions : Seuls les flux entre les 10 territoires qui génèrent le plus de flux depuis/vers le territoire sélectionné sont affichés." %}
103
- <div style="width:100%; height: auto;">
104
- <div id="sankey-graph"></div>
105
- </div>
106
- </div>
107
- <button
108
- data-title="Sankey"
109
- class="fr-btn fr-btn--secondary fr-btn--sm fr-icon-line-chart-line fr-btn--icon-right fr-mx-4w fr-mt-4w fr-mb-4w btn-download">
110
- <span>Exporter le graphique</span>
111
- </button>
112
- </div>
113
- {% endif %}
114
- {% if indicator.filters %}
115
- <div class="subtheme">
116
- <div class="fr-px-md-4w fr-px-2w fr-py-2w">
117
- {% include "territories_dashboard_lib/website/pages/indicators/components/title.html" with title="Répartition des valeurs de l'indicateur selon ses modalités" key="proportions" text="Survolez le graphique pour afficher les valeurs de l'indicateur pour chaque modalité. Cliquez sur les catégories de la légende pour afficher/masquer des modalités." %}
118
- <div style="width:100%; height: auto;">
119
- <canvas id="proportionsChart" aria-describedby="proportions-export-csv"></canvas>
120
- </div>
121
- {% include "./components/filters-reminder.html" %}
122
- </div>
123
- {% include "territories_dashboard_lib/website/pages/indicators/components/chart-buttons.html" with name="Répartition par dimensions" route="proportions" pattern="show" one_indicator=True %}
124
- </div>
125
- {% endif %}
126
- <div class="subtheme">
127
- <div class="fr-px-md-4w fr-px-2w fr-py-2w">
128
- {% include "territories_dashboard_lib/website/pages/indicators/components/title.html" with title="Top 10 des territoires" key="top10" text="Survolez les graphiques pour afficher les valeurs de l'indicateur pour chaque modalité. Cliquez sur les catégories de la légende pour afficher/masquer des modalités. Précisions : Ce graphique varie selon la maille sélectionnée." %}
129
- <div style="width:100%; height: auto;">
130
- <canvas id="top10Chart" aria-describedby="top-10-export-csv"></canvas>
131
- </div>
132
- {% include "./components/filters-reminder.html" %}
133
- </div>
134
- {% include "territories_dashboard_lib/website/pages/indicators/components/chart-buttons.html" with name="Top 10" route="top-10" pattern="show" one_indicator=True %}
135
- </div>
136
- <div id="histogramContainer" class="subtheme">
137
- <div class="fr-px-md-4w fr-px-2w fr-py-2w">
138
- {% include "territories_dashboard_lib/website/pages/indicators/components/title.html" with title="Répartition des territoires selon les valeurs de l'indicateur" key="repartition" text="Le nom des territoires s'affiche au survol ds'il y a moins de 6 territoires. Précisions : Ce graphique varie selon la maille sélectionnée." %}
139
- <div style="width:100%; height: 400px;">
140
- <canvas id="histogramChart" aria-describedby="histogram-export-csv"></canvas>
141
- </div>
142
- {% include "./components/filters-reminder.html" %}
143
- </div>
144
- {% include "territories_dashboard_lib/website/pages/indicators/components/chart-buttons.html" with name="Répartition par valeurs" route="histogram" one_indicator=True %}
145
- </div>
146
- <div class="subtheme" id="values-table-section">
147
- <div class="fr-px-md-4w fr-px-2w fr-py-2w">
148
- <h3 class="fr-mt-4w">Tableau des valeurs de l'indicateur</h3>
149
- <div class="data-table" data-source="indicator"></div>
150
- </div>
151
- </div>
152
- {% if indicator.flows_db_table_prefix %}
153
- <div class="subtheme">
154
- <div class="fr-px-md-4w fr-px-2w fr-py-2w">
155
- <h3 class="fr-mt-4w">Tableau des flux</h3>
156
- <div class="data-table" data-source="flows"></div>
157
- </div>
158
- </div>
159
- {% endif %}
96
+ {% include "./components/map.html" %}
97
+ {% include "./components/sankey.html" %}
98
+ {% include "./components/proportions.html" %}
99
+ {% include "./components/top10.html" %}
100
+ {% include "./components/histogram.html" %}
101
+ {% include "./components/table-values.html" %}
102
+ {% include "./components/table-flows.html" %}
160
103
  </div>
161
104
  {% include "territories_dashboard_lib/website/pages/indicators/components/side_panel_geo.html" %}
162
105
  {% include "territories_dashboard_lib/website/pages/indicators/components/side_panel_methodo.html" %}
@@ -33,36 +33,33 @@
33
33
  </div>
34
34
  </div>
35
35
  </div>
36
- <section class="tdbmd-indicator-card__comparisons fr-grid-row fr-grid-row--gutters">
37
- <h4 class="fr-sr-only">Statistiques</h4>
38
- {% include "./extremum.html" with title="Minimum" prefix="min" %}
39
- {% include "./extremum.html" with title="Mediane" prefix="med" %}
40
- {% include "./extremum.html" with title="Maximum" prefix="max" %}
41
- </section>
36
+ {% include "./stats.html" %}
42
37
  {% endhtmlparam %}
43
38
 
44
39
  {% htmlparam footer %}
45
- <section class="fr-accordion tdbmd-indicator-accordion">
46
- <h4 class="fr-accordion__title">
47
- <button
48
- class="fr-accordion__btn"
49
- aria-expanded="false"
50
- aria-controls="accordion-{{indicator.id}}"
51
- aria-label="Historique - {{ indicator.title }}"
40
+ {% if indicator.show_evolution %}
41
+ <section class="fr-accordion tdbmd-indicator-accordion">
42
+ <h4 class="fr-accordion__title">
43
+ <button
44
+ class="fr-accordion__btn"
45
+ aria-expanded="false"
46
+ aria-controls="accordion-{{indicator.id}}"
47
+ aria-label="Historique - {{ indicator.title }}"
48
+ >
49
+ Historique
50
+ </button>
51
+ </h4>
52
+ <div
53
+ class="fr-collapse"
54
+ id="accordion-{{indicator.id}}"
52
55
  >
53
- Historique
54
- </button>
55
- </h4>
56
- <div
57
- class="fr-collapse"
58
- id="accordion-{{indicator.id}}"
59
- >
60
- <div style="height: 300px;">
61
- <canvas class="history-chart" aria-describedby="{{indicator.id}}values-export-csv"></canvas>
56
+ <div style="height: 300px;">
57
+ <canvas class="history-chart" aria-describedby="{{indicator.id}}values-export-csv"></canvas>
58
+ </div>
59
+ {% include "territories_dashboard_lib/website/pages/indicators/components/chart-buttons.html" with name="Historique" route="values" indicator=indicator no_pb=True %}
62
60
  </div>
63
- {% include "territories_dashboard_lib/website/pages/indicators/components/chart-buttons.html" with name="Historique" route="values" indicator=indicator no_pb=True %}
64
- </div>
65
- </section>
61
+ </section>
62
+ {% endif %}
66
63
  <a
67
64
  class="fr-btn fr-btn--tertiary fr-icon-external-link-fill fr-btn--icon-right tdbmd-indicator-btn"
68
65
  href="/indicateurs/details/{{indicator.name}}/"
@@ -0,0 +1,12 @@
1
+ {% load other_filters %}
2
+
3
+ {% if params.mesh != params.territory_mesh and params|should_mesh_analysis:indicator %}
4
+ <section class="tdbmd-indicator-card__comparisons fr-grid-row fr-grid-row--gutters">
5
+ <h4 class="fr-sr-only">Statistiques</h4>
6
+ {% include "./extremum.html" with title="Minimum" prefix="min" %}
7
+ {% include "./extremum.html" with title="Mediane" prefix="med" %}
8
+ {% include "./extremum.html" with title="Maximum" prefix="max" %}
9
+ </section>
10
+ {% else %}
11
+ <div>Les statistiques ne sont pas disponibles à cette maille.</div>
12
+ {% endif %}
@@ -1,5 +1,6 @@
1
1
  from django import template
2
2
  from django.urls import reverse
3
+ from territories_dashboard_lib.indicators_lib.enums import get_all_meshes
3
4
 
4
5
  register = template.Library()
5
6
 
@@ -28,3 +29,10 @@ def indicator_api_urls(indicator_dict):
28
29
  )
29
30
  for view_name in view_names
30
31
  }
32
+
33
+
34
+ @register.filter
35
+ def should_mesh_analysis(params, indicator):
36
+ meshes = get_all_meshes()
37
+ above_min_mesh = meshes.index(params["mesh"]) <= meshes.index(indicator["min_mesh"])
38
+ return above_min_mesh
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: territories-dashboard-lib
3
- Version: 0.1.3
3
+ Version: 0.1.4
4
4
  Summary: Librairie pour la visualisation d'indicateurs territoriaux.
5
5
  Author-email: Bastien <bastien@prune.sh>
6
6
  License: LICENCE OUVERTE 2.0/OPEN LICENCE 2.0
@@ -85,20 +85,122 @@ Classifier: License :: Other/Proprietary License
85
85
  Requires-Python: >=3.13
86
86
  Description-Content-Type: text/markdown
87
87
 
88
- # territories-dashboard-lib
88
+ # Tableau de bord des indicateurs territoriaux
89
89
 
90
- **Librairie Python pour créer rapidement un dashboard d'indicateurs territoriaux.**
90
+ ## Présentation
91
91
 
92
- Cette librairie permet d’analyser facilement des indicateurs sur un territoire donné, ou bien de se concentrer sur un indicateur spécifique pour une analyse détaillée.
92
+ Bienvenue dans ce projet visant à faciliter la création de tableaux de bord territoriaux interactifs à partir de données d’indicateurs. Ce dispositif est composé de deux briques complémentaires :
93
93
 
94
- ## Fonctionnalités
94
+ ### 1. `territories_dashboard_lib`
95
95
 
96
- - Création rapide de dashboards interactifs
97
- - Vue globale par territoire ou focus par indicateur
98
- - Pensée pour les projets liés à l’aménagement, à la planification ou à l’analyse territoriale
96
+ Une **librairie Django** réutilisable, contenant des applications modulaires pour afficher rapidement un tableau de bord d'indicateurs territoriaux. Elle permet d’analyser des données à différentes mailles géographiques : nationale, régionale, départementale, et communale.
97
+ Elle comprend des fonctionnalités prêtes à l'emploi pour visualiser des données sur des thématiques comme la **mobilité durable**, la **rénovation énergétique** ou d'autres indicateurs liés au développement territorial.
99
98
 
100
- ## 🔧 Installation
99
+ ### 2. `territories_dashboard_template`
101
100
 
102
- ```bash
103
- pip install territories-dashboard-lib
101
+ Un **template de projet Django clef en main**, conçu pour permettre à des équipes techniques de démarrer rapidement leur propre tableau de bord. Ce template utilise la librairie `territories_dashboard_lib` comme fondation.
102
+ Les utilisateurs peuvent cloner ce dépôt, l’adapter à leurs besoins, et configurer leur tableau de bord directement depuis l’interface d’administration (titre, organisme, pages de contenu statique, indicateurs à afficher...).
103
+
104
+ Le template constitue un **point de départ standard**, mais n’impose aucune restriction technique en dehors du choix de Django comme framework. Les développeurs sont libres d'étendre ou de modifier les composants selon leurs besoins.
105
+
106
+ ### Prérequis
107
+
108
+ Pour utiliser la librairie ou le template, vous devez disposer de :
109
+
110
+ - Une base de données PostgreSQL contenant les données des indicateurs territoriaux.
111
+ - Une capacité à déployer une application Django (hébergement, serveur web, etc.).
112
+
113
+ Pour obtenir des informations détaillées sur les prérequis techniques ou les données :
114
+
115
+ - **Marina Ribeiro** – Directrice de projet Mission Connaissance
116
+ marina.ribeiro@developpement-durable.gouv.fr
117
+ - **Louise Columelli** – ECOLAB
118
+ louise.columelli@developpement-durable.gouv.fr
119
+ - **Olivier Rousseau** – Expert données
120
+ olivier.rousseau@i-carre.net
121
+ - **Bastien** – Développeur web
122
+ bastien@prune.sh
123
+
124
+ ### Exemples de projets utilisant ce dispositif
125
+
126
+ - [Tableau de bord des mobilités durables](https://mobilite-durable-tdb.din.developpement-durable.gouv.fr)
127
+ - [Boussole énergétique de la rénovation des logements](https://boussole-renovation.din.developpement-durable.gouv.fr)
128
+
129
+ L’objectif de ce projet est d’**encourager la réutilisation** et l’**essaimage** de nouveaux tableaux de bord territoriaux, en mettant à disposition un socle technique commun, facilement adaptable et extensible.
130
+
131
+ ## Structure de la librairie
132
+
133
+ La librairie est composée de plusieurs **applications Django** indépendantes et complémentaires :
134
+
135
+ ### `website_lib`
136
+
137
+ Contient le code principal d’affichage des pages du tableau de bord :
138
+
139
+ - **Templates HTML Django** : dans `website_lib/templates`, organisés par page.
140
+ - **Fichiers statiques** (JS, CSS) : dans `website_lib/static`. Le JS est modulaire grâce à l’extension `.mjs`.
141
+ - **Vues Django** : dans `website_lib/views`, associées aux templates et fichiers statiques.
142
+
143
+ ### `tracking_lib`
144
+
145
+ Gère le **tracking backend** : enregistrement en base de données des visites de pages, avec leurs paramètres (indicateur sélectionné, territoire, etc.) pour permettre des analyses d’usage.
146
+
147
+ ### `superset_lib`
148
+
149
+ Permet d’**intégrer des dashboards Superset** dans les pages du site.
150
+ Superset est un outil permettant à des utilisateurs non techniques de construire des visualisations depuis une base de données.
151
+
152
+ ### `geo_lib`
153
+
154
+ Permet d’**ajouter des couches géographiques** personnalisées (points, lignes, polygones) à la carte :
155
+
156
+ - Points : ex. stationnements vélo.
157
+ - Lignes : ex. pistes cyclables.
158
+ - Polygones : ex. zones ZFE.
159
+
160
+ ### `indicators_lib`
161
+
162
+ Contient le code pour l’accès et la requête des **données d’indicateurs** dans la base PostgreSQL dédiée.
163
+
164
+ ### Composants React
165
+
166
+ Certaines visualisations complexes sont développées en **React** (ex. cartes interactives, diagrammes de Sankey).
167
+
168
+ - Les composants sont dans `website_lib/react-components/`.
169
+ - Le bundling est effectué via **Webpack**
170
+ - Les composants React sont ensuite inclus dans les templates Django.
171
+ - `cd website_lib/react-components && npm install && npm run webpack`
172
+
173
+ ## Installation
174
+
175
+ La librairie est publiée sur PyPI. Elle s’installe dans un projet Django via le package manager uv :
176
+
177
+ `uv add territories_dashboard_lib`
178
+
179
+ ### Figer la version en production
180
+
181
+ Pour éviter les mises à jour inattendues, il est conseillé de figer la version dans le fichier pyproject.toml :
182
+
183
+ ```
184
+ # Par exemple :
185
+ territories_dashboard_lib == 1.0.3
104
186
  ```
187
+
188
+ ### Développement local
189
+
190
+ Pour tester une version locale de la librairie (ex : modifications en cours) :
191
+
192
+ `uv add --editable ~/territories-dashboard/territories-dashboard-lib`
193
+
194
+ ## Publication PyPI
195
+
196
+ Pour builder la librairie avant publication :
197
+
198
+ `uv run python -m build`
199
+
200
+ Pour déployer sur PyPI, vous devez :
201
+
202
+ 1. Avoir un compte PyPI.
203
+
204
+ 2. Être membre du projet sur PyPI.
205
+
206
+ 3. Lancer : `uv run twine upload dist/*`
@@ -12,24 +12,25 @@ territories_dashboard_lib/geo_lib/migrations/0001_initial.py,sha256=-H_5uG0IaPes
12
12
  territories_dashboard_lib/geo_lib/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  territories_dashboard_lib/indicators_lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
14
  territories_dashboard_lib/indicators_lib/admin.py,sha256=IhmZEYuxt0WCr8rDjc6Iht-uOL7gRgDQNYjq6B0_uaI,4057
15
- territories_dashboard_lib/indicators_lib/enums.py,sha256=0HZcKtq97AbV2hbPPn7_BtUtSefp5EvgvTWhqx6rn3o,1267
15
+ territories_dashboard_lib/indicators_lib/enums.py,sha256=Azv-3O9M8UvP5Mx_N75Fa7PDayEviD4Qdgdrkk_x8GU,1843
16
16
  territories_dashboard_lib/indicators_lib/export.py,sha256=bvrqa2K4aSw17JWF-P2sGBryeab2JZjoE25Ntf68dIk,859
17
17
  territories_dashboard_lib/indicators_lib/format.py,sha256=W-ajQjrH6E2mseSq4Lozl0bhmEq481tGFIGsjYS8MMo,891
18
18
  territories_dashboard_lib/indicators_lib/methodo_pdf.py,sha256=LpDHMFSNavvfJOI7gDicdY7uF27JpUd-ceUMnOY_FNU,2920
19
- territories_dashboard_lib/indicators_lib/models.py,sha256=xTi4_Exoc9AdBICRCpN2oLhZPiRdCwa9GX8bo1xb1GQ,8058
19
+ territories_dashboard_lib/indicators_lib/models.py,sha256=9f8XmM_WDuIjQTF9V3p3BAqRS0hlbLJjWTGOW5Kdp_4,8323
20
20
  territories_dashboard_lib/indicators_lib/payloads.py,sha256=I03bgoNoLTehd8lfby0xbSy2zUXKRILMUOqYGqvg-Ig,1288
21
- territories_dashboard_lib/indicators_lib/refresh_filters.py,sha256=loO3Iw97AAWnwQnkRg77q1zUPU7kY5mGlkTCe_glKzs,654
21
+ territories_dashboard_lib/indicators_lib/refresh_filters.py,sha256=uPdKKcCtfwQL2QoGXtRcZcxagYpVv2yiiiTTsCYaXEI,652
22
22
  territories_dashboard_lib/indicators_lib/table.py,sha256=BsvimE68NxXdRI7xnUVYK1axZRZTywVpSUDEtAYWlMo,5332
23
23
  territories_dashboard_lib/indicators_lib/urls.py,sha256=BrizGcGJzvcijMvkImMzsi4zRzsgw4fl_cIScsfDYcU,2482
24
24
  territories_dashboard_lib/indicators_lib/views.py,sha256=NH-Mppel-A5eT0gxbdfnU0B5UT1RZTSW1kIn8q7_zrs,16755
25
25
  territories_dashboard_lib/indicators_lib/migrations/0001_initial.py,sha256=3EyizMGkqve5Gtxrmf-mADzzmOhcAVWe-P0y1TIBKCs,8092
26
+ territories_dashboard_lib/indicators_lib/migrations/0002_filter_color_indicator_min_mesh_and_more.py,sha256=Lz6_UVKLAmaRT-OskwbTMh3PjIh0k4BaGyIOHCC8zMI,884
26
27
  territories_dashboard_lib/indicators_lib/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
- territories_dashboard_lib/indicators_lib/query/commons.py,sha256=6UlN7lYArYt2BKPaweBMtfwUg2cZtl3UCEHb9ecWmjA,7838
28
+ territories_dashboard_lib/indicators_lib/query/commons.py,sha256=ikZRa8-VvP5oyZT8Zv4ejvvlHGZjBwPgo9F8HxgMW8I,7885
28
29
  territories_dashboard_lib/indicators_lib/query/comparison.py,sha256=ypT8jed99NubgBWqsjZ_4vs9xX2rArnxeGFQ2IY3cKM,2540
29
- territories_dashboard_lib/indicators_lib/query/details.py,sha256=NHFO3yat7kRtxsuEuOUAgt0yuMzAVVAumzI2auxffSg,2277
30
+ territories_dashboard_lib/indicators_lib/query/details.py,sha256=si43KVB5QxgQTc9c6AJZ04EK8zPSag9NPfiril9Fv0k,2476
30
31
  territories_dashboard_lib/indicators_lib/query/histogram.py,sha256=NpQdAqVzm-bB5AuMZF3jOzEJKLjecwafhlorkYQY6IU,2964
31
32
  territories_dashboard_lib/indicators_lib/query/indicator_card.py,sha256=pu-oGTQ8-niIFtZP09HIgJJWkFfJb1CGX99EdsojJDw,3232
32
- territories_dashboard_lib/indicators_lib/query/top_10.py,sha256=ugx2FD9_IHyaZHkOS0rEDxy3L-dE-F_Gl8sRsQPu2qw,3516
33
+ territories_dashboard_lib/indicators_lib/query/top_10.py,sha256=3eDBd5w1ovfaMOyN3JQ5mYxBSUrcRJjR1i0v7HG04o4,3677
33
34
  territories_dashboard_lib/indicators_lib/query/utils.py,sha256=nCeQCLzfq35KZzun9hpM5U34TN7JowB4t3NshIzfLAo,649
34
35
  territories_dashboard_lib/superset_lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
36
  territories_dashboard_lib/superset_lib/admin.py,sha256=3Yj3PjCd-jC0g4uMNmah-OST-yoE7DDEzJkx2kWlrXg,563
@@ -51,13 +52,14 @@ territories_dashboard_lib/website_lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCe
51
52
  territories_dashboard_lib/website_lib/admin.py,sha256=TUDxtX3O-ga33jvSowX6HMBHxdqprM9-nSFmsZ2m6Bk,876
52
53
  territories_dashboard_lib/website_lib/context_processors.py,sha256=Xq9W_w86Oh242VSGAjScHlgpnXuNcnNt3kSRIqK-ETc,863
53
54
  territories_dashboard_lib/website_lib/forms.py,sha256=BNbHx6CgMlA33z6eD-1VaI7AkyO20ZsloJKsec4BcoU,1146
54
- territories_dashboard_lib/website_lib/models.py,sha256=bsvSKXSQJaG5oKcXqRNN3rC5Ra8M3uZhqou4FkjgAcI,4750
55
+ territories_dashboard_lib/website_lib/models.py,sha256=aVBsVL6H3_H6J9UFLBT6PJ4Fs-qTsmqR219F_5XriRE,5336
55
56
  territories_dashboard_lib/website_lib/navigation.py,sha256=D9YNfBVPpO9bRgNT02j99sp0A0_uqDaBgc25BbQOako,3994
56
- territories_dashboard_lib/website_lib/params.py,sha256=xmROBlWVv-T8ABTGaGEEuJjFan50yq44iwLYAn5Hzh8,9466
57
- territories_dashboard_lib/website_lib/serializers.py,sha256=-QvQx0jpbGaBrHcrqLG0Lrb9z4TRIu6VbxOqSfWKtHo,3680
57
+ territories_dashboard_lib/website_lib/params.py,sha256=M7a3SsLpFiGsPlHy9hOzbwvnWRGyOHSCeDLym70gFTA,10067
58
+ territories_dashboard_lib/website_lib/serializers.py,sha256=PVcOC52zlNn2tp7IRwMuB4T7rOaLl3bLKiqqesWgRE4,3772
58
59
  territories_dashboard_lib/website_lib/static_content.py,sha256=08Fw3190RsTZ8wXwZkmskh-86widq7NRmTD9Ve-9PJY,589
59
60
  territories_dashboard_lib/website_lib/views.py,sha256=ZNz23Vrws-L49xeZzrhSJA8KFpqSnURn-9-b0RdR9JE,6760
60
61
  territories_dashboard_lib/website_lib/migrations/0001_initial.py,sha256=4g2YgUUBEdak_iW717cJojCv5kqnNV_46GVnw8u8eAw,5701
62
+ territories_dashboard_lib/website_lib/migrations/0002_mainconf_contact_email_mainconf_newsletter_link_and_more.py,sha256=HJbz8w63SGhPwBNCqPJXFMuepkHfImgnmqRe3gQ3W8g,1052
61
63
  territories_dashboard_lib/website_lib/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
64
  territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/css/website.css,sha256=IgpMQ-sgR5TORylFowRZEheQdR-2v-gUPWh2jiUcluw,20013
63
65
  territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/chart.js,sha256=qKg5SGiIDybjFd0WYySXtFROPHmdJVENEIatEXIQv34,205577
@@ -74,7 +76,7 @@ territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/j
74
76
  territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/filters.mjs,sha256=RGlAwpsWn0x6VwIDIp4tdQYBIRsHpQhh1L6ysXHxxoI,5591
75
77
  territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/format.mjs,sha256=Iqp5x9U_LxyYjOvIseNn5iJYjr_a3jRd5AMhq5pUEjc,1472
76
78
  territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/side_panel.mjs,sha256=DMs8ZHONVfjmbblfpvlGl4Bg0hLrEUBK7Hv6U1vEZ2E,3463
77
- territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/utils.mjs,sha256=ud00kXSdx3ODXnf51f14tSm_lRMmj7AjIk9In_J-Id0,2658
79
+ territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/utils.mjs,sha256=N_mgAsyvgvYttC30hVpHcaXi7zBhM3i_s6xsRFcgJAQ,2626
78
80
  territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/comparaison/data.mjs,sha256=tt5MzRwqMNqKUL1UDI9ueVVPAo2kLsnsrFnGdoW0xUg,1953
79
81
  territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/comparaison/history.mjs,sha256=-4X6QlRa-4Z0lAzt66pC-lgxkhH2lKtectfuZoIkXXE,2789
80
82
  territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/pages/indicators/comparaison/main-values.mjs,sha256=SwrhsRc1HSv7hUKmUCpxmMj3CDMOGMkylP0-Sdy8l6Q,976
@@ -102,12 +104,13 @@ territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/websit
102
104
  territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/500.html,sha256=zKtoQpzH_wOlNe_COwXANZR4lIV5DnZgcuymezmdk0g,278
103
105
  territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/base.html,sha256=jZu1inonZam6OKcyrB5C3jFpJD_5UGccWiZb3I4MbtQ,1619
104
106
  territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/base.js,sha256=IHW3YF3451k-G7GjZieQ7sBaRPezNK5TYt1WV_qF5OY,1624
105
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/footer.html,sha256=zjjegNRsJP6IE1XHKexu9Qlnj4wnQdG80ieCxFmGn_s,6025
107
+ territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/footer.html,sha256=I_JyfoVq1IZi9ESZA8C4nlYiJgIVYShy3L-rVioI5NA,6124
106
108
  territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/header.html,sha256=fiGqMzN3Pk6QpqCIWOhxtg-6O7UDUOHnS7p3TXmLgyw,4928
107
109
  territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/header.js,sha256=3UX-TtbTD2lHaabcMIX2SeFq0WksDevJxZnrwBdhWkE,2949
108
110
  territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/page.html,sha256=X2uo97996uXj2hdn9IYWutFOrawUND8E1uASGMhJekI,456
109
111
  territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/comparaison/[theme]/page.html,sha256=I7XyxwQPZcNDMOJMmQUnzMlDd5IR2BDKn3MjT9gFPO0,2760
110
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/comparaison/[theme]/components/indicateur-card.html,sha256=y3xxbpHM1lVzoY7JUoVeoNmVWvp_FtA75oqVugi71sk,3136
112
+ territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/comparaison/[theme]/components/histogram.html,sha256=VFk45v4GNmpCC2qdZoRk8re74EfemrXjo9CHlA6iZ4o,1893
113
+ territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/comparaison/[theme]/components/indicateur-card.html,sha256=aZ4VntbuaK60uPWcCorm0-gGVlf2P89mEoal0XvdApo,1372
111
114
  territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/chart-buttons.html,sha256=GSQR2xlLqiZLDW7qhV0IkcMOVN93MR6mk4yy0nwpmB0,1400
112
115
  territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/geo_params.html,sha256=IBCCs_NlbDAIfZhEkIBy-DC648_YsBvwr1VBgVl1LGM,2761
113
116
  territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/indicator-card.html,sha256=jezeF9mJ1u0Ebm7wQdonEovFquPpFYINAEXoh7eWj3Y,2360
@@ -120,20 +123,28 @@ territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/websit
120
123
  territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/themes-list.html,sha256=nCpa4M6EUoVNSnXVK9SflY6-02Z2C8u3j_MzI_rUjns,320
121
124
  territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/themes-nav.html,sha256=-UECnGre6uAOiScRqWu_c_wX6Oxvpx-dsZWDMy-uSLQ,1827
122
125
  territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/components/title.html,sha256=GNtdGyUM9gvoGcjS8oNOYw1nqyojHJBTnnnKbDAxFDE,841
123
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/page.html,sha256=LuYNBAzFZiF8hEKO84M3LSxFOe2NN-1dhokeH4a-qqs,11482
126
+ territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/page.html,sha256=7Llw34GvsfBvoRLCCE2SD96OZ6VXer9Tac5YbAyFeOk,6661
124
127
  territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/components/filters-reminder.html,sha256=81qfB3XETr2XUAGxNCxwhSepsDjrjnnnK0_hZwAxp7Q,888
128
+ territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/components/histogram.html,sha256=iHHrHUD7uVzITuXt8EYLgHW-I-PJcWnXytRMz5oOZF0,1269
129
+ territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/components/map.html,sha256=wfpg7QDNlakNw1mEcYuF1kydWZIDpDqh5OSBQzdxP94,316
130
+ territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/components/proportions.html,sha256=OHKWYkdGO2XGyS52tYRoh9HkUi-5n1NyRRdZ3g20zdk,1320
131
+ territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/components/sankey.html,sha256=Br3RbCLS5ueJeyB1wgJ-QY2hVPnQ5upwpdasFz8IilQ,1068
132
+ territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/components/table-flows.html,sha256=aWHuBN6cxTMnnIuPJZcp3b3qmTRgHLJwXKZX_ek4c2U,275
133
+ territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/components/table-values.html,sha256=MhriM8hceVmkLJvmMulBp-dCYnO0ncH0bjSxoq5wOUU,633
125
134
  territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/components/table.html,sha256=Js05L7L_ULxap4ep6uVUEup4fXGWmZi9Uwc4Y-6nTO0,6751
135
+ territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/details/components/top10.html,sha256=LNjHPCbqz9hTCNLMvZQnicob6PpF499homEwaHnZOOY,1216
126
136
  territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/themes/page.html,sha256=7RZ5fBxF3coD-tmUBARLoAoXbvEoLGYp5MmdscMOCq4,3354
127
137
  territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/themes/components/extremum.html,sha256=q_Edf7cb3EnC_prU2MzF8M1fnlqbYNTfQk92H1SxJEc,830
128
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/themes/components/indicateur-card.html,sha256=inIZnKJxNPeONyeX6HZyP4WICBUstcMMn0w3NuBnQjQ,3842
138
+ territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/themes/components/indicateur-card.html,sha256=hfZv_0mj-WX3Ekt-InrCS6FCscAPAGlibGaNP5HT4dQ,3626
139
+ territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/indicators/themes/components/stats.html,sha256=3Kn9FqfEFUXGuhMpMxBDmO6KifHYdaaAc2Tg8X9TUzc,585
129
140
  territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/lexique/page.html,sha256=Y7J0RA339I-j_0gDeO-t1MgX7Xalz7VMbZCE1Pk6gec,542
130
141
  territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/sitemap/page.html,sha256=cP9BWq8eLpfS6jVwFcrhFy5-cJ55iGmsJLoGXwArZCM,1797
131
142
  territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/static/page.html,sha256=6x1zpJ_gLA7se-DfC9bf-9hYubAHP_wBjaORuzJHFSk,483
132
143
  territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/pages/superset/page.html,sha256=mqcmgTTutZWEhuldm558SW4TpvZphe6MSL3VnM13WgM,1641
133
144
  territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/svg/delete-back.svg,sha256=fJPjkZT2jdTcW2nmwr7YtBayOmQKOxiGNyO8bM8jP2U,618
134
145
  territories_dashboard_lib/website_lib/templatetags/htmlparams.py,sha256=jWXlmT-nFh7YefVP_zJSXEA1YgT37wnWqelPhmj7UoM,2092
135
- territories_dashboard_lib/website_lib/templatetags/other_filters.py,sha256=7jcQB8LmnlrDycLyRYuOA62O9nBHROCvogOpegdrarY,661
136
- territories_dashboard_lib-0.1.3.dist-info/METADATA,sha256=VOP1eVBJumuN4ADG1ECIg2IgXhgAilTu_eLYbpUvwG4,9518
137
- territories_dashboard_lib-0.1.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
138
- territories_dashboard_lib-0.1.3.dist-info/top_level.txt,sha256=Cih-lil8CSXTpDZV6fgHKIKIBtUjDaNpmkiuW2TSzsk,26
139
- territories_dashboard_lib-0.1.3.dist-info/RECORD,,
146
+ territories_dashboard_lib/website_lib/templatetags/other_filters.py,sha256=EEczSQi8lJZ_rfceuXQz3iF1SIxh5d-3-liTY8lkKtU,944
147
+ territories_dashboard_lib-0.1.4.dist-info/METADATA,sha256=-84ezEcVQ-JPRqqHTWn6vhzhKbPKrmsuIpLXZPMLBkQ,14212
148
+ territories_dashboard_lib-0.1.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
149
+ territories_dashboard_lib-0.1.4.dist-info/top_level.txt,sha256=Cih-lil8CSXTpDZV6fgHKIKIBtUjDaNpmkiuW2TSzsk,26
150
+ territories_dashboard_lib-0.1.4.dist-info/RECORD,,