Ajout d'un menu de navigation

This commit is contained in:
Colin Maudry
2025-04-21 18:09:10 +02:00
parent 75e09b0bc6
commit 60d204b061
6 changed files with 175 additions and 86 deletions
+2 -1
View File
@@ -10,7 +10,8 @@ dependencies = [
"dash",
"polars",
"gunicorn",
"dash-bootstrap-components"
"dash-bootstrap-components",
"python-dotenv"
]
[project.optional-dependencies]
+19 -85
View File
@@ -1,101 +1,35 @@
from dash import Dash, html, dcc, callback, Output, Input, dash_table
import polars as pl
from dash import Dash, html, page_container, page_registry, dcc
import dash_bootstrap_components as dbc
df = pl.read_parquet("/home/colin/git/decp-processing/dist/2025-04-21/decp.parquet")
app = Dash(external_stylesheets=[dbc.themes.UNITED], title="decp.info")
app = Dash(external_stylesheets=[dbc.themes.UNITED], title="decp.info", use_pages=True)
server = app.server
datatable = dash_table.DataTable(
cell_selectable=False,
id="table",
data=df.to_dicts(),
page_size=20,
page_current=0,
page_action="native",
filter_action="native",
filter_options={"case": "insensitive", "placeholder_text": "Filtrer..."},
columns=[
{"name": i, "id": i, "deletable": True, "selectable": False} for i in df.columns
],
selected_columns=[],
selected_rows=[],
sort_action="native",
sort_mode="multi",
export_format="xlsx",
export_columns="visible",
export_headers="ids",
style_cell_conditional=[
{
"if": {"column_id": "objet"},
"minWidth": "300px",
"textAlign": "left",
"overflow": "hidden",
"lineHeight": "14px",
"whiteSpace": "normal",
},
],
)
app.layout = [
html.H1(children="decp.info"),
html.Details(
children=[
html.Summary("Utilisation"),
dcc.Markdown(
"""
**Filtres**
Vous pouvez appliquer un filtre pour chaque colonne en entrant du texte sous le nom de la colonne, puis en tapant sur `Entrée`.
- Champs textuels : la recherche est insensible à la casse (majuscules/minuscules).
- Champs numériques : possibilité d'ajouter < ou > devant le chiffre recherché pour chercher des valeurs inférieures ou supérieur.
**Télécharger le résultat**
Vous pouvez télécharger le résultat de vos filtres et tris en cliquant sur Télécharger au format Excel.
Les colonnes supprimées seront absentes du fichier téléchargé.
Si vous téléchargez un volume important de données, il se peut que vous attendiez quelques minutes avant le début du téléchargement.
"""
),
],
id="instructions",
),
html.Div(
[
"Recherche dans objet : ",
dcc.Input(id="search", value="", type="text"),
]
),
dcc.Loading(
overlay_style={"visibility": "visible", "filter": "blur(2px)"},
id="loading-1",
type="default",
children=datatable,
html.H1("decp.info"),
html.Div(
[
dcc.Link(page["name"], href=page["relative_path"], className="nav")
for page in page_registry.values()
]
),
],
className="navbar",
),
page_container,
]
@callback(
Output(component_id="table", component_property="data", allow_duplicate=True),
Input(component_id="search", component_property="value"),
prevent_initial_call=True,
)
def global_search(text):
new_df = df
new_df = new_df.filter(pl.col("objet").str.contains("(?i)" + text))
return new_df.to_dicts()
# @callback(
# Output("table", "data"), Input("table", "page_current"), Input("table", "page_size")
# Output(component_id="table", component_property="data", allow_duplicate=True),
# Input(component_id="search", component_property="value"),
# prevent_initial_call=True,
# )
# def update_table(page_current, page_size):
# return df[page_current * page_size : (page_current + 1) * page_size].to_dicts()
# def global_search(text):
# new_df = df
# new_df = new_df.filter(pl.col("objet").str.contains("(?i)" + text))
# return new_df.to_dicts()
if __name__ == "__main__":
+41
View File
@@ -17,3 +17,44 @@ input.dash-filter--case {
td[data-dash-column="objet"] {
font-size: 85%;
}
.dash-table-container
.dash-spreadsheet-container
.dash-spreadsheet-inner
th.dash-header {
background-color: #666986;
color: white;
}
.dash-table-container
.dash-spreadsheet-container
.dash-spreadsheet-inner
th.dash-filter {
background-color: #d0d2e6;
}
#header > *,
.dash-spreadsheet-menu button.export {
margin: 0 0 20px 20px;
}
.navbar {
width: 100%;
height: 100px;
padding: 10px;
}
a.nav {
float: left;
margin-right: 40px;
font-size: 120%;
}
h1 {
float: left;
width: 50%;
}
h3 {
display: inline;
}
+9
View File
@@ -0,0 +1,9 @@
from dash import register_page, html, page_registry
title = "À propos"
register_page(
__name__, path="/a-propos", title=f"decp.info - {title}", name=title, order=3
)
layout = [html.H2(title)]
+95
View File
@@ -0,0 +1,95 @@
from dash import (
Dash,
html,
dcc,
callback,
Output,
Input,
dash_table,
page_container,
register_page,
)
from dotenv import load_dotenv
import os
import polars as pl
load_dotenv()
df = pl.read_parquet(os.getenv("DATA_FILE_PARQUET_PATH"))
title = "Tableau"
register_page(__name__, path="/", title=f"decp.info - {title}", name=title, order=1)
datatable = dash_table.DataTable(
cell_selectable=False,
id="table",
data=df.to_dicts(),
page_size=20,
page_current=0,
page_action="native",
filter_action="native",
filter_options={"case": "insensitive", "placeholder_text": "Filtrer..."},
columns=[
{"name": i, "id": i, "deletable": True, "selectable": False} for i in df.columns
],
selected_columns=[],
selected_rows=[],
sort_action="native",
sort_mode="multi",
export_format="xlsx",
export_columns="visible",
export_headers="ids",
style_cell_conditional=[
{
"if": {"column_id": "objet"},
"minWidth": "300px",
"textAlign": "left",
"overflow": "hidden",
"lineHeight": "14px",
"whiteSpace": "normal",
},
],
)
layout = [
html.Div(
html.Details(
children=[
html.Summary(html.H3("Utilisation")),
dcc.Markdown(
"""
**Filtres**
Vous pouvez appliquer un filtre pour chaque colonne en entrant du texte sous le nom de la colonne, puis en tapant sur `Entrée`.
- Champs textuels : la recherche est insensible à la casse (majuscules/minuscules).
- Champs numériques : possibilité d'ajouter < ou > devant le chiffre recherché pour chercher des valeurs inférieures ou supérieur.
**Télécharger le résultat**
Vous pouvez télécharger le résultat de vos filtres et tris en cliquant sur Télécharger au format Excel.
Les colonnes supprimées seront absentes du fichier téléchargé.
Si vous téléchargez un volume important de données, il se peut que vous attendiez quelques minutes avant le début du téléchargement.
"""
),
],
id="instructions",
),
id="header",
),
# html.Div(
# [
# "Recherche dans objet : ",
# dcc.Input(id="search", value="", type="text"),
# ]
# )]),
dcc.Loading(
overlay_style={"visibility": "visible", "filter": "blur(2px)"},
id="loading-1",
type="default",
children=datatable,
),
]
+9
View File
@@ -0,0 +1,9 @@
from dash import register_page, html
title = "Statistiques"
register_page(
__name__, path="/statistiques", title=f"decp.info - {title}", name=title, order=2
)
layout = [html.H2(title)]