Vue marché simple #40
This commit is contained in:
@@ -38,7 +38,7 @@ python run.py
|
|||||||
|
|
||||||
#### 2.1.0
|
#### 2.1.0
|
||||||
|
|
||||||
- Ajout des vues [acheteur](https://decp.info/acheteurs/24350013900189) et [titulaire](https://decp.info/titulaires/51903758414786) ([#28](https://github.com/ColinMaudry/decp.info/issues/28) et [#35](https://github.com/ColinMaudry/decp.info/issues/35)) 🔎
|
- Ajout des vues [acheteur](https://decp.info/acheteurs/24350013900189) ([#28](https://github.com/ColinMaudry/decp.info/issues/28)), [titulaire](https://decp.info/titulaires/51903758414786) ([#35](https://github.com/ColinMaudry/decp.info/issues/35)) et [marché](https://decp.info/marches/532239472000482025S00004) ([#40](https://github.com/ColinMaudry/decp.info/issues/40)) 🔎
|
||||||
- Ajout des balises HTML meta Open Graph et Twitter ([#39](https://github.com/ColinMaudry/decp.info/issues/39)) pour de beaux aperçus de liens 🖼️
|
- Ajout des balises HTML meta Open Graph et Twitter ([#39](https://github.com/ColinMaudry/decp.info/issues/39)) pour de beaux aperçus de liens 🖼️
|
||||||
- Formulaire de contact ([#48](https://github.com/ColinMaudry/decp.info/issues/48)) 📨
|
- Formulaire de contact ([#48](https://github.com/ColinMaudry/decp.info/issues/48)) 📨
|
||||||
- Nom de colonnes plus_agréables ([#33](https://github.com/ColinMaudry/decp.info/issues/33)) 💅
|
- Nom de colonnes plus_agréables ([#33](https://github.com/ColinMaudry/decp.info/issues/33)) 💅
|
||||||
|
|||||||
+1
-1
@@ -96,7 +96,7 @@ app.layout = html.Div(
|
|||||||
page["name"], href=page["relative_path"], className="nav"
|
page["name"], href=page["relative_path"], className="nav"
|
||||||
)
|
)
|
||||||
for page in page_registry.values()
|
for page in page_registry.values()
|
||||||
if page["name"] not in ["Acheteur", "Titulaire"]
|
if page["name"] not in ["Acheteur", "Titulaire", "Marché"]
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
+33
-2
@@ -88,8 +88,8 @@ td[data-dash-column="objet"] {
|
|||||||
color: #333;
|
color: #333;
|
||||||
width: 400px !important;
|
width: 400px !important;
|
||||||
max-width: 400px !important;
|
max-width: 400px !important;
|
||||||
height: 100px !important;
|
height: 150px !important;
|
||||||
max-height: 100px !important;
|
max-height: 150px !important;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,6 +179,9 @@ summary > h3 {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wrapper > div {
|
||||||
|
}
|
||||||
|
|
||||||
.org_title {
|
.org_title {
|
||||||
grid-column: 1 / 3;
|
grid-column: 1 / 3;
|
||||||
grid-row: 1;
|
grid-row: 1;
|
||||||
@@ -207,3 +210,31 @@ summary > h3 {
|
|||||||
grid-column: 3;
|
grid-column: 3;
|
||||||
grid-row: 2;
|
grid-row: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Vue marché */
|
||||||
|
|
||||||
|
.marche_infos p {
|
||||||
|
margin-top: 6px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.marche_title {
|
||||||
|
grid-column: 1/3;
|
||||||
|
grid-row: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.marche_map {
|
||||||
|
grid-column: 3;
|
||||||
|
grid-row: 2;
|
||||||
|
width: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.marche_infos_1 {
|
||||||
|
grid-column: 1;
|
||||||
|
grid-row: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.marche_infos_2 {
|
||||||
|
grid-column: 2;
|
||||||
|
grid-row: 2;
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -48,7 +48,7 @@ les fonctionnalités actuelles de decp.info. Il est ainsi possible de rajouter
|
|||||||
|
|
||||||
- ✉️ [inscription à la liste de diffusion](https://6254d9a3.sibforms.com/serve/MUIFAEonUVkoSVrdgey18CTgLyI16xw4yeu-M-YOUzhWE_AgfQfbgkyT7GvA_RYLro9MfuRqkzQxSvu7-uzbMSv2a2ZQPsliM7wtiiqIL8kR2zOvl6m11fb5qjcOxMAYsLiY_YBi3P7NY95CTJ8vRY4CpsDclF2iLooOElKkTgIgi5nePe7zAIrgiYM5v2EuALlGJZMEG9vBP-Cu) (annonces des mises à jour et évènements, maximum une fois par mois)
|
- ✉️ [inscription à la liste de diffusion](https://6254d9a3.sibforms.com/serve/MUIFAEonUVkoSVrdgey18CTgLyI16xw4yeu-M-YOUzhWE_AgfQfbgkyT7GvA_RYLro9MfuRqkzQxSvu7-uzbMSv2a2ZQPsliM7wtiiqIL8kR2zOvl6m11fb5qjcOxMAYsLiY_YBi3P7NY95CTJ8vRY4CpsDclF2iLooOElKkTgIgi5nePe7zAIrgiYM5v2EuALlGJZMEG9vBP-Cu) (annonces des mises à jour et évènements, maximum une fois par mois)
|
||||||
- 💾 [données consolidées en Open Data](https://www.data.gouv.fr/datasets/donnees-essentielles-de-la-commande-publique-consolidees-format-tabulaire/)
|
- 💾 [données consolidées en Open Data](https://www.data.gouv.fr/datasets/donnees-essentielles-de-la-commande-publique-consolidees-format-tabulaire/)
|
||||||
- 🗞️ [mon blog](https://colin.maudry.com), qui parle beaucoup de transparence des marchés publics
|
- 🗞️ [mon blog](https://colin.maudry.com)
|
||||||
- 📔 [wiki du projet](https://github.com/ColinMaudry/decp-processing/wiki)
|
- 📔 [wiki du projet](https://github.com/ColinMaudry/decp-processing/wiki)
|
||||||
- 🚰 code source
|
- 🚰 code source
|
||||||
- [de decp.info](https://github.com/ColinMaudry/decp.info)
|
- [de decp.info](https://github.com/ColinMaudry/decp.info)
|
||||||
|
|||||||
+6
-13
@@ -5,7 +5,7 @@ from dash import Input, Output, State, callback, dash_table, dcc, html, register
|
|||||||
|
|
||||||
from src.figures import point_on_map
|
from src.figures import point_on_map
|
||||||
from src.utils import (
|
from src.utils import (
|
||||||
add_org_links_in_dict,
|
add_links_in_dict,
|
||||||
format_montant,
|
format_montant,
|
||||||
format_number,
|
format_number,
|
||||||
get_annuaire_data,
|
get_annuaire_data,
|
||||||
@@ -177,6 +177,7 @@ def get_acheteur_marches_data(url, acheteur_year: str) -> pl.LazyFrame:
|
|||||||
lff = lff.fill_null("")
|
lff = lff.fill_null("")
|
||||||
lff = lff.select(
|
lff = lff.select(
|
||||||
"id",
|
"id",
|
||||||
|
"uid",
|
||||||
"objet",
|
"objet",
|
||||||
"dateNotification",
|
"dateNotification",
|
||||||
"titulaire_id",
|
"titulaire_id",
|
||||||
@@ -201,23 +202,15 @@ def get_acheteur_marches_data(url, acheteur_year: str) -> pl.LazyFrame:
|
|||||||
Input(component_id="acheteur_data", component_property="data"),
|
Input(component_id="acheteur_data", component_property="data"),
|
||||||
)
|
)
|
||||||
def get_last_marches_table(data) -> html.Div:
|
def get_last_marches_table(data) -> html.Div:
|
||||||
columns = [
|
|
||||||
"id",
|
|
||||||
"objet",
|
|
||||||
"dateNotification",
|
|
||||||
"titulaire_nom",
|
|
||||||
"montant",
|
|
||||||
"codeCPV",
|
|
||||||
"dureeMois",
|
|
||||||
]
|
|
||||||
|
|
||||||
dff = pl.DataFrame(data)
|
dff = pl.DataFrame(data)
|
||||||
dff = format_montant(dff)
|
dff = format_montant(dff)
|
||||||
columns, tooltip = setup_table_columns(
|
columns, tooltip = setup_table_columns(
|
||||||
dff, hideable=False, exclude=["titulaire_id", "titulaire_typeIdentifiant"]
|
dff,
|
||||||
|
hideable=False,
|
||||||
|
exclude=["titulaire_id", "titulaire_typeIdentifiant", "uid"],
|
||||||
)
|
)
|
||||||
data = dff.to_dicts()
|
data = dff.to_dicts()
|
||||||
data = add_org_links_in_dict(data, "titulaire")
|
data = add_links_in_dict(data, "titulaire")
|
||||||
|
|
||||||
table = html.Div(
|
table = html.Div(
|
||||||
className="marches_table",
|
className="marches_table",
|
||||||
|
|||||||
+2
-2
@@ -5,7 +5,7 @@ import polars as pl
|
|||||||
from dash import Input, Output, State, callback, dash_table, dcc, html, register_page
|
from dash import Input, Output, State, callback, dash_table, dcc, html, register_page
|
||||||
|
|
||||||
from src.utils import (
|
from src.utils import (
|
||||||
add_org_links,
|
add_links,
|
||||||
add_resource_link,
|
add_resource_link,
|
||||||
filter_table_data,
|
filter_table_data,
|
||||||
format_montant,
|
format_montant,
|
||||||
@@ -197,7 +197,7 @@ def update_table(page_current, page_size, filter_query, sort_by, data_timestamp)
|
|||||||
dff = dff.slice(start_row, page_size)
|
dff = dff.slice(start_row, page_size)
|
||||||
|
|
||||||
# Ajout des liens vers l'annuaire des entreprises
|
# Ajout des liens vers l'annuaire des entreprises
|
||||||
dff = add_org_links(dff)
|
dff = add_links(dff)
|
||||||
|
|
||||||
# Ajout des liens vers les fichiers Open Data
|
# Ajout des liens vers les fichiers Open Data
|
||||||
dff = add_resource_link(dff)
|
dff = add_resource_link(dff)
|
||||||
|
|||||||
@@ -0,0 +1,188 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
import polars as pl
|
||||||
|
from dash import Input, Output, callback, dcc, html, register_page
|
||||||
|
from polars import selectors as cs
|
||||||
|
|
||||||
|
from src.utils import data_schema, format_montant, lf, meta_content
|
||||||
|
|
||||||
|
register_page(
|
||||||
|
__name__,
|
||||||
|
path_template="/marches/<uid>",
|
||||||
|
title=meta_content["title"],
|
||||||
|
name="Marché",
|
||||||
|
description=meta_content["description"],
|
||||||
|
image_url=meta_content["image_url"],
|
||||||
|
order=7,
|
||||||
|
)
|
||||||
|
|
||||||
|
layout = [
|
||||||
|
dcc.Store(id="marche_data"),
|
||||||
|
dcc.Store(id="titulaires_data"),
|
||||||
|
dcc.Location(id="url", refresh="callback-nav"),
|
||||||
|
html.Div(
|
||||||
|
className="container marche_infos",
|
||||||
|
children=[
|
||||||
|
html.P("Vous consultez un résumé des données de ce marché public"),
|
||||||
|
html.Ul(
|
||||||
|
[
|
||||||
|
html.Li(
|
||||||
|
"après son attribution aux titulaires qui l'ont remporté à la suite d'un appel d'offres (ou sans appel d'offres via une attribution directe)"
|
||||||
|
),
|
||||||
|
html.Li(
|
||||||
|
"après avoir appliqué les éventuelles modifications de montant, durée ou titulaires renseignées par l'acheteur"
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
html.P(
|
||||||
|
"Le montant total payé aux titulaires, la durée du marché et la liste des titulaires peuvent cependant encore évoluer jusqu'à la fin de l'exécution du marché."
|
||||||
|
),
|
||||||
|
html.Div(
|
||||||
|
className="wrapper",
|
||||||
|
children=[
|
||||||
|
html.Div(
|
||||||
|
className="marche_map",
|
||||||
|
id="marche_map",
|
||||||
|
children=[
|
||||||
|
html.H4("Titulaires"),
|
||||||
|
html.Ul(id="marche_infos_titulaires"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
html.Div(className="marche_infos_1", id="marche_infos_1"),
|
||||||
|
html.Div(className="marche_infos_2", id="marche_infos_2"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@callback(
|
||||||
|
Output("marche_data", "data"),
|
||||||
|
Output("titulaires_data", "data"),
|
||||||
|
Input(component_id="url", component_property="pathname"),
|
||||||
|
)
|
||||||
|
def get_marche_data(url):
|
||||||
|
marche_uid = url.split("/")[-1]
|
||||||
|
|
||||||
|
# Récupération des données du marché à partir du lf global
|
||||||
|
lff = lf.filter(pl.col("uid") == pl.lit(marche_uid))
|
||||||
|
|
||||||
|
# Données des titulaires du marché
|
||||||
|
dff_titulaires = lff.select(cs.starts_with("titulaire")).collect(engine="streaming")
|
||||||
|
|
||||||
|
# Données du marché
|
||||||
|
dff_marche = (
|
||||||
|
lff.select(~cs.starts_with("titulaires")).unique().collect(engine="streaming")
|
||||||
|
)
|
||||||
|
dff_marche = format_montant(dff_marche)
|
||||||
|
|
||||||
|
assert dff_marche.height == 1
|
||||||
|
|
||||||
|
return dff_marche.to_dicts()[0], dff_titulaires.to_dicts()
|
||||||
|
|
||||||
|
|
||||||
|
@callback(
|
||||||
|
Output("marche_infos_1", "children"),
|
||||||
|
Output("marche_infos_2", "children"),
|
||||||
|
Output("marche_infos_titulaires", "children"),
|
||||||
|
Input("marche_data", "data"),
|
||||||
|
Input("titulaires_data", "data"),
|
||||||
|
)
|
||||||
|
def update_marche_info(marche, titulaires):
|
||||||
|
def make_parameter(col):
|
||||||
|
column_object = data_schema.get(col)
|
||||||
|
column_name = column_object.get("friendly_name") if column_object else col
|
||||||
|
|
||||||
|
if marche[col]:
|
||||||
|
if col == "acheteur_nom":
|
||||||
|
value = html.A(
|
||||||
|
href=f"/acheteurs/{marche['acheteur_id']}",
|
||||||
|
children=marche["acheteur_nom"],
|
||||||
|
)
|
||||||
|
elif col == "sourceDataset":
|
||||||
|
value = html.A(
|
||||||
|
href=marche["sourceFile"], children=marche["sourceDataset"]
|
||||||
|
)
|
||||||
|
column_name = "Source des données"
|
||||||
|
|
||||||
|
# Dates
|
||||||
|
elif col in ["dateNotification", "datePublicationDonnees"]:
|
||||||
|
print(marche[col])
|
||||||
|
|
||||||
|
value = datetime.fromisoformat(marche[col]).strftime("%d/%m/%Y")
|
||||||
|
|
||||||
|
# Listes
|
||||||
|
elif (
|
||||||
|
col
|
||||||
|
in [
|
||||||
|
"techniques",
|
||||||
|
"typesPrix",
|
||||||
|
"considerationsSociales",
|
||||||
|
"considerationsEnvironnementales",
|
||||||
|
]
|
||||||
|
and "," in marche[col]
|
||||||
|
):
|
||||||
|
col_values = marche[col].split(", ")
|
||||||
|
lines = []
|
||||||
|
for val in col_values:
|
||||||
|
lines.append(html.Li(val))
|
||||||
|
_content = html.Div(
|
||||||
|
[html.P([column_name, " : "]), html.Ul(children=lines)]
|
||||||
|
)
|
||||||
|
return _content
|
||||||
|
else:
|
||||||
|
value = marche.get(col)
|
||||||
|
else:
|
||||||
|
value = ""
|
||||||
|
|
||||||
|
param_content = html.P([column_name, " : ", html.Strong(value)])
|
||||||
|
return param_content
|
||||||
|
|
||||||
|
marche_infos = [
|
||||||
|
make_parameter("id"),
|
||||||
|
make_parameter("objet"),
|
||||||
|
make_parameter("dateNotification"), # date
|
||||||
|
make_parameter("nature"),
|
||||||
|
make_parameter("acheteur_nom"), # lien
|
||||||
|
make_parameter("montant"),
|
||||||
|
make_parameter("codeCPV"),
|
||||||
|
make_parameter("procedure"),
|
||||||
|
make_parameter("techniques"), # list
|
||||||
|
make_parameter("dureeMois"),
|
||||||
|
make_parameter("offresRecues"),
|
||||||
|
make_parameter("datePublicationDonnees"), # date
|
||||||
|
make_parameter("formePrix"),
|
||||||
|
make_parameter("typesPrix"), # list
|
||||||
|
make_parameter("attributionAvance"),
|
||||||
|
make_parameter("tauxAvance"),
|
||||||
|
make_parameter("marcheInnovant"), # label
|
||||||
|
make_parameter("modalitesExecution"),
|
||||||
|
make_parameter("considerationsSociales"), # list
|
||||||
|
make_parameter("considerationsEnvironnementales"), # list
|
||||||
|
make_parameter("ccag"),
|
||||||
|
make_parameter("sousTraitanceDeclaree"),
|
||||||
|
make_parameter("typeGroupementOperateurs"),
|
||||||
|
make_parameter("origineFrance"),
|
||||||
|
make_parameter("origineUE"),
|
||||||
|
make_parameter("idAccordCadre"),
|
||||||
|
make_parameter("sourceDataset"), # lien
|
||||||
|
]
|
||||||
|
|
||||||
|
half = round(len(marche_infos) / 2)
|
||||||
|
# pas inclus pour l'instant : lieu d'exécution, modifications
|
||||||
|
|
||||||
|
titulaires_lines = []
|
||||||
|
for titulaire in titulaires:
|
||||||
|
if titulaire["titulaire_typeIdentifiant"] == "SIRET":
|
||||||
|
content = html.Li(
|
||||||
|
html.A(
|
||||||
|
href=f"/titulaires/{titulaire['titulaire_id']}",
|
||||||
|
children=titulaire["titulaire_nom"],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
content = html.Li(titulaire["titulaire_nom"])
|
||||||
|
titulaires_lines.append(content)
|
||||||
|
|
||||||
|
return marche_infos[:half], marche_infos[half:], titulaires_lines
|
||||||
@@ -5,7 +5,7 @@ from dash import Input, Output, State, callback, dash_table, dcc, html, register
|
|||||||
|
|
||||||
from src.figures import point_on_map
|
from src.figures import point_on_map
|
||||||
from src.utils import (
|
from src.utils import (
|
||||||
add_org_links_in_dict,
|
add_links_in_dict,
|
||||||
format_montant,
|
format_montant,
|
||||||
format_number,
|
format_number,
|
||||||
get_annuaire_data,
|
get_annuaire_data,
|
||||||
@@ -181,6 +181,7 @@ def get_titulaire_marches_data(url, titulaire_year: str) -> pl.LazyFrame:
|
|||||||
)
|
)
|
||||||
lff = lff.fill_null("")
|
lff = lff.fill_null("")
|
||||||
lff = lff.select(
|
lff = lff.select(
|
||||||
|
"id",
|
||||||
"uid",
|
"uid",
|
||||||
"objet",
|
"objet",
|
||||||
"dateNotification",
|
"dateNotification",
|
||||||
@@ -217,11 +218,13 @@ def get_last_marches_table(data) -> html.Div:
|
|||||||
|
|
||||||
dff = pl.DataFrame(data)
|
dff = pl.DataFrame(data)
|
||||||
dff = format_montant(dff)
|
dff = format_montant(dff)
|
||||||
columns, tooltip = setup_table_columns(dff, hideable=False, exclude=["acheteur_id"])
|
columns, tooltip = setup_table_columns(
|
||||||
|
dff, hideable=False, exclude=["acheteur_id", "id"]
|
||||||
|
)
|
||||||
data = dff.to_dicts()
|
data = dff.to_dicts()
|
||||||
# Idéalement on utiliserait add_org_links(), mais le résultat attendu
|
# Idéalement on utiliserait add_org_links(), mais le résultat attendu
|
||||||
# est différent de home.py (Tableau)
|
# est différent de home.py (Tableau)
|
||||||
data = add_org_links_in_dict(data, "acheteur")
|
data = add_links_in_dict(data, "acheteur")
|
||||||
|
|
||||||
table = html.Div(
|
table = html.Div(
|
||||||
className="marches_table",
|
className="marches_table",
|
||||||
@@ -249,7 +252,7 @@ def get_last_marches_table(data) -> html.Div:
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"if": {"column_id": "acheteur_nom"},
|
"if": {"column_id": "acheteur_nom"},
|
||||||
"minWidth": "200px",
|
"maxWidth": "400px",
|
||||||
"textAlign": "left",
|
"textAlign": "left",
|
||||||
"overflow": "hidden",
|
"overflow": "hidden",
|
||||||
"lineHeight": "18px",
|
"lineHeight": "18px",
|
||||||
|
|||||||
+15
-7
@@ -49,7 +49,7 @@ def add_resource_link(dff: pl.DataFrame) -> pl.DataFrame:
|
|||||||
return dff
|
return dff
|
||||||
|
|
||||||
|
|
||||||
def add_org_links(dff: pl.DataFrame):
|
def add_links(dff: pl.DataFrame):
|
||||||
dff = dff.with_columns(
|
dff = dff.with_columns(
|
||||||
pl.when(pl.col("titulaire_typeIdentifiant") == "SIRET")
|
pl.when(pl.col("titulaire_typeIdentifiant") == "SIRET")
|
||||||
.then(
|
.then(
|
||||||
@@ -62,25 +62,29 @@ def add_org_links(dff: pl.DataFrame):
|
|||||||
.otherwise(pl.col("titulaire_id"))
|
.otherwise(pl.col("titulaire_id"))
|
||||||
.alias("titulaire_id")
|
.alias("titulaire_id")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for column, path in [("acheteur_id", "acheteurs"), ("uid", "marches")]:
|
||||||
dff = dff.with_columns(
|
dff = dff.with_columns(
|
||||||
(
|
(
|
||||||
'<a href = "/acheteurs/'
|
f'<a href = "/{path}/'
|
||||||
+ pl.col("acheteur_id")
|
+ pl.col(column)
|
||||||
+ '" target="_blank">'
|
+ '" target="_blank">'
|
||||||
+ pl.col("acheteur_id")
|
+ pl.col(column)
|
||||||
+ "</a>"
|
+ "</a>"
|
||||||
).alias("acheteur_id")
|
).alias(column)
|
||||||
)
|
)
|
||||||
return dff
|
return dff
|
||||||
|
|
||||||
|
|
||||||
def add_org_links_in_dict(data: list, org_type: str) -> list:
|
def add_links_in_dict(data: list, org_type: str) -> list:
|
||||||
new_data = []
|
new_data = []
|
||||||
for marche in data:
|
for marche in data:
|
||||||
org_id = marche[org_type + "_id"]
|
org_id = marche[org_type + "_id"]
|
||||||
marche[org_type + "_nom"] = (
|
marche[org_type + "_nom"] = (
|
||||||
f'<a href="/{org_type}s/{org_id}">{marche[org_type + "_nom"]}</a>'
|
f'<a href="/{org_type}s/{org_id}">{marche[org_type + "_nom"]}</a>'
|
||||||
)
|
)
|
||||||
|
marche["id"] = f'<a href="/marches/{marche["uid"]}">{marche["id"]}</a>'
|
||||||
|
marche["uid"] = f'<a href="/marches/{marche["uid"]}">{marche["uid"]}</a>'
|
||||||
new_data.append(marche)
|
new_data.append(marche)
|
||||||
return new_data
|
return new_data
|
||||||
|
|
||||||
@@ -280,7 +284,7 @@ def setup_table_columns(dff, hideable: bool = True, exclude: list = None) -> tup
|
|||||||
|
|
||||||
if column_object:
|
if column_object:
|
||||||
tooltip[column_id] = {
|
tooltip[column_id] = {
|
||||||
"value": f"""**{column_object.get("friendly_name", column_id)}**
|
"value": f"""**{column_object.get("friendly_name")}** ({column_id})
|
||||||
|
|
||||||
"""
|
"""
|
||||||
+ column_object["description"],
|
+ column_object["description"],
|
||||||
@@ -305,3 +309,7 @@ meta_content = {
|
|||||||
|
|
||||||
# Récupération du schéma des données tabulaires
|
# Récupération du schéma des données tabulaires
|
||||||
data_schema: dict = get(os.getenv("DATA_SCHEMA_PATH"), follow_redirects=True).json()
|
data_schema: dict = get(os.getenv("DATA_SCHEMA_PATH"), follow_redirects=True).json()
|
||||||
|
data_schema["source"] = {
|
||||||
|
"description": "Code de la source des données, avec un lien vers le fichier Open Data dont proviennent les données de ce marché public.",
|
||||||
|
"friendly_name": "Source des données",
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user