From c2513914fadb4157fb0991e8c8182ee42c4fe1c1 Mon Sep 17 00:00:00 2001 From: Jenny Williams Date: Tue, 8 Aug 2023 10:04:22 -0400 Subject: [PATCH] Add cardinality check button to RACK UI (#990) --- rack-ui/pages/verify.py | 117 ++++++++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 47 deletions(-) diff --git a/rack-ui/pages/verify.py b/rack-ui/pages/verify.py index 12dcf6e3..fcd5cff5 100644 --- a/rack-ui/pages/verify.py +++ b/rack-ui/pages/verify.py @@ -12,7 +12,7 @@ DEFAULT_GRAPH_NAME = "uri://DefaultGraph" # dialog confirming ASSIST verification done -verify_assist_done_dialog = dbc.Modal( +verify_assist_done_dialog = dbc.Spinner(dbc.Modal( [ dbc.ModalBody("MESSAGE PLACEHOLDER", id="verify-assist-done-dialog-body"), # message dbc.ModalFooter([ @@ -24,32 +24,32 @@ id="verify-assist-done-dialog", is_open=False, backdrop=False, -) +)) # div showing graphs list -verify_report_options_div = dbc.Spinner(html.Div( +select_graphs_div = dbc.Spinner(html.Div( [ - dcc.Markdown("Select graphs to include in report:"), + dcc.Markdown("Select graphs to include:"), dcc.Checklist([], [], id="verify-graph-checklist", labelStyle={'display': 'block'}), # choose which graphs to verify dbc.Row([ - dbc.Col(html.Button("Continue", id="verify-report-continue-button", n_clicks=0), width="auto"), # button to open SPARQLgraph report - dbc.Col(html.Button("Cancel", id="verify-report-cancel-button", n_clicks=0), width="auto") # button to cancel + dbc.Col(html.Button("Continue", id="select-graphs-continue-button", n_clicks=0), width="auto"), # button to open SPARQLgraph + dbc.Col(html.Button("Cancel", id="select-graphs-cancel-button", n_clicks=0), width="auto") # button to cancel ]) ], - id="verify-report-options-div", + id="select-graphs-div", hidden=True, style={"margin-top": "50px"}, )) -# dialog indicating an error generating the SPARQLgraph report (e.g. no graphs selected) -verify_report_error_dialog = dbc.Modal( +# dialog indicating an error generating the SPARQLgraph link (e.g. no graphs selected) +sg_link_error_dialog = dbc.Modal( [ - dbc.ModalBody("MESSAGE PLACEHOLDER", id="verify-report-error-dialog-body"), # message + dbc.ModalBody("MESSAGE PLACEHOLDER", id="sg-link-error-dialog-body"), # message dbc.ModalFooter([ - html.Button("Close", id="verify-report-error-button", n_clicks=0) # close button + html.Button("Close", id="sg-link-error-button", n_clicks=0) # close button ]), ], - id="verify-report-error-dialog", + id="sg-link-error-dialog", is_open=False, backdrop=False, ) @@ -59,17 +59,20 @@ html.H2('Verify Data'), dcc.Markdown("_Run verification routines on the data loaded in RACK_"), dbc.Row([ - dbc.Col(html.Button("Verify using ASSIST", id="verify-assist-button", n_clicks=0), width="auto"), # button to verify using ASSIST - dbc.Col(html.Button("Verify using report", id="verify-report-button"), width="auto") # button to verify using SPARQLgraph report + dbc.Col(html.Button("Data verification report", id="verify-report-button"), width="auto"), # button to verify using SPARQLgraph data verification report + dbc.Col(html.Button("Cardinality checker", id="cardinality-button"), width="auto"), # button to check cardinality via SPARQLgraph + dbc.Col(html.Button("ASSIST-DV", id="verify-assist-button", n_clicks=0), width="auto") # button to verify using ASSIST ]), - dbc.Tooltip("Run the ASSIST tool and download an error report", target="verify-assist-button"), - dbc.Tooltip("Open SPARQLgraph and run data verification report on selected graphs", target="verify-report-button"), - verify_report_options_div, + dbc.Tooltip("Run the ASSIST-DV tool and download an error report", target="verify-assist-button"), + dbc.Tooltip("Run SPARQLgraph data verification report on selected graphs", target="verify-report-button"), + dbc.Tooltip("Run SPARQLgraph cardinality checker on selected graphs", target="cardinality-button"), + select_graphs_div, html.Div(id="assist-status-div", className="scrollarea"), # displays status verify_assist_done_dialog, - verify_report_error_dialog, + sg_link_error_dialog, dcc.Store("assist-status-filepath"), # stores the filename of the temp file containing status - dcc.Store("sparqlgraph-url"), # stores the URL of the SPARQLgraph report + dcc.Store("report-vs-cardinality"), # stores user choice of SPARQLgraph report or cardinality + dbc.Spinner(dcc.Store("sparqlgraph-url")), # stores the SPARQLgraph URL. Show spinner while generating it. dcc.Store(id="clientside-dummy-store"), # dummy store because callback needs an Output dcc.Interval(id='assist-status-interval', interval=0.5*1000, n_intervals=0, disabled=True), # triggers updating the status display ]) @@ -84,6 +87,7 @@ running=[ (Output("verify-report-button", "disabled"), True, False), # disable the button while running (Output("verify-assist-button", "disabled"), True, False), # disable the button while running + (Output("cardinality-button", "disabled"), True, False), # disable the button while running ], prevent_initial_call=True ) @@ -103,6 +107,7 @@ def create_assist_status_filepath(n_clicks): running=[ (Output("verify-report-button", "disabled"), True, False), # disable the button while running (Output("verify-assist-button", "disabled"), True, False), # disable the button while running + (Output("cardinality-button", "disabled"), True, False), # disable the button while running (Output("assist-status-interval", "disabled"), False, True) # enable the interval component while running ], prevent_initial_call=True @@ -161,26 +166,37 @@ def download_assist_results(n_clicks, status_filepath): return dict(content=file_content, filename="rack_verification_results.txt") -####### callbacks for SPARQLgraph report verification ###################################### +####### callbacks for SPARQLgraph report / cardinality ###################################### @dash.callback( output=[ + Output("report-vs-cardinality", "data"), # remember whether user wanted SPARQLgraph report or cardinality Output("verify-graph-checklist", "options"), # list of graphs populated in the triple store Output("verify-graph-checklist", "value")], # list of graphs to pre-select (graphs recently loaded) - inputs=Input("verify-report-button", "n_clicks"), # triggered by user clicking button + inputs=[ + Input("verify-report-button", "n_clicks"), # triggered by user clicking buttons + Input("cardinality-button", "n_clicks")], state=State("last-loaded-graphs", "data"), # last loaded graphs background=True, # background callback running=[ - (Output("verify-report-button", "disabled"), True, False), # disable the run button while running + (Output("verify-report-button", "disabled"), True, False), # disable the button while running (Output("verify-assist-button", "disabled"), True, False), # disable the button while running + (Output("cardinality-button", "disabled"), True, False), # disable the button while running ], prevent_initial_call=True ) -def show_report_options(button_clicks, last_loaded_graphs): +def show_graphs_checklist(report_button_clicks, cardinality_button_clicks, last_loaded_graphs): """ - Show list of graphs for verification report, with the last loaded graphs pre-selected + Show list of graphs for generating SPARQLgraph link, with the last loaded graphs pre-selected """ + + # remember which button triggered this: report or cardinality + if (get_trigger() == "verify-report-button.n_clicks"): + report_vs_cardinality = True # user wants report + else: + report_vs_cardinality = False # user wants cardinality + # get list of graphs populated in the triple store graphs_list_values = get_graph_info().get_column(0) # list of graphs, including uri://DefaultGraph graphs_list_labels = list(map(lambda x: x.replace(DEFAULT_GRAPH_NAME, 'Optimized graph'), graphs_list_values.copy())) # display default graph as "Optimized graph" @@ -190,24 +206,27 @@ def show_report_options(button_clicks, last_loaded_graphs): if last_loaded_graphs is None: last_loaded_graphs = [] - return graphs_list, last_loaded_graphs + return report_vs_cardinality, graphs_list, last_loaded_graphs @dash.callback( - output=[Output("sparqlgraph-url", "data"), # output SPARQLgraph report URL - Output("verify-report-error-dialog-body", "children")], # output error message - inputs=Input("verify-report-continue-button", "n_clicks"), # triggered by clicking continue button - state=State("verify-graph-checklist", "value"), # the currently selected graphs + output=[Output("sparqlgraph-url", "data"), # output SPARQLgraph URL + Output("sg-link-error-dialog-body", "children")], # output error message + inputs=Input("select-graphs-continue-button", "n_clicks"), # triggered by clicking continue button + state=[ + State("report-vs-cardinality", "data"), # true for report, false for cardinality + State("verify-graph-checklist", "value")], # the currently selected graphs background=True, # background callback running=[ (Output("verify-report-button", "disabled"), True, False), # disable the button while running (Output("verify-assist-button", "disabled"), True, False), # disable the button while running + (Output("cardinality-button", "disabled"), True, False), # disable the button while running ], prevent_initial_call=True ) -def generate_report_link(sg_button_clicks, graphs_selected): +def generate_sg_link(sg_button_clicks, report_vs_cardinality, graphs_selected): """ - Generate the SPARQLgraph report link + Generate the SPARQLgraph link """ # error if no graphs were selected if len(graphs_selected) == 0: @@ -219,14 +238,17 @@ def generate_report_link(sg_button_clicks, graphs_selected): graphs.append(graph) conn = semtk3.build_connection_str("Graphs To Verify", rack.DEFAULT_TRIPLE_STORE_TYPE, rack.DEFAULT_TRIPLE_STORE, graphs, graphs[0], graphs[1:]) # use all graphs for both model and data, to avoid either being empty - # construct SG report URL - sparqlgraph_verify_url_str = semtk3.get_sparqlgraph_url(SPARQLGRAPH_BASE_URL, conn_json_str=str(conn), report_id="report data verification") + # construct SG URL + if(report_vs_cardinality): + sparqlgraph_verify_url_str = semtk3.get_sparqlgraph_url(SPARQLGRAPH_BASE_URL, conn_json_str=str(conn), report_id="report data verification") # URL to generate report + else: + sparqlgraph_verify_url_str = semtk3.get_sparqlgraph_url(SPARQLGRAPH_BASE_URL, conn_json_str=str(conn), explore_restrictions=True) # URL to explore cardinality - # return SPARQLgraph report URL + # return SPARQLgraph URL return sparqlgraph_verify_url_str, None -# Open a browser tab with SPARQLgraph report (this is a clientside callback written in JavaScript: https://dash.plotly.com/clientside-callbacks) +# Open a browser tab with SPARQLgraph link (this is a clientside callback written in JavaScript: https://dash.plotly.com/clientside-callbacks) dash.clientside_callback( """ function(url) { @@ -248,25 +270,26 @@ def generate_report_link(sg_button_clicks, graphs_selected): @callback(Output("assist-status-div", "hidden"), Input("verify-assist-button", "n_clicks"), Input("verify-report-button", "n_clicks"), + Input("cardinality-button", "n_clicks"), prevent_initial_call=True ) -def manage_assist_status_div(assist_clicks, report_clicks): +def manage_assist_status_div(assist_clicks, report_clicks, cardinality_clicks): """ Show or hide the ASSIST status div """ if (get_trigger() in ["verify-assist-button.n_clicks"]): return False # user clicked ASSIST, show the div else: - return True # user clicked report, hide the div + return True # user clicked other button, hide the div -@callback(Output("verify-report-options-div", "hidden"), +@callback(Output("select-graphs-div", "hidden"), Input("verify-graph-checklist", "options"), Input("verify-assist-button", "n_clicks"), - Input("verify-report-cancel-button", "n_clicks"), + Input("select-graphs-cancel-button", "n_clicks"), prevent_initial_call=True ) -def manage_verify_report_options_div(checklist_options, continue_clicks, cancel_clicks): +def manage_select_graphs_div(checklist_options, continue_clicks, cancel_clicks): """ Show or hide the graph checklist div """ - if (get_trigger() in ["verify-assist-button.n_clicks", "verify-report-cancel-button.n_clicks"]): + if (get_trigger() in ["verify-assist-button.n_clicks", "select-graphs-cancel-button.n_clicks"]): return True # continue or cancel button pressed, hide div elif checklist_options == []: return True # no checklist options provided, don't show div @@ -287,14 +310,14 @@ def manage_verify_assist_done_dialog(children, n_clicks): return True # child added, show the dialog -@callback(Output("verify-report-error-dialog", "is_open"), - Input("verify-report-error-dialog-body", "children"), - Input("verify-report-error-button", "n_clicks"), +@callback(Output("sg-link-error-dialog", "is_open"), + Input("sg-link-error-dialog-body", "children"), + Input("sg-link-error-button", "n_clicks"), prevent_initial_call=True ) -def manage_verify_report_error_dialog(children, n_clicks): - """ Show or hide the SPARQLgraph report error dialog (e.g. if no graphs selected) """ - if (get_trigger() == "verify-report-error-button.n_clicks"): +def manage_sg_link_error_dialog(children, n_clicks): + """ Show or hide the SPARQLgraph link error dialog (e.g. if no graphs selected) """ + if (get_trigger() == "sg-link-error-button.n_clicks"): return False # button pressed, hide the dialog else: if children is None: