Tableau de choix des colonnes aussi sur les pages acheteur et titulaire
This commit is contained in:
@@ -354,15 +354,17 @@ table.cell-table th {
|
||||
position: relative;
|
||||
width: 180px;
|
||||
margin: 0 0 10px 0;
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*
|
||||
.show-hide::before {
|
||||
background: inherit;
|
||||
content: "Colonnes affichées";
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
|
||||
#column_list .show-hide,
|
||||
#table .show-hide {
|
||||
@@ -371,7 +373,7 @@ table.cell-table th {
|
||||
|
||||
.show-hide-menu-item > input {
|
||||
margin-right: 10px;
|
||||
}
|
||||
} */
|
||||
|
||||
/* Tooltips */
|
||||
.dash-tooltip,
|
||||
|
||||
+59
-5
@@ -6,10 +6,10 @@ import plotly.graph_objects as go
|
||||
import polars as pl
|
||||
from dash import dash_table, dcc, html
|
||||
|
||||
from src.utils import data_schema, format_number
|
||||
from src.utils import data_schema, df, format_number
|
||||
|
||||
|
||||
def get_map_count_marches(df: pl.DataFrame):
|
||||
def get_map_count_marches():
|
||||
lf = df.lazy()
|
||||
lf = lf.with_columns(
|
||||
pl.col("lieuExecution_code").str.head(2).str.zfill(2).alias("Département")
|
||||
@@ -31,16 +31,16 @@ def get_map_count_marches(df: pl.DataFrame):
|
||||
for f in departements["features"]:
|
||||
f["id"] = f["properties"]["code"]
|
||||
|
||||
df = lf.collect(engine="streaming")
|
||||
df_map = lf.collect(engine="streaming")
|
||||
|
||||
fig = px.choropleth(
|
||||
df,
|
||||
df_map,
|
||||
geojson=departements,
|
||||
locations="Département",
|
||||
color="uid",
|
||||
color_continuous_scale="Reds",
|
||||
title="Nombres de marchés attribués par département (lieu d'exécution)",
|
||||
range_color=(df["uid"].min(), df["uid"].max()),
|
||||
range_color=(df_map["uid"].min(), df_map["uid"].max()),
|
||||
labels={"uid": "Marchés attribués"},
|
||||
scope="europe",
|
||||
width=900,
|
||||
@@ -414,3 +414,57 @@ def get_duplicate_matrix() -> html.Div:
|
||||
dcc.Graph(figure=fig),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def make_column_picker(page: str):
|
||||
table_data = []
|
||||
table_columns = [
|
||||
{
|
||||
"id": col,
|
||||
"name": data_schema[col]["title"],
|
||||
"description": data_schema[col]["description"],
|
||||
}
|
||||
for col in df.columns
|
||||
]
|
||||
for column in table_columns:
|
||||
new_column = {
|
||||
"id": column["id"],
|
||||
"name": column["name"],
|
||||
"description": data_schema[column["id"]]["description"],
|
||||
}
|
||||
table_data.append(new_column)
|
||||
|
||||
table = (
|
||||
DataTable(
|
||||
row_selectable="multi",
|
||||
data=table_data,
|
||||
filter_action="native",
|
||||
sort_action="none",
|
||||
style_cell={
|
||||
"textAlign": "left",
|
||||
},
|
||||
columns=[
|
||||
{
|
||||
"name": "Nom",
|
||||
"id": "name",
|
||||
},
|
||||
{
|
||||
"name": "Description",
|
||||
"id": "description",
|
||||
},
|
||||
],
|
||||
style_cell_conditional=[
|
||||
{
|
||||
"if": {"column_id": "description"},
|
||||
"minWidth": "450px",
|
||||
"overflow": "hidden",
|
||||
"lineHeight": "18px",
|
||||
"whiteSpace": "normal",
|
||||
}
|
||||
],
|
||||
page_action="none",
|
||||
dtid=f"{page}_column_list",
|
||||
),
|
||||
)
|
||||
|
||||
return table
|
||||
|
||||
+83
-1
@@ -1,11 +1,13 @@
|
||||
import datetime
|
||||
|
||||
import dash_bootstrap_components as dbc
|
||||
import polars as pl
|
||||
from dash import Input, Output, State, callback, dcc, html, register_page
|
||||
|
||||
from src.callbacks import get_top_org_table
|
||||
from src.figures import DataTable, point_on_map
|
||||
from src.figures import DataTable, make_column_picker, point_on_map
|
||||
from src.utils import (
|
||||
columns,
|
||||
df,
|
||||
df_acheteurs,
|
||||
filter_table_data,
|
||||
@@ -53,6 +55,7 @@ datatable = html.Div(
|
||||
|
||||
layout = [
|
||||
dcc.Store(id="acheteur_data", storage_type="memory"),
|
||||
dcc.Store(id="acheteur-hidden-columns", storage_type="memory"),
|
||||
dcc.Location(id="acheteur_url", refresh="callback-nav"),
|
||||
html.Div(
|
||||
children=[
|
||||
@@ -133,6 +136,12 @@ layout = [
|
||||
children=[
|
||||
html.Div(
|
||||
[
|
||||
# Bouton modal des colonnes affichées
|
||||
dbc.Button(
|
||||
"Colonnes affichées",
|
||||
id="acheteur_columns_open",
|
||||
className="column_list",
|
||||
),
|
||||
html.P("lignes", id="acheteur_nb_rows"),
|
||||
html.Button(
|
||||
"Téléchargement désactivé au-delà de 65 000 lignes",
|
||||
@@ -144,6 +153,30 @@ layout = [
|
||||
],
|
||||
className="table-menu",
|
||||
),
|
||||
dbc.Modal(
|
||||
[
|
||||
dbc.ModalHeader(
|
||||
dbc.ModalTitle("Choix des colonnes à afficher")
|
||||
),
|
||||
dbc.ModalBody(
|
||||
id="acheteur_columns_body",
|
||||
children=make_column_picker("acheteur"),
|
||||
),
|
||||
dbc.ModalFooter(
|
||||
dbc.Button(
|
||||
"Fermer",
|
||||
id="acheteur_columns_close",
|
||||
className="ms-auto",
|
||||
n_clicks=0,
|
||||
)
|
||||
),
|
||||
],
|
||||
id="acheteur_columns",
|
||||
is_open=False,
|
||||
fullscreen="md-down",
|
||||
scrollable=True,
|
||||
size="xl",
|
||||
),
|
||||
datatable,
|
||||
],
|
||||
),
|
||||
@@ -333,3 +366,52 @@ def download_filtered_acheteur_data(
|
||||
return dcc.send_bytes(
|
||||
to_bytes, filename=f"decp_filtrées_{acheteur_nom}_{date}.xlsx"
|
||||
)
|
||||
|
||||
|
||||
@callback(
|
||||
Output("acheteur-hidden-columns", "data", allow_duplicate=True),
|
||||
Input("acheteur_column_list", "selected_rows"),
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def update_hidden_columns_from_checkboxes(selected_columns):
|
||||
if selected_columns:
|
||||
selected_columns = [columns[i] for i in selected_columns]
|
||||
hidden_columns = [col for col in columns if col not in selected_columns]
|
||||
return hidden_columns
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
@callback(
|
||||
Output("acheteur_datatable", "hidden_columns", allow_duplicate=True),
|
||||
Input(
|
||||
"acheteur-hidden-columns",
|
||||
"data",
|
||||
),
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def store_hidden_columns(hidden_columns):
|
||||
return hidden_columns
|
||||
|
||||
|
||||
@callback(
|
||||
Output("acheteur_column_list", "selected_rows"),
|
||||
Input("acheteur_datatable", "hidden_columns"),
|
||||
State("acheteur_column_list", "selected_rows"), # pour éviter la boucle infinie
|
||||
)
|
||||
def update_checkboxes_from_hidden_columns(hidden_cols, current_checkboxes):
|
||||
# Show all columns that are NOT hidden
|
||||
visible_cols = [columns.index(col) for col in columns if col not in hidden_cols]
|
||||
return visible_cols
|
||||
|
||||
|
||||
@callback(
|
||||
Output("acheteur_columns", "is_open"),
|
||||
Input("acheteur_columns_open", "n_clicks"),
|
||||
Input("acheteur_columns_close", "n_clicks"),
|
||||
State("acheteur_columns", "is_open"),
|
||||
)
|
||||
def toggle_acheteur_columns(click_open, click_close, is_open):
|
||||
if click_open or click_close:
|
||||
return not is_open
|
||||
return is_open
|
||||
|
||||
+9
-66
@@ -19,10 +19,10 @@ from dash import (
|
||||
register_page,
|
||||
)
|
||||
|
||||
from figures import make_column_picker
|
||||
from src.figures import DataTable
|
||||
from src.utils import (
|
||||
columns,
|
||||
data_schema,
|
||||
df,
|
||||
filter_table_data,
|
||||
get_default_hidden_columns,
|
||||
@@ -63,66 +63,6 @@ datatable = html.Div(
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def make_tableau_columns_table():
|
||||
table_data = []
|
||||
table_columns = [
|
||||
{
|
||||
"id": col,
|
||||
"name": data_schema[col]["title"],
|
||||
"description": data_schema[col]["description"],
|
||||
}
|
||||
for col in df.columns
|
||||
]
|
||||
for column in table_columns:
|
||||
new_column = {
|
||||
"id": column["id"],
|
||||
"name": column["name"],
|
||||
"description": data_schema[column["id"]]["description"],
|
||||
}
|
||||
table_data.append(new_column)
|
||||
|
||||
table = (
|
||||
DataTable(
|
||||
row_selectable="multi",
|
||||
data=table_data,
|
||||
filter_action="native",
|
||||
sort_action="none",
|
||||
style_cell={
|
||||
"textAlign": "left",
|
||||
},
|
||||
columns=[
|
||||
{
|
||||
"name": "Nom",
|
||||
"id": "name",
|
||||
},
|
||||
{
|
||||
"name": "Description",
|
||||
"id": "description",
|
||||
},
|
||||
{
|
||||
"name": "column_id",
|
||||
"id": "id",
|
||||
},
|
||||
],
|
||||
hidden_columns=["id"],
|
||||
style_cell_conditional=[
|
||||
{
|
||||
"if": {"column_id": "description"},
|
||||
"minWidth": "450px",
|
||||
"overflow": "hidden",
|
||||
"lineHeight": "18px",
|
||||
"whiteSpace": "normal",
|
||||
}
|
||||
],
|
||||
page_action="none",
|
||||
dtid="column_list",
|
||||
),
|
||||
)
|
||||
|
||||
return table
|
||||
|
||||
|
||||
layout = [
|
||||
dcc.Location(id="tableau_url", refresh=False),
|
||||
dcc.Store(id="filter-cleanup-trigger"),
|
||||
@@ -199,6 +139,7 @@ layout = [
|
||||
children=[
|
||||
html.Div(
|
||||
[
|
||||
# Modal du mode d'emploi
|
||||
dbc.Button("Mode d'emploi", id="tableau_help_open"),
|
||||
dbc.Modal(
|
||||
[
|
||||
@@ -246,7 +187,7 @@ layout = [
|
||||
|
||||
##### Partager une vue
|
||||
|
||||
Une vue est un ensemble de filtres, de tris et de choix de colonnes que vous avez appliqué. Cliquez sur l'icône <img src="/assets/copy.svg" alt="drawing" width="20"/> pour copier une adresse Web qui reproduit la vue courante à l'identique : en la collant dans la barre d'adresse d'un navigateur, vous ouvrez la vue Tableau avec les mêmes paramètres.
|
||||
Une vue est un ensemble de filtres, de tris et de choix de colonnes que vous avez appliqués. Cliquez sur l'icône <img src="/assets/copy.svg" alt="drawing" width="20"/> pour copier une adresse Web qui reproduit la vue courante à l'identique : en la collant dans la barre d'adresse d'un navigateur, vous ouvrez la vue Tableau avec les mêmes paramètres.
|
||||
|
||||
Pratique pour partager une vue avec un·e collègue, sur les réseaux sociaux, ou la sauvegarder pour plus tard.
|
||||
|
||||
@@ -277,6 +218,7 @@ layout = [
|
||||
scrollable=True,
|
||||
size="lg",
|
||||
),
|
||||
# Bouton modal des colonnes affichées
|
||||
dbc.Button(
|
||||
"Colonnes affichées",
|
||||
id="tableau_columns_open",
|
||||
@@ -300,7 +242,8 @@ layout = [
|
||||
[
|
||||
dbc.ModalHeader(dbc.ModalTitle("Choix des colonnes à afficher")),
|
||||
dbc.ModalBody(
|
||||
id="tableau_columns_body", children=make_tableau_columns_table()
|
||||
id="tableau_columns_body",
|
||||
children=make_column_picker("tableau"),
|
||||
),
|
||||
dbc.ModalFooter(
|
||||
dbc.Button(
|
||||
@@ -502,7 +445,7 @@ def toggle_tableau_help(click_open, click_close, is_open):
|
||||
|
||||
@callback(
|
||||
Output("tableau-hidden-columns", "data", allow_duplicate=True),
|
||||
Input("column_list", "selected_rows"),
|
||||
Input("tableau_column_list", "selected_rows"),
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def update_hidden_columns_from_checkboxes(selected_columns):
|
||||
@@ -527,9 +470,9 @@ def store_hidden_columns(hidden_columns):
|
||||
|
||||
|
||||
@callback(
|
||||
Output("column_list", "selected_rows"),
|
||||
Output("tableau_column_list", "selected_rows"),
|
||||
Input("table", "hidden_columns"),
|
||||
State("column_list", "selected_rows"), # pour éviter la boucle infinie
|
||||
State("tableau_column_list", "selected_rows"), # pour éviter la boucle infinie
|
||||
)
|
||||
def update_checkboxes_from_hidden_columns(hidden_cols, current_checkboxes):
|
||||
# Show all columns that are NOT hidden
|
||||
|
||||
+83
-1
@@ -1,11 +1,13 @@
|
||||
import datetime
|
||||
|
||||
import dash_bootstrap_components as dbc
|
||||
import polars as pl
|
||||
from dash import Input, Output, State, callback, dcc, html, register_page
|
||||
|
||||
from src.callbacks import get_top_org_table
|
||||
from src.figures import DataTable, point_on_map
|
||||
from src.figures import DataTable, make_column_picker, point_on_map
|
||||
from src.utils import (
|
||||
columns,
|
||||
df,
|
||||
df_titulaires,
|
||||
filter_table_data,
|
||||
@@ -53,6 +55,7 @@ datatable = html.Div(
|
||||
|
||||
layout = [
|
||||
dcc.Store(id="titulaire_data", storage_type="memory"),
|
||||
dcc.Store(id="titulaire-hidden-columns", storage_type="memory"),
|
||||
dcc.Location(id="titulaire_url", refresh="callback-nav"),
|
||||
html.Div(
|
||||
children=[
|
||||
@@ -132,6 +135,12 @@ layout = [
|
||||
children=[
|
||||
html.Div(
|
||||
[
|
||||
# Bouton modal des colonnes affichées
|
||||
dbc.Button(
|
||||
"Colonnes affichées",
|
||||
id="titulaire_columns_open",
|
||||
className="column_list",
|
||||
),
|
||||
html.P("lignes", id="titulaire_nb_rows"),
|
||||
html.Button(
|
||||
"Téléchargement désactivé au-delà de 65 000 lignes",
|
||||
@@ -142,6 +151,30 @@ layout = [
|
||||
],
|
||||
className="table-menu",
|
||||
),
|
||||
dbc.Modal(
|
||||
[
|
||||
dbc.ModalHeader(
|
||||
dbc.ModalTitle("Choix des colonnes à afficher")
|
||||
),
|
||||
dbc.ModalBody(
|
||||
id="titulaire_columns_body",
|
||||
children=make_column_picker("titulaire"),
|
||||
),
|
||||
dbc.ModalFooter(
|
||||
dbc.Button(
|
||||
"Fermer",
|
||||
id="titulaire_columns_close",
|
||||
className="ms-auto",
|
||||
n_clicks=0,
|
||||
)
|
||||
),
|
||||
],
|
||||
id="titulaire_columns",
|
||||
is_open=False,
|
||||
fullscreen="md-down",
|
||||
scrollable=True,
|
||||
size="xl",
|
||||
),
|
||||
datatable,
|
||||
],
|
||||
),
|
||||
@@ -346,3 +379,52 @@ def download_filtered_titulaire_data(
|
||||
return dcc.send_bytes(
|
||||
to_bytes, filename=f"decp_filtrées_{titulaire_nom}_{date}.xlsx"
|
||||
)
|
||||
|
||||
|
||||
@callback(
|
||||
Output("titulaire-hidden-columns", "data", allow_duplicate=True),
|
||||
Input("titulaire_column_list", "selected_rows"),
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def update_hidden_columns_from_checkboxes(selected_columns):
|
||||
if selected_columns:
|
||||
selected_columns = [columns[i] for i in selected_columns]
|
||||
hidden_columns = [col for col in columns if col not in selected_columns]
|
||||
return hidden_columns
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
@callback(
|
||||
Output("titulaire_datatable", "hidden_columns", allow_duplicate=True),
|
||||
Input(
|
||||
"titulaire-hidden-columns",
|
||||
"data",
|
||||
),
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def store_hidden_columns(hidden_columns):
|
||||
return hidden_columns
|
||||
|
||||
|
||||
@callback(
|
||||
Output("titulaire_column_list", "selected_rows"),
|
||||
Input("titulaire_datatable", "hidden_columns"),
|
||||
State("titulaire_column_list", "selected_rows"), # pour éviter la boucle infinie
|
||||
)
|
||||
def update_checkboxes_from_hidden_columns(hidden_cols, current_checkboxes):
|
||||
# Show all columns that are NOT hidden
|
||||
visible_cols = [columns.index(col) for col in columns if col not in hidden_cols]
|
||||
return visible_cols
|
||||
|
||||
|
||||
@callback(
|
||||
Output("titulaire_columns", "is_open"),
|
||||
Input("titulaire_columns_open", "n_clicks"),
|
||||
Input("titulaire_columns_close", "n_clicks"),
|
||||
State("titulaire_columns", "is_open"),
|
||||
)
|
||||
def toggle_titulaire_columns(click_open, click_close, is_open):
|
||||
if click_open or click_close:
|
||||
return not is_open
|
||||
return is_open
|
||||
|
||||
Reference in New Issue
Block a user