Feat: put table's callback and layout in factory
This commit is contained in:
parent
612df0a8eb
commit
7fb7bc6f5c
@ -1,6 +1,7 @@
|
|||||||
import dash
|
import dash
|
||||||
from dash import Dash, html, dcc
|
from dash import Dash, html, dcc
|
||||||
from .pages import home, config, stage, schema, table
|
from .pages import home, config, stage, schema, table
|
||||||
|
from .datalake import stages
|
||||||
|
|
||||||
external_scripts = [
|
external_scripts = [
|
||||||
{'src': 'https://cdn.tailwindcss.com'}
|
{'src': 'https://cdn.tailwindcss.com'}
|
||||||
@ -36,8 +37,9 @@ dash.register_page(
|
|||||||
dash.register_page(
|
dash.register_page(
|
||||||
table.__name__,
|
table.__name__,
|
||||||
path_template='/stg/<stage_name>/schm/<schema_name>/table/<table_name>',
|
path_template='/stg/<stage_name>/schm/<schema_name>/table/<table_name>',
|
||||||
layout=table.layout
|
layout=table.layout_factory(stages)
|
||||||
)
|
)
|
||||||
|
table.callback_factory(app)
|
||||||
|
|
||||||
app.layout = html.Div([
|
app.layout = html.Div([
|
||||||
html.Div([
|
html.Div([
|
||||||
|
@ -1,126 +1,128 @@
|
|||||||
from dash import html, dcc, dash_table, callback, Input, Output, State
|
from dash import html, dcc, dash_table, Input, Output, State
|
||||||
from dash.exceptions import PreventUpdate
|
from dash.exceptions import PreventUpdate
|
||||||
from ..datalake import stages
|
|
||||||
from ..libs.stage.stage import AbstractStage
|
from ..libs.stage.stage import AbstractStage
|
||||||
|
|
||||||
|
def layout_factory(stages: list[AbstractStage]):
|
||||||
|
def layout(stage_name=None, schema_name=None, table_name=None):
|
||||||
|
stage = stages[stage_name]
|
||||||
|
df = stage.read(table=table_name, schema=schema_name)
|
||||||
|
return html.Div([
|
||||||
|
dcc.Store(id="table_backup"),
|
||||||
|
html.Div([
|
||||||
|
html.H2([
|
||||||
|
dcc.Link(
|
||||||
|
f"{stage.name}",
|
||||||
|
href=f"/stage/{stage.name}",
|
||||||
|
className="hover:underline"
|
||||||
|
),
|
||||||
|
html.Span(" > "),
|
||||||
|
dcc.Link(
|
||||||
|
f"{schema_name}",
|
||||||
|
href=f"/stg/{stage.name}/schema/{schema_name}",
|
||||||
|
className="hover:underline"
|
||||||
|
),
|
||||||
|
html.Span(" > "),
|
||||||
|
html.Span(table_name),
|
||||||
|
],
|
||||||
|
className="text-2xl"
|
||||||
|
),
|
||||||
|
html.Div([
|
||||||
|
html.Button(
|
||||||
|
"Editer",
|
||||||
|
id="btn_edit",
|
||||||
|
className="rounded border px-2 py-1",
|
||||||
|
style={"display": "block"}
|
||||||
|
),
|
||||||
|
html.Button(
|
||||||
|
"Sauver",
|
||||||
|
id="btn_save",
|
||||||
|
className="rounded border px-2 py-1 border-green-500 hover:bg-green-500",
|
||||||
|
style={"display": "none"}
|
||||||
|
),
|
||||||
|
html.Button(
|
||||||
|
"Annuler",
|
||||||
|
id="btn_cancel",
|
||||||
|
className="rounded border px-2 py-1 border-red-500 hover:bg-red-500",
|
||||||
|
style={"display": "none"}
|
||||||
|
),
|
||||||
|
],
|
||||||
|
className="flex flex-row space-x-2",
|
||||||
|
id="toolbar"
|
||||||
|
),
|
||||||
|
],
|
||||||
|
className="flex flex-row justify-between p-4"
|
||||||
|
),
|
||||||
|
html.Div([
|
||||||
|
html.Div([
|
||||||
|
dash_table.DataTable(
|
||||||
|
id="datatable",
|
||||||
|
data=df.to_dict('records'),
|
||||||
|
columns=[{"name": i, "id": i} for i in df.columns],
|
||||||
|
filter_action="native",
|
||||||
|
sort_action="native",
|
||||||
|
sort_mode="multi",
|
||||||
|
editable=False
|
||||||
|
)
|
||||||
|
])
|
||||||
|
],
|
||||||
|
className="overflow-y-auto"
|
||||||
|
),
|
||||||
|
],
|
||||||
|
className="p-2"
|
||||||
|
)
|
||||||
|
return layout
|
||||||
|
|
||||||
def layout(stage_name=None, schema_name=None, table_name=None):
|
|
||||||
stage = stages[stage_name]
|
def callback_factory(app):
|
||||||
df = stage.read(table=table_name, schema=schema_name)
|
@app.callback(
|
||||||
return html.Div([
|
Output("datatable", 'editable', allow_duplicate=True),
|
||||||
dcc.Store(id="table_backup"),
|
Output("table_backup", 'data'),
|
||||||
html.Div([
|
Input("btn_edit", "n_clicks"),
|
||||||
html.H2([
|
State("datatable", 'data'),
|
||||||
dcc.Link(
|
prevent_initial_call=True
|
||||||
f"{stage.name}",
|
|
||||||
href=f"/stage/{stage.name}",
|
|
||||||
className="hover:underline"
|
|
||||||
),
|
|
||||||
html.Span(" > "),
|
|
||||||
dcc.Link(
|
|
||||||
f"{schema_name}",
|
|
||||||
href=f"/stg/{stage.name}/schema/{schema_name}",
|
|
||||||
className="hover:underline"
|
|
||||||
),
|
|
||||||
html.Span(" > "),
|
|
||||||
html.Span(table_name),
|
|
||||||
],
|
|
||||||
className="text-2xl"
|
|
||||||
),
|
|
||||||
html.Div([
|
|
||||||
html.Button(
|
|
||||||
"Editer",
|
|
||||||
id="btn_edit",
|
|
||||||
className="rounded border px-2 py-1",
|
|
||||||
style={"display": "block"}
|
|
||||||
),
|
|
||||||
html.Button(
|
|
||||||
"Sauver",
|
|
||||||
id="btn_save",
|
|
||||||
className="rounded border px-2 py-1 border-green-500 hover:bg-green-500",
|
|
||||||
style={"display": "none"}
|
|
||||||
),
|
|
||||||
html.Button(
|
|
||||||
"Annuler",
|
|
||||||
id="btn_cancel",
|
|
||||||
className="rounded border px-2 py-1 border-red-500 hover:bg-red-500",
|
|
||||||
style={"display": "none"}
|
|
||||||
),
|
|
||||||
],
|
|
||||||
className="flex flex-row space-x-2",
|
|
||||||
id="toolbar"
|
|
||||||
),
|
|
||||||
],
|
|
||||||
className="flex flex-row justify-between p-4"
|
|
||||||
),
|
|
||||||
html.Div([
|
|
||||||
html.Div([
|
|
||||||
dash_table.DataTable(
|
|
||||||
id="datatable",
|
|
||||||
data=df.to_dict('records'),
|
|
||||||
columns=[{"name": i, "id": i} for i in df.columns],
|
|
||||||
filter_action="native",
|
|
||||||
sort_action="native",
|
|
||||||
sort_mode="multi",
|
|
||||||
editable=False
|
|
||||||
)
|
|
||||||
])
|
|
||||||
],
|
|
||||||
className="overflow-y-auto"
|
|
||||||
),
|
|
||||||
],
|
|
||||||
className="p-2"
|
|
||||||
)
|
)
|
||||||
|
def activate_editable(n_clicks, df_src):
|
||||||
|
if n_clicks is None:
|
||||||
@callback(
|
raise PreventUpdate
|
||||||
Output("datatable", 'editable', allow_duplicate=True),
|
if n_clicks > 0:
|
||||||
Output("table_backup", 'data'),
|
df_backup = df_src.copy()
|
||||||
Input("btn_edit", "n_clicks"),
|
return True, df_backup
|
||||||
State("datatable", 'data'),
|
|
||||||
prevent_initial_call=True
|
|
||||||
)
|
|
||||||
def activate_editable(n_clicks, df_src):
|
|
||||||
if n_clicks is None:
|
|
||||||
raise PreventUpdate
|
raise PreventUpdate
|
||||||
if n_clicks > 0:
|
|
||||||
df_backup = df_src.copy()
|
|
||||||
return True, df_backup
|
|
||||||
raise PreventUpdate
|
|
||||||
|
|
||||||
@callback(
|
@app.callback(
|
||||||
Output("datatable", 'editable'),
|
Output("datatable", 'editable', allow_duplicate=True),
|
||||||
Output("datatable", 'data'),
|
Output("datatable", 'data', allow_duplicate=True),
|
||||||
Input("btn_cancel", "n_clicks"),
|
Input("btn_cancel", "n_clicks"),
|
||||||
State("table_backup", 'data'),
|
State("table_backup", 'data'),
|
||||||
prevent_initial_call=True
|
prevent_initial_call=True
|
||||||
)
|
)
|
||||||
def cancel_modifications(n_clicks, data):
|
def cancel_modifications(n_clicks, data):
|
||||||
if n_clicks is None:
|
if n_clicks is None:
|
||||||
|
raise PreventUpdate
|
||||||
|
if n_clicks > 0 and data is not None:
|
||||||
|
return False, data.copy()
|
||||||
raise PreventUpdate
|
raise PreventUpdate
|
||||||
if n_clicks > 0 and data is not None:
|
|
||||||
return False, data.copy()
|
|
||||||
raise PreventUpdate
|
|
||||||
|
|
||||||
# @callback(
|
@app.callback(
|
||||||
# Output("datatable", 'editable'),
|
Output("datatable", 'editable'),
|
||||||
# Input("btn_save", "n_clicks"),
|
Output("datatable", 'data'),
|
||||||
# State("datatable", 'editable'),
|
Input("btn_save", "n_clicks"),
|
||||||
# )
|
State("datatable", 'editable'),
|
||||||
# def save_modifications(n_clicks, editable):
|
)
|
||||||
# if n_clicks is None:
|
def save_modifications(n_clicks, editable):
|
||||||
# raise PreventUpdate
|
if n_clicks is None:
|
||||||
# if n_clicks > 0:
|
raise PreventUpdate
|
||||||
# return not editable
|
if n_clicks > 0:
|
||||||
# return editable
|
return not editable
|
||||||
|
return editable
|
||||||
|
|
||||||
@callback(
|
@app.callback(
|
||||||
Output("btn_edit", "style"),
|
Output("btn_edit", "style"),
|
||||||
Output("btn_save", "style"),
|
Output("btn_save", "style"),
|
||||||
Output("btn_cancel", "style"),
|
Output("btn_cancel", "style"),
|
||||||
Input("datatable", "editable"),
|
Input("datatable", "editable"),
|
||||||
)
|
)
|
||||||
def toolbar(editable):
|
def toolbar(editable):
|
||||||
if editable:
|
if editable:
|
||||||
return {"display": "none"}, {"display": "block"}, {"display": "block"}
|
return {"display": "none"}, {"display": "block"}, {"display": "block"}
|
||||||
return {"display": "block"}, {"display": "none"}, {"display": "none"}
|
return {"display": "block"}, {"display": "none"}, {"display": "none"}
|
||||||
|
Loading…
Reference in New Issue
Block a user