from dash import Input, Output, State, dash_table, dcc, html from dash.exceptions import PreventUpdate from ..libs.repository.repository import AbstractRepository def layout_factory(repositories: dict[str,AbstractRepository]): def layout(repository_name:str="", schema_name:str="", table_name:str=""): repository = repositories[repository_name] df = repository.read(table=table_name, schema=schema_name) return html.Div([ dcc.Store(id="table_backup"), html.Div([ html.H2([ dcc.Link( f"{repository.name}", href=f"/repository/{repository.name}", className="hover:underline" ), html.Span(" > "), dcc.Link( f"{schema_name}", href=f"/stg/{repository.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 callback_factory(app): @app.callback( Output("datatable", 'editable', allow_duplicate=True), Output("table_backup", 'data'), Input("btn_edit", "n_clicks"), State("datatable", 'data'), prevent_initial_call=True ) def activate_editable(n_clicks, df_src): if n_clicks is None: raise PreventUpdate if n_clicks > 0: df_backup = df_src.copy() return True, df_backup raise PreventUpdate @app.callback( Output("datatable", 'editable', allow_duplicate=True), Output("datatable", 'data', allow_duplicate=True), Input("btn_cancel", "n_clicks"), State("table_backup", 'data'), prevent_initial_call=True ) def cancel_modifications(n_clicks, data): if n_clicks is None: raise PreventUpdate if n_clicks > 0 and data is not None: return False, data.copy() raise PreventUpdate @app.callback( Output("datatable", 'editable'), Output("datatable", 'data'), Input("btn_save", "n_clicks"), State("datatable", 'editable'), ) def save_modifications(n_clicks, editable): if n_clicks is None: raise PreventUpdate if n_clicks > 0: return not editable return editable @app.callback( Output("btn_edit", "style"), Output("btn_save", "style"), Output("btn_cancel", "style"), Input("datatable", "editable"), ) def toolbar(editable): if editable: return {"display": "none"}, {"display": "block"}, {"display": "block"} return {"display": "block"}, {"display": "none"}, {"display": "none"}