territories-dashboard-lib 0.1.20__py3-none-any.whl → 0.1.21__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/types.py +20 -0
- territories_dashboard_lib/geo_lib/payloads.py +65 -0
- territories_dashboard_lib/geo_lib/views.py +19 -37
- territories_dashboard_lib/indicators_lib/payloads.py +7 -5
- territories_dashboard_lib/indicators_lib/query/commons.py +4 -38
- territories_dashboard_lib/indicators_lib/query/indicator_card.py +0 -11
- territories_dashboard_lib/indicators_lib/query/top_10.py +2 -0
- territories_dashboard_lib/indicators_lib/table.py +9 -9
- territories_dashboard_lib/indicators_lib/views.py +14 -12
- territories_dashboard_lib/superset_lib/payloads.py +7 -0
- territories_dashboard_lib/superset_lib/views.py +4 -2
- territories_dashboard_lib/website_lib/context_processors.py +1 -0
- territories_dashboard_lib/website_lib/migrations/0004_mainconf_description_mainconf_social_image_url.py +23 -0
- territories_dashboard_lib/website_lib/models.py +12 -0
- territories_dashboard_lib/website_lib/params.py +3 -0
- territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/base.html +11 -0
- {territories_dashboard_lib-0.1.20.dist-info → territories_dashboard_lib-0.1.21.dist-info}/METADATA +2 -2
- {territories_dashboard_lib-0.1.20.dist-info → territories_dashboard_lib-0.1.21.dist-info}/RECORD +21 -17
- {territories_dashboard_lib-0.1.20.dist-info → territories_dashboard_lib-0.1.21.dist-info}/WHEEL +0 -0
- {territories_dashboard_lib-0.1.20.dist-info → territories_dashboard_lib-0.1.21.dist-info}/licenses/licence.md +0 -0
- {territories_dashboard_lib-0.1.20.dist-info → territories_dashboard_lib-0.1.21.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from typing import Annotated
|
|
2
|
+
|
|
3
|
+
from pydantic import StringConstraints
|
|
4
|
+
|
|
5
|
+
TerritoryCode = Annotated[
|
|
6
|
+
str, StringConstraints(strip_whitespace=True, pattern=r"^[A-Za-z0-9]*$")
|
|
7
|
+
]
|
|
8
|
+
|
|
9
|
+
# comme un TerritoryCode mais prend en compte l'exception pour la France entière : territory=FR0,FR1,FR2-fr
|
|
10
|
+
MutualisedTerritoryCode = Annotated[
|
|
11
|
+
str, StringConstraints(strip_whitespace=True, pattern=r"^[A-Za-z0-9,]*$")
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
SQlName = Annotated[
|
|
15
|
+
str, StringConstraints(strip_whitespace=True, pattern=r"^[A-Za-z0-9_]*$")
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
SimpleIDType = Annotated[
|
|
19
|
+
str, StringConstraints(strip_whitespace=True, pattern=r"^[A-Za-z0-9_\-]*$")
|
|
20
|
+
]
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from typing import List, Optional
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, field_validator
|
|
4
|
+
|
|
5
|
+
from territories_dashboard_lib.commons.types import TerritoryCode
|
|
6
|
+
from territories_dashboard_lib.indicators_lib.enums import (
|
|
7
|
+
GeoLevel,
|
|
8
|
+
MeshLevel,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class GeoFeaturesParams(BaseModel):
|
|
13
|
+
mesh: MeshLevel
|
|
14
|
+
geo_level: GeoLevel
|
|
15
|
+
main_territories: List[TerritoryCode]
|
|
16
|
+
last: Optional[int] = None
|
|
17
|
+
limit: Optional[int] = 1000
|
|
18
|
+
feature: int
|
|
19
|
+
|
|
20
|
+
@field_validator("main_territories", mode="before")
|
|
21
|
+
def split_main_territories(cls, v):
|
|
22
|
+
if isinstance(v, str):
|
|
23
|
+
return v.split(",")
|
|
24
|
+
return v
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class MainTerritoryParams(BaseModel):
|
|
28
|
+
geo_level: GeoLevel
|
|
29
|
+
geo_id: List[TerritoryCode]
|
|
30
|
+
|
|
31
|
+
@field_validator("geo_id", mode="before")
|
|
32
|
+
def split_main_territories(cls, v):
|
|
33
|
+
if isinstance(v, str):
|
|
34
|
+
return v.split(",")
|
|
35
|
+
return v
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class TerritoriesParams(BaseModel):
|
|
39
|
+
mesh: MeshLevel
|
|
40
|
+
territories: List[TerritoryCode]
|
|
41
|
+
|
|
42
|
+
@field_validator("territories", mode="before")
|
|
43
|
+
def split_main_territories(cls, v):
|
|
44
|
+
if isinstance(v, str):
|
|
45
|
+
return v.split(",")
|
|
46
|
+
return v
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class TerritoryFeatureParams(BaseModel):
|
|
50
|
+
mesh: MeshLevel
|
|
51
|
+
geo_level: GeoLevel | None = None
|
|
52
|
+
main_territories: List[TerritoryCode] | None = None
|
|
53
|
+
codes: List[TerritoryCode] | None = None
|
|
54
|
+
|
|
55
|
+
@field_validator("main_territories", "codes", mode="before")
|
|
56
|
+
def split_main_territories(cls, v):
|
|
57
|
+
if isinstance(v, str):
|
|
58
|
+
return v.split(",")
|
|
59
|
+
return v
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class SearchTerritoriesParams(BaseModel):
|
|
63
|
+
mesh: MeshLevel
|
|
64
|
+
search: str = ""
|
|
65
|
+
offset: int = 0
|
|
@@ -2,19 +2,23 @@ import base64
|
|
|
2
2
|
import datetime
|
|
3
3
|
import gzip
|
|
4
4
|
import json
|
|
5
|
-
from typing import Optional
|
|
6
5
|
|
|
7
6
|
from django.http import HttpResponse, JsonResponse
|
|
8
7
|
from django.shortcuts import get_object_or_404
|
|
9
8
|
from django.views.decorators.cache import cache_control
|
|
10
9
|
from django.views.decorators.http import require_GET
|
|
11
10
|
from psycopg2.sql import SQL, Identifier, Literal
|
|
12
|
-
from pydantic import BaseModel
|
|
13
11
|
|
|
12
|
+
from territories_dashboard_lib.geo_lib.payloads import (
|
|
13
|
+
GeoFeaturesParams,
|
|
14
|
+
MainTerritoryParams,
|
|
15
|
+
SearchTerritoriesParams,
|
|
16
|
+
TerritoriesParams,
|
|
17
|
+
TerritoryFeatureParams,
|
|
18
|
+
)
|
|
14
19
|
from territories_dashboard_lib.indicators_lib.enums import (
|
|
15
20
|
FRANCE_GEOLEVEL_TITLES,
|
|
16
21
|
MESH_DB,
|
|
17
|
-
GeoLevel,
|
|
18
22
|
MeshLevel,
|
|
19
23
|
)
|
|
20
24
|
from territories_dashboard_lib.indicators_lib.query.commons import get_territories_ids
|
|
@@ -24,15 +28,6 @@ from .enums import GeoFeatureType
|
|
|
24
28
|
from .models import GeoFeature
|
|
25
29
|
|
|
26
30
|
|
|
27
|
-
class GeoFeaturesParams(BaseModel):
|
|
28
|
-
mesh: MeshLevel
|
|
29
|
-
geo_level: GeoLevel
|
|
30
|
-
main_territories: str
|
|
31
|
-
last: Optional[str] = None
|
|
32
|
-
limit: Optional[str] = "1000"
|
|
33
|
-
feature: str
|
|
34
|
-
|
|
35
|
-
|
|
36
31
|
class DateTimeEncoder(json.JSONEncoder):
|
|
37
32
|
def default(self, obj):
|
|
38
33
|
if isinstance(obj, (datetime.date, datetime.datetime)):
|
|
@@ -52,7 +47,7 @@ def geo_features_view(request):
|
|
|
52
47
|
geo_feature = get_object_or_404(GeoFeature, id=params.feature)
|
|
53
48
|
geo_level = params.geo_level
|
|
54
49
|
mesh = params.mesh
|
|
55
|
-
main_territory_codes = params.main_territories
|
|
50
|
+
main_territory_codes = params.main_territories
|
|
56
51
|
last = params.last
|
|
57
52
|
limit = params.limit
|
|
58
53
|
|
|
@@ -94,6 +89,7 @@ def geo_features_view(request):
|
|
|
94
89
|
|
|
95
90
|
# Execute the query
|
|
96
91
|
results = run_custom_query(query)
|
|
92
|
+
|
|
97
93
|
items = geo_feature.items.all()
|
|
98
94
|
# Transform results
|
|
99
95
|
data = [
|
|
@@ -114,17 +110,12 @@ def geo_features_view(request):
|
|
|
114
110
|
return JsonResponse({"data": compressed_base64, "last": last_queried_order_id})
|
|
115
111
|
|
|
116
112
|
|
|
117
|
-
class MainTerritoryParams(BaseModel):
|
|
118
|
-
geo_level: GeoLevel
|
|
119
|
-
geo_id: str
|
|
120
|
-
|
|
121
|
-
|
|
122
113
|
@require_GET
|
|
123
114
|
@cache_control(max_age=3600)
|
|
124
115
|
def main_territory_view(request):
|
|
125
116
|
params = MainTerritoryParams(**request.GET.dict())
|
|
126
117
|
|
|
127
|
-
codes = ", ".join(f"'{code.strip()}'" for code in params.geo_id
|
|
118
|
+
codes = ", ".join(f"'{code.strip()}'" for code in params.geo_id)
|
|
128
119
|
|
|
129
120
|
query = f"""
|
|
130
121
|
SELECT code as id, ST_asgeojson(ST_simplify(geometry, 0.01)) AS polygon
|
|
@@ -148,8 +139,9 @@ def main_territory_view(request):
|
|
|
148
139
|
@require_GET
|
|
149
140
|
@cache_control(max_age=3600)
|
|
150
141
|
def precise_view(request):
|
|
151
|
-
|
|
152
|
-
mesh_level =
|
|
142
|
+
params = TerritoriesParams(**request.GET.dict())
|
|
143
|
+
mesh_level = params.mesh
|
|
144
|
+
territories_ids = params.territories
|
|
153
145
|
|
|
154
146
|
if not mesh_level:
|
|
155
147
|
return JsonResponse({"error": "Missing 'mesh' parameter"}, status=400)
|
|
@@ -169,13 +161,6 @@ def precise_view(request):
|
|
|
169
161
|
return JsonResponse(territories)
|
|
170
162
|
|
|
171
163
|
|
|
172
|
-
class TerritoryFeatureParams(BaseModel):
|
|
173
|
-
mesh: MeshLevel
|
|
174
|
-
geo_level: GeoLevel | None = None
|
|
175
|
-
main_territories: str | None = None
|
|
176
|
-
codes: str | None = None
|
|
177
|
-
|
|
178
|
-
|
|
179
164
|
@require_GET
|
|
180
165
|
@cache_control(max_age=3600)
|
|
181
166
|
def territories_view(request):
|
|
@@ -184,9 +169,9 @@ def territories_view(request):
|
|
|
184
169
|
mesh = params.mesh
|
|
185
170
|
|
|
186
171
|
if params.codes:
|
|
187
|
-
territories_ids = params.codes
|
|
172
|
+
territories_ids = params.codes
|
|
188
173
|
else:
|
|
189
|
-
main_territory_codes = params.main_territories
|
|
174
|
+
main_territory_codes = params.main_territories
|
|
190
175
|
territories_ids = get_territories_ids(main_territory_codes, geo_level, mesh)
|
|
191
176
|
|
|
192
177
|
query = f"""
|
|
@@ -212,11 +197,10 @@ def _fill_territory_li(code, name, mesh):
|
|
|
212
197
|
@require_GET
|
|
213
198
|
@cache_control(max_age=3600)
|
|
214
199
|
def search_territories_view(request):
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
raise ValueError("mesh")
|
|
200
|
+
params = SearchTerritoriesParams(**request.GET.dict())
|
|
201
|
+
mesh = params.mesh
|
|
202
|
+
search = params.search
|
|
203
|
+
offset = params.offset
|
|
220
204
|
if mesh == MeshLevel.National:
|
|
221
205
|
lis = []
|
|
222
206
|
for code, name in FRANCE_GEOLEVEL_TITLES.items():
|
|
@@ -225,8 +209,6 @@ def search_territories_view(request):
|
|
|
225
209
|
return HttpResponse("\n".join(lis))
|
|
226
210
|
mesh_db = MESH_DB[mesh]
|
|
227
211
|
pagination = 20
|
|
228
|
-
search = request.GET.get("search", "")
|
|
229
|
-
offset = int(request.GET.get("offset", 0))
|
|
230
212
|
query = SQL("""
|
|
231
213
|
SELECT DISTINCT {code} as code, {name} as name FROM arborescence_geo
|
|
232
214
|
WHERE unaccent({name}) || {code} ILIKE unaccent(%s)
|
|
@@ -2,11 +2,13 @@ from typing import Annotated, Optional
|
|
|
2
2
|
|
|
3
3
|
from pydantic import BaseModel, BeforeValidator, Field
|
|
4
4
|
|
|
5
|
+
from territories_dashboard_lib.commons.types import MutualisedTerritoryCode, SQlName
|
|
6
|
+
|
|
5
7
|
from .enums import MeshLevel
|
|
6
8
|
|
|
7
9
|
|
|
8
10
|
class Territory(BaseModel):
|
|
9
|
-
id:
|
|
11
|
+
id: MutualisedTerritoryCode
|
|
10
12
|
mesh: MeshLevel
|
|
11
13
|
|
|
12
14
|
|
|
@@ -24,8 +26,8 @@ class SubMeshPayload(BasePayload):
|
|
|
24
26
|
|
|
25
27
|
|
|
26
28
|
class FlowsPayload(SubMeshPayload):
|
|
27
|
-
prefix:
|
|
28
|
-
dimension:
|
|
29
|
+
prefix: SQlName
|
|
30
|
+
dimension: SQlName | None = None
|
|
29
31
|
|
|
30
32
|
|
|
31
33
|
class ComparisonQueryPayload(SubMeshPayload):
|
|
@@ -43,8 +45,8 @@ class OptionalComparisonQueryPayload(SubMeshPayload):
|
|
|
43
45
|
|
|
44
46
|
|
|
45
47
|
class IndicatorTablePayload(SubMeshPayload):
|
|
46
|
-
column_order:
|
|
47
|
-
column_order_flow:
|
|
48
|
+
column_order: SQlName | None = None
|
|
49
|
+
column_order_flow: SQlName | None = None
|
|
48
50
|
pagination: int = 1
|
|
49
51
|
limit: int = 20
|
|
50
52
|
previous_limit: int | None = None
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
from ..enums import (
|
|
2
|
-
DEFAULT_MESH,
|
|
3
2
|
FRANCE_DB_VALUES,
|
|
4
|
-
GeoLevel,
|
|
5
3
|
MeshLevel,
|
|
6
|
-
get_miminum_mesh,
|
|
7
4
|
)
|
|
8
5
|
from ..models import AggregationFunctions, Indicator
|
|
9
6
|
from .utils import get_breakdown_dimension, run_custom_query
|
|
@@ -112,9 +109,13 @@ def get_table_data_for_geography(
|
|
|
112
109
|
|
|
113
110
|
|
|
114
111
|
def calculate_aggregate_values(indicator, with_alternative=True):
|
|
112
|
+
# TODO coverage tester avec un indicateur de cette sorte
|
|
113
|
+
# Bastien doit exporter des nouvelles données pour faire le test
|
|
115
114
|
if not indicator.is_composite:
|
|
116
115
|
return "SUM(valeur) as valeur"
|
|
117
116
|
|
|
117
|
+
# TODO coverage tester avec un indicateur de cette sorte
|
|
118
|
+
# Bastien doit exporter des nouvelles données pour faire le test
|
|
118
119
|
if indicator.aggregation_function == AggregationFunctions.DISCRETE_COMPONENT_2:
|
|
119
120
|
sql = f"SUM(composante_1) / COALESCE(NULLIF(SUM(composante_2), 0), 1) * {indicator.aggregation_constant} as valeur"
|
|
120
121
|
if with_alternative:
|
|
@@ -132,41 +133,6 @@ def calculate_aggregate_values(indicator, with_alternative=True):
|
|
|
132
133
|
return sql
|
|
133
134
|
|
|
134
135
|
|
|
135
|
-
def order_filters(filters, bo_ordered_filters):
|
|
136
|
-
# Filters that exist in the predefined order
|
|
137
|
-
ordered_filters = [filter for filter in bo_ordered_filters if filter in filters]
|
|
138
|
-
|
|
139
|
-
# Filters that are not in the predefined order, sorted alphabetically
|
|
140
|
-
not_in_bo = sorted(
|
|
141
|
-
[item for item in filters if item not in bo_ordered_filters],
|
|
142
|
-
key=lambda x: x.lower(), # Case-insensitive alphabetical sort
|
|
143
|
-
)
|
|
144
|
-
|
|
145
|
-
# Combine both lists
|
|
146
|
-
final_array = ordered_filters + not_in_bo
|
|
147
|
-
return final_array
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
def get_mesh_level_for_geo_level(mesh, submesh):
|
|
151
|
-
if mesh == GeoLevel.Region:
|
|
152
|
-
return (
|
|
153
|
-
MeshLevel.Department
|
|
154
|
-
if submesh is None or submesh in [MeshLevel.National, MeshLevel.Region]
|
|
155
|
-
else submesh
|
|
156
|
-
)
|
|
157
|
-
elif mesh == GeoLevel.Department:
|
|
158
|
-
return (
|
|
159
|
-
MeshLevel.Epci
|
|
160
|
-
if submesh is None
|
|
161
|
-
or submesh in [MeshLevel.National, MeshLevel.Region, MeshLevel.Department]
|
|
162
|
-
else submesh
|
|
163
|
-
)
|
|
164
|
-
elif mesh in [GeoLevel.Epci, GeoLevel.Town]:
|
|
165
|
-
return get_miminum_mesh()
|
|
166
|
-
else:
|
|
167
|
-
return submesh or DEFAULT_MESH
|
|
168
|
-
|
|
169
|
-
|
|
170
136
|
def get_territories_ids(main_territory_codes, territory_mesh, submesh):
|
|
171
137
|
mapped_territory_mesh = (
|
|
172
138
|
"DEPCOM" if territory_mesh == "com" else territory_mesh.upper()
|
|
@@ -68,17 +68,6 @@ def get_geography_statistics_values_for_indicator(
|
|
|
68
68
|
return query
|
|
69
69
|
|
|
70
70
|
|
|
71
|
-
def get_indicator_filters(indicator):
|
|
72
|
-
if not indicator.db_table_prefix or not indicator.dimension:
|
|
73
|
-
return None
|
|
74
|
-
|
|
75
|
-
# Get the possible indicator's dimension's values
|
|
76
|
-
query = f"""
|
|
77
|
-
SELECT DISTINCT({indicator.dimension}) as filter FROM "{indicator.db_table_prefix}_reg"
|
|
78
|
-
"""
|
|
79
|
-
return query
|
|
80
|
-
|
|
81
|
-
|
|
82
71
|
def get_names_from_codes(dict_result, submesh):
|
|
83
72
|
codes_to_fetch = []
|
|
84
73
|
for key, value in dict_result.items():
|
|
@@ -77,6 +77,8 @@ def get_indicator_top_10_data(indicator, territory, submesh, filters):
|
|
|
77
77
|
}
|
|
78
78
|
for f in breakdown_filters
|
|
79
79
|
]
|
|
80
|
+
# TODO coverage faire un test avec un indicateur qui n'a pas de dimensions
|
|
81
|
+
# necessite un export de données de Bastien
|
|
80
82
|
else:
|
|
81
83
|
datasets_top_bar_chart = [
|
|
82
84
|
{
|
|
@@ -12,29 +12,29 @@ def _get_query(
|
|
|
12
12
|
limitation = f"LIMIT {limit}" if limit is not None else ""
|
|
13
13
|
offset = f"OFFSET {(props.pagination - 1) * limit}" if limit is not None else ""
|
|
14
14
|
dimension_search_where = (
|
|
15
|
-
f"OR (unaccent(LOWER({indicator.flows_dimension})) LIKE unaccent(LOWER('
|
|
15
|
+
f"OR (unaccent(LOWER({indicator.flows_dimension})) LIKE unaccent(LOWER(CONCAT('%%', %(search)s, '%%'))))"
|
|
16
16
|
if props.flows
|
|
17
17
|
else " ".join(
|
|
18
18
|
[
|
|
19
|
-
f"OR (unaccent(LOWER({dimension.db_name})) LIKE unaccent(LOWER('
|
|
19
|
+
f"OR (unaccent(LOWER({dimension.db_name})) LIKE unaccent(LOWER(CONCAT('%%', %(search)s, '%%'))))"
|
|
20
20
|
for dimension in indicator.dimensions.all()
|
|
21
21
|
]
|
|
22
22
|
)
|
|
23
23
|
)
|
|
24
24
|
territory_search_where = (
|
|
25
|
-
|
|
25
|
+
"OR (unaccent(LOWER(territory_1)) LIKE unaccent(LOWER(CONCAT('%%', %(search)s, '%%')))) OR (unaccent(LOWER(territory_2)) LIKE unaccent(LOWER(CONCAT('%%', %(search)s, '%%'))))"
|
|
26
26
|
if props.flows
|
|
27
27
|
else (
|
|
28
|
-
|
|
28
|
+
"OR (unaccent(LOWER(lieu)) LIKE unaccent(LOWER(CONCAT('%%', %(search)s, '%%'))))"
|
|
29
29
|
)
|
|
30
30
|
)
|
|
31
31
|
where = (
|
|
32
32
|
f"""
|
|
33
33
|
AND (
|
|
34
|
-
(LENGTH(TRIM(
|
|
34
|
+
(LENGTH(TRIM(%(search)s)) = 0)
|
|
35
35
|
{territory_search_where}
|
|
36
36
|
{dimension_search_where}
|
|
37
|
-
OR (CAST(annee AS TEXT) LIKE '
|
|
37
|
+
OR (CAST(annee AS TEXT) LIKE CONCAT('%%', %(search)s, '%%'))
|
|
38
38
|
)
|
|
39
39
|
"""
|
|
40
40
|
if props.search
|
|
@@ -128,7 +128,7 @@ def get_count_and_data_for_indicator_table(
|
|
|
128
128
|
orders=[],
|
|
129
129
|
filters=filters,
|
|
130
130
|
)
|
|
131
|
-
count = run_custom_query(count_query)
|
|
131
|
+
count = run_custom_query(count_query, {"search": props.search})
|
|
132
132
|
columns = get_values_columns(indicator, props)
|
|
133
133
|
orders = get_values_orders(indicator, props)
|
|
134
134
|
data_query = _get_query(
|
|
@@ -139,7 +139,7 @@ def get_count_and_data_for_indicator_table(
|
|
|
139
139
|
limit=props.limit,
|
|
140
140
|
filters=filters,
|
|
141
141
|
)
|
|
142
|
-
data = run_custom_query(data_query)
|
|
142
|
+
data = run_custom_query(data_query, {"search": props.search})
|
|
143
143
|
return count[0]["count"], data
|
|
144
144
|
|
|
145
145
|
|
|
@@ -151,4 +151,4 @@ def get_export_indicator_table_values(indicator, props: IndicatorTablePayload, f
|
|
|
151
151
|
orders=get_values_orders(indicator, props),
|
|
152
152
|
filters=filters,
|
|
153
153
|
)
|
|
154
|
-
return run_custom_query(query)
|
|
154
|
+
return run_custom_query(query, {"search": props.search})
|
|
@@ -335,18 +335,20 @@ def flows_view(request, payload):
|
|
|
335
335
|
external_territories_ids.add(row["territory_2_id"])
|
|
336
336
|
external_territories_ids
|
|
337
337
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
338
|
+
external_territories = []
|
|
339
|
+
if external_territories_ids:
|
|
340
|
+
codes = ", ".join([f"'{tid}'" for tid in external_territories_ids])
|
|
341
|
+
geo_query = f"""
|
|
342
|
+
SELECT DISTINCT
|
|
343
|
+
arbo."{mapped_mesh_level}" as territory_id,
|
|
344
|
+
arbo."NOM_{mapped_mesh_level}" as territory_name,
|
|
345
|
+
ST_ASGEOJSON(ST_CENTROID(contours.geometry)) as center
|
|
346
|
+
FROM arborescence_geo AS arbo
|
|
347
|
+
JOIN contours_simplified_{payload.submesh} as contours
|
|
348
|
+
ON arbo."{mapped_mesh_level}" = contours.code
|
|
349
|
+
WHERE arbo."{mapped_mesh_level}" IN ({codes})
|
|
350
|
+
"""
|
|
351
|
+
external_territories = run_custom_query(geo_query)
|
|
350
352
|
for t in external_territories:
|
|
351
353
|
territories_dict[t["territory_id"]] = {
|
|
352
354
|
"name": f"{t['territory_name']} (externe)",
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
from django.http import HttpResponse, JsonResponse
|
|
2
2
|
from django.views.decorators.http import require_GET
|
|
3
3
|
|
|
4
|
+
from territories_dashboard_lib.superset_lib.payloads import GuestTokenPayload
|
|
5
|
+
|
|
4
6
|
from .guest_token import get_guest_token
|
|
5
7
|
from .models import Dashboard
|
|
6
8
|
|
|
7
9
|
|
|
8
10
|
@require_GET
|
|
9
11
|
def guest_token_view(request):
|
|
10
|
-
|
|
11
|
-
guest_token = get_guest_token(
|
|
12
|
+
payload = GuestTokenPayload(**request.GET.dict())
|
|
13
|
+
guest_token = get_guest_token(payload.dashboard)
|
|
12
14
|
return HttpResponse(guest_token)
|
|
13
15
|
|
|
14
16
|
|
|
@@ -16,6 +16,7 @@ def default(request):
|
|
|
16
16
|
"ANALYTICS_ID": settings.ANALYTICS_ID,
|
|
17
17
|
"ENVIRONMENT": settings.ENVIRONMENT,
|
|
18
18
|
"view_name": request.resolver_match.view_name,
|
|
19
|
+
"absolute_uri": request.build_absolute_uri(),
|
|
19
20
|
"main_conf": main_conf,
|
|
20
21
|
"notice": notice,
|
|
21
22
|
"dashboards": [
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Generated by Django 5.2.6 on 2025-09-23 12:27
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('website_lib', '0003_alter_mainconf_footer_navigation_and_more'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AddField(
|
|
14
|
+
model_name='mainconf',
|
|
15
|
+
name='description',
|
|
16
|
+
field=models.TextField(blank=True, help_text='Utilisé pour la balise meta description du site et pour le relais sur les réseaux sociaux.', null=True, verbose_name='Description du site'),
|
|
17
|
+
),
|
|
18
|
+
migrations.AddField(
|
|
19
|
+
model_name='mainconf',
|
|
20
|
+
name='social_image_url',
|
|
21
|
+
field=models.TextField(blank=True, help_text="Lien d'une image (idéalement 1200x630px). Elle sera utilisée lors du partage sur les réseaux sociaux.", null=True, verbose_name='Image de description'),
|
|
22
|
+
),
|
|
23
|
+
]
|
|
@@ -16,6 +16,12 @@ class MainConf(CommonModel):
|
|
|
16
16
|
title = models.TextField(
|
|
17
17
|
verbose_name="Titre principal du site", default="Tableau de bord"
|
|
18
18
|
)
|
|
19
|
+
description = models.TextField(
|
|
20
|
+
verbose_name="Description du site",
|
|
21
|
+
null=True,
|
|
22
|
+
blank=True,
|
|
23
|
+
help_text="Utilisé pour la balise meta description du site et pour le relais sur les réseaux sociaux.",
|
|
24
|
+
)
|
|
19
25
|
entity = models.TextField(
|
|
20
26
|
verbose_name="Entité qui possède le site",
|
|
21
27
|
default="",
|
|
@@ -62,6 +68,12 @@ class MainConf(CommonModel):
|
|
|
62
68
|
verbose_name="Afficher une bannière de contact au-dessus du footer",
|
|
63
69
|
help_text="Pour afficher la bannière, l'email de contact et le lien d'inscription à la newsletter doivent être renseignés.",
|
|
64
70
|
)
|
|
71
|
+
social_image_url = models.TextField(
|
|
72
|
+
null=True,
|
|
73
|
+
blank=True,
|
|
74
|
+
verbose_name="Image de description",
|
|
75
|
+
help_text="Lien d'une image (idéalement 1200x630px). Elle sera utilisée lors du partage sur les réseaux sociaux.",
|
|
76
|
+
)
|
|
65
77
|
|
|
66
78
|
@property
|
|
67
79
|
def entity_breaklines(self):
|
|
@@ -32,6 +32,9 @@ class BadParam(Exception):
|
|
|
32
32
|
pass
|
|
33
33
|
|
|
34
34
|
|
|
35
|
+
# TODO coverage
|
|
36
|
+
# appeler la page détail d'un indicateur (page html, pas api) avec plus de combinaisons de paramètres GET
|
|
37
|
+
# tester les valeurs du context du template
|
|
35
38
|
class ParamsHandler:
|
|
36
39
|
def __init__(self, request):
|
|
37
40
|
self.request = request
|
territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/base.html
CHANGED
|
@@ -25,6 +25,17 @@
|
|
|
25
25
|
{% block page_title %}{% endblock %}
|
|
26
26
|
</title>
|
|
27
27
|
|
|
28
|
+
{% if main_conf.description %}
|
|
29
|
+
<meta name="description" content="{{ main_conf.description }}">
|
|
30
|
+
{% if main_conf.social_image_url %}
|
|
31
|
+
<meta property="og:url" content="{{ absolute_uri }}">
|
|
32
|
+
<meta property="og:type" content="website">
|
|
33
|
+
<meta property="og:title" content="{{ main_conf.title }}">
|
|
34
|
+
<meta property="og:description" content="{{ main_conf.description }}">
|
|
35
|
+
<meta property="og:image" content="{{ main_conf.social_image_url }}">
|
|
36
|
+
{% endif %}
|
|
37
|
+
{% endif %}
|
|
38
|
+
|
|
28
39
|
{% if ENVIRONMENT != "prd" %}
|
|
29
40
|
<meta name="robots" content="noindex, nofollow">
|
|
30
41
|
{% endif %}
|
{territories_dashboard_lib-0.1.20.dist-info → territories_dashboard_lib-0.1.21.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: territories-dashboard-lib
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.21
|
|
4
4
|
Summary: Librairie pour la visualisation d'indicateurs territoriaux.
|
|
5
5
|
Author-email: Bastien <bastien@prune.sh>
|
|
6
6
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -16,7 +16,7 @@ Requires-Dist: django-nested-admin>=4.1.1
|
|
|
16
16
|
Requires-Dist: geoip2>=5.1.0
|
|
17
17
|
Requires-Dist: gunicorn>=23.0.0
|
|
18
18
|
Requires-Dist: ipython>=8.32.0
|
|
19
|
-
Requires-Dist: martor>=1.
|
|
19
|
+
Requires-Dist: martor>=1.7.15
|
|
20
20
|
Requires-Dist: pre-commit>=4.2.0
|
|
21
21
|
Requires-Dist: psycopg2-binary>=2.9.10
|
|
22
22
|
Requires-Dist: pydantic>=2.10.6
|
{territories_dashboard_lib-0.1.20.dist-info → territories_dashboard_lib-0.1.21.dist-info}/RECORD
RENAMED
|
@@ -2,12 +2,14 @@ territories_dashboard_lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
|
|
|
2
2
|
territories_dashboard_lib/commons/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
3
|
territories_dashboard_lib/commons/decorators.py,sha256=_ACVnbaiCPuplT_81oA0nf_d6l7z0wTCFXMYwXIabew,1225
|
|
4
4
|
territories_dashboard_lib/commons/models.py,sha256=TQIvoXHSFrnIOQcVptHiMe4ZOdw5byse8sVLjnyeWTI,215
|
|
5
|
+
territories_dashboard_lib/commons/types.py,sha256=H9MuX0GQfdlqFzo67usQ_Gd7p9AaHEdBjfoch9wB4KI,614
|
|
5
6
|
territories_dashboard_lib/geo_lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
7
|
territories_dashboard_lib/geo_lib/admin.py,sha256=4Ek5WP-D3o1mBgPMqIBTPEsT7GeNo9REaw_FguIRw-M,1664
|
|
7
8
|
territories_dashboard_lib/geo_lib/enums.py,sha256=AwMKwYQP5Z9Qm_5FlO7AtHlJUU92obHXpSpAO1vGuwY,135
|
|
8
9
|
territories_dashboard_lib/geo_lib/models.py,sha256=r7lPzm0akEnbVTFSG3B_7dtDzFMSHzqpgt2MeNNhL8c,2191
|
|
10
|
+
territories_dashboard_lib/geo_lib/payloads.py,sha256=lwuZ4DpWIAWPyGHUgXOCevToxVimrgEOSHVKP6NpSVw,1646
|
|
9
11
|
territories_dashboard_lib/geo_lib/urls.py,sha256=W0Zc2z7dn06p4pyFAf0EKATpXAbM0byxCpJK-LRYLak,602
|
|
10
|
-
territories_dashboard_lib/geo_lib/views.py,sha256=
|
|
12
|
+
territories_dashboard_lib/geo_lib/views.py,sha256=ElpoEGHWwynnq9BPGGadHzH1zyVII1Wq9mQ8zqggSH0,7428
|
|
11
13
|
territories_dashboard_lib/geo_lib/migrations/0001_initial.py,sha256=-H_5uG0IaPesUfGDkYWdtqHqfWOIKvoQQuAZkfGAu-E,3092
|
|
12
14
|
territories_dashboard_lib/geo_lib/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
15
|
territories_dashboard_lib/indicators_lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -17,29 +19,30 @@ territories_dashboard_lib/indicators_lib/export.py,sha256=pfzGNR09093qG6t_rVzHNc
|
|
|
17
19
|
territories_dashboard_lib/indicators_lib/format.py,sha256=W-ajQjrH6E2mseSq4Lozl0bhmEq481tGFIGsjYS8MMo,891
|
|
18
20
|
territories_dashboard_lib/indicators_lib/methodo_pdf.py,sha256=LpDHMFSNavvfJOI7gDicdY7uF27JpUd-ceUMnOY_FNU,2920
|
|
19
21
|
territories_dashboard_lib/indicators_lib/models.py,sha256=9f8XmM_WDuIjQTF9V3p3BAqRS0hlbLJjWTGOW5Kdp_4,8323
|
|
20
|
-
territories_dashboard_lib/indicators_lib/payloads.py,sha256=
|
|
22
|
+
territories_dashboard_lib/indicators_lib/payloads.py,sha256=gUM_ZpnnCsDiKAaVLgyrA88Kj9HoGMUSFRhEyEltNVk,1410
|
|
21
23
|
territories_dashboard_lib/indicators_lib/refresh_filters.py,sha256=uPdKKcCtfwQL2QoGXtRcZcxagYpVv2yiiiTTsCYaXEI,652
|
|
22
|
-
territories_dashboard_lib/indicators_lib/table.py,sha256=
|
|
24
|
+
territories_dashboard_lib/indicators_lib/table.py,sha256=yBbdW_W0nJAP3wN5kTXj6FylZ9s75GFh-j1tUGWXUNU,5402
|
|
23
25
|
territories_dashboard_lib/indicators_lib/urls.py,sha256=1Rr5mDOitIA40bZcO3lGlseQsvXIwyw1QM6PyUPi_Nw,2489
|
|
24
|
-
territories_dashboard_lib/indicators_lib/views.py,sha256=
|
|
26
|
+
territories_dashboard_lib/indicators_lib/views.py,sha256=hxZdM-HpJYj9u3dfQ3ExE4CHnYxpup7otrDgIeaPHB0,17249
|
|
25
27
|
territories_dashboard_lib/indicators_lib/migrations/0001_initial.py,sha256=3EyizMGkqve5Gtxrmf-mADzzmOhcAVWe-P0y1TIBKCs,8092
|
|
26
28
|
territories_dashboard_lib/indicators_lib/migrations/0002_filter_color_indicator_min_mesh_and_more.py,sha256=Lz6_UVKLAmaRT-OskwbTMh3PjIh0k4BaGyIOHCC8zMI,884
|
|
27
29
|
territories_dashboard_lib/indicators_lib/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
|
-
territories_dashboard_lib/indicators_lib/query/commons.py,sha256=
|
|
30
|
+
territories_dashboard_lib/indicators_lib/query/commons.py,sha256=SI8h2Jdcp8AFzlent-J9MHXOcf1P9wv6r0pqtICNezA,6949
|
|
29
31
|
territories_dashboard_lib/indicators_lib/query/comparison.py,sha256=ypT8jed99NubgBWqsjZ_4vs9xX2rArnxeGFQ2IY3cKM,2540
|
|
30
32
|
territories_dashboard_lib/indicators_lib/query/details.py,sha256=si43KVB5QxgQTc9c6AJZ04EK8zPSag9NPfiril9Fv0k,2476
|
|
31
33
|
territories_dashboard_lib/indicators_lib/query/histogram.py,sha256=NpQdAqVzm-bB5AuMZF3jOzEJKLjecwafhlorkYQY6IU,2964
|
|
32
|
-
territories_dashboard_lib/indicators_lib/query/indicator_card.py,sha256=
|
|
33
|
-
territories_dashboard_lib/indicators_lib/query/top_10.py,sha256=
|
|
34
|
+
territories_dashboard_lib/indicators_lib/query/indicator_card.py,sha256=ecgv-5gezo3iJ_vVGBHIn2i__Tf_fQqbhGBOffXg_gY,2926
|
|
35
|
+
territories_dashboard_lib/indicators_lib/query/top_10.py,sha256=n-VTwoXAL6L0jZEae3DRNGFsdzY4txgl77bGDCGqen4,3805
|
|
34
36
|
territories_dashboard_lib/indicators_lib/query/utils.py,sha256=o9tQTMSSlidH60JLo5RwVfWY3UXFCx0b44VeHiWC6cM,1610
|
|
35
37
|
territories_dashboard_lib/superset_lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
36
38
|
territories_dashboard_lib/superset_lib/admin.py,sha256=3Yj3PjCd-jC0g4uMNmah-OST-yoE7DDEzJkx2kWlrXg,563
|
|
37
39
|
territories_dashboard_lib/superset_lib/guest_token.py,sha256=smsl11NS2Sgsuz5UJlvI_lDaBi6Fj9rdpSVmuUol8Fs,2300
|
|
38
40
|
territories_dashboard_lib/superset_lib/logic.py,sha256=vVzSimSlrwefVVdEf2dMr83MW2c_yB4k2uw_Szu_nHg,2492
|
|
39
41
|
territories_dashboard_lib/superset_lib/models.py,sha256=D_IKcYggr8OeH4Gc9KxmU0ArQ3lq8DFN-e0JDQs9Dng,2613
|
|
42
|
+
territories_dashboard_lib/superset_lib/payloads.py,sha256=IKXIuDIMFkSUZNZz4_9VGPHN41YXdRLRYyIIeu0vB1I,163
|
|
40
43
|
territories_dashboard_lib/superset_lib/serializers.py,sha256=k5DcdwN-k5w9dPchiyxBZtG3BAULp8c00JTO3DR6rA4,250
|
|
41
44
|
territories_dashboard_lib/superset_lib/urls.py,sha256=URXJLciWDTlzU7gIymlK0nWwAm3Iq8bMkhO0P7RwMuk,254
|
|
42
|
-
territories_dashboard_lib/superset_lib/views.py,sha256=
|
|
45
|
+
territories_dashboard_lib/superset_lib/views.py,sha256=hsBkU8EshP4b3n_0hL7aFwGOZa2IRWwWwpGWkT21Li8,676
|
|
43
46
|
territories_dashboard_lib/superset_lib/migrations/0001_initial.py,sha256=Y6iY33EVPMg0XIJu8EErKRJMguYqE7IaZhthZ69OxXA,3461
|
|
44
47
|
territories_dashboard_lib/superset_lib/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
45
48
|
territories_dashboard_lib/tracking_lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -59,17 +62,18 @@ territories_dashboard_lib/tracking_lib/migrations/0004_cookieinfo_ip_address.py,
|
|
|
59
62
|
territories_dashboard_lib/tracking_lib/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
60
63
|
territories_dashboard_lib/website_lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
61
64
|
territories_dashboard_lib/website_lib/admin.py,sha256=jq0KgN8CPVqJQ1IMq8kaoWqqxzpPDyW0z7cTatmrmi0,952
|
|
62
|
-
territories_dashboard_lib/website_lib/context_processors.py,sha256=
|
|
65
|
+
territories_dashboard_lib/website_lib/context_processors.py,sha256=0lI2KvOBCGyvE52xnTfFyAVget25DLNtaIMgyT9NfAI,917
|
|
63
66
|
territories_dashboard_lib/website_lib/forms.py,sha256=BNbHx6CgMlA33z6eD-1VaI7AkyO20ZsloJKsec4BcoU,1146
|
|
64
|
-
territories_dashboard_lib/website_lib/models.py,sha256=
|
|
67
|
+
territories_dashboard_lib/website_lib/models.py,sha256=w5EtwvuzRc8Ei4jQBJOobcCJchokzTc5u1givt6URd0,5852
|
|
65
68
|
territories_dashboard_lib/website_lib/navigation.py,sha256=D9YNfBVPpO9bRgNT02j99sp0A0_uqDaBgc25BbQOako,3994
|
|
66
|
-
territories_dashboard_lib/website_lib/params.py,sha256=
|
|
69
|
+
territories_dashboard_lib/website_lib/params.py,sha256=SLPoaaKmkkis8c61d6DqIlZOpFaI1AKN9ZOJy1c06cg,10036
|
|
67
70
|
territories_dashboard_lib/website_lib/serializers.py,sha256=PVcOC52zlNn2tp7IRwMuB4T7rOaLl3bLKiqqesWgRE4,3772
|
|
68
71
|
territories_dashboard_lib/website_lib/static_content.py,sha256=08Fw3190RsTZ8wXwZkmskh-86widq7NRmTD9Ve-9PJY,589
|
|
69
72
|
territories_dashboard_lib/website_lib/views.py,sha256=ZNz23Vrws-L49xeZzrhSJA8KFpqSnURn-9-b0RdR9JE,6760
|
|
70
73
|
territories_dashboard_lib/website_lib/migrations/0001_initial.py,sha256=4g2YgUUBEdak_iW717cJojCv5kqnNV_46GVnw8u8eAw,5701
|
|
71
74
|
territories_dashboard_lib/website_lib/migrations/0002_mainconf_contact_email_mainconf_newsletter_link_and_more.py,sha256=HJbz8w63SGhPwBNCqPJXFMuepkHfImgnmqRe3gQ3W8g,1052
|
|
72
75
|
territories_dashboard_lib/website_lib/migrations/0003_alter_mainconf_footer_navigation_and_more.py,sha256=TK8o5EPq1Zcs737XLMDmFvbn3LqhjK3RRZBS9vcfD_I,1654
|
|
76
|
+
territories_dashboard_lib/website_lib/migrations/0004_mainconf_description_mainconf_social_image_url.py,sha256=FrCn4IwajxX7s80fnTK43NH8xUPpw1oUD13TOTz0jqA,894
|
|
73
77
|
territories_dashboard_lib/website_lib/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
74
78
|
territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/chart.js,sha256=qKg5SGiIDybjFd0WYySXtFROPHmdJVENEIatEXIQv34,205577
|
|
75
79
|
territories_dashboard_lib/website_lib/static/territories_dashboard_lib/website/js/chartjs-plugin-datalabels.js,sha256=nhS5Le-PSsSKXcYJl2KaaI1NMFQlRIN2Oggha7ehtdc,12754
|
|
@@ -112,7 +116,7 @@ territories_dashboard_lib/website_lib/templates/admin/indicators_lib/indicator/c
|
|
|
112
116
|
territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/404.html,sha256=IbXsHmSXPdhbhMFPYCFnuBCjSLTdFPNpeJbl-vQXX-o,278
|
|
113
117
|
territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/500.html,sha256=zKtoQpzH_wOlNe_COwXANZR4lIV5DnZgcuymezmdk0g,278
|
|
114
118
|
territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/base.css,sha256=5Y_BiY7qqgR1XBjqz22tqbWpMqwyhydDNCIbim_W8jw,1385
|
|
115
|
-
territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/base.html,sha256=
|
|
119
|
+
territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/base.html,sha256=T5a0xLiRBrZPsJ3SfIs5_S-glWUiAUxf312vmgMFsy8,2331
|
|
116
120
|
territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/base.js,sha256=IHW3YF3451k-G7GjZieQ7sBaRPezNK5TYt1WV_qF5OY,1624
|
|
117
121
|
territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/footer.css,sha256=IX2OUf1BCJEh3fMbpwvtQFtMVj24AY9GEf22DsHmEN4,233
|
|
118
122
|
territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/layout/footer.html,sha256=I_JyfoVq1IZi9ESZA8C4nlYiJgIVYShy3L-rVioI5NA,6124
|
|
@@ -173,8 +177,8 @@ territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/websit
|
|
|
173
177
|
territories_dashboard_lib/website_lib/templates/territories_dashboard_lib/website/svg/delete-back.svg,sha256=fJPjkZT2jdTcW2nmwr7YtBayOmQKOxiGNyO8bM8jP2U,618
|
|
174
178
|
territories_dashboard_lib/website_lib/templatetags/htmlparams.py,sha256=jWXlmT-nFh7YefVP_zJSXEA1YgT37wnWqelPhmj7UoM,2092
|
|
175
179
|
territories_dashboard_lib/website_lib/templatetags/other_filters.py,sha256=EEczSQi8lJZ_rfceuXQz3iF1SIxh5d-3-liTY8lkKtU,944
|
|
176
|
-
territories_dashboard_lib-0.1.
|
|
177
|
-
territories_dashboard_lib-0.1.
|
|
178
|
-
territories_dashboard_lib-0.1.
|
|
179
|
-
territories_dashboard_lib-0.1.
|
|
180
|
-
territories_dashboard_lib-0.1.
|
|
180
|
+
territories_dashboard_lib-0.1.21.dist-info/licenses/licence.md,sha256=9Tat8mM_Yyww-wmWps8avlOhzumqEUGYy8853tKy7aE,7804
|
|
181
|
+
territories_dashboard_lib-0.1.21.dist-info/METADATA,sha256=i12-Pzgaubzydg7rCXFfPMxfjgR5ikBXvjShSGZeARM,6191
|
|
182
|
+
territories_dashboard_lib-0.1.21.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
183
|
+
territories_dashboard_lib-0.1.21.dist-info/top_level.txt,sha256=Cih-lil8CSXTpDZV6fgHKIKIBtUjDaNpmkiuW2TSzsk,26
|
|
184
|
+
territories_dashboard_lib-0.1.21.dist-info/RECORD,,
|
{territories_dashboard_lib-0.1.20.dist-info → territories_dashboard_lib-0.1.21.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|