Skip to content

Commit

Permalink
Change select groups modal loading behaviour (#208)
Browse files Browse the repository at this point in the history
* Update select groups modal body every data update

* Regardless of whether modal is open or not

* Stop updating whenever modal is opened

* Rollback jQuery UI for faster sortable calls

* Also remove stale TODO
  • Loading branch information
ivansg44 authored Jun 14, 2024
1 parent 96de600 commit a9e6acf
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 30 deletions.
56 changes: 31 additions & 25 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
# callbacks.
external_scripts=[
"https://code.jquery.com/jquery-2.2.4.min.js",
"https://code.jquery.com/ui/1.12.1/jquery-ui.min.js",
"https://code.jquery.com/ui/1.11.4/jquery-ui.min.js",
],
# We can use bootstrap CSS.
# https://bit.ly/3tMqY0W for details.
Expand Down Expand Up @@ -590,54 +590,59 @@ def update_hidden_strains(_, deleted_strain, checkbox_ids, checkbox_vals,


@app.callback(
Output("select-lineages-modal", "is_open"),
Output("select-lineages-modal-body", "children"),
Input("get-data-args", "data"),
State("last-data-mtime", "data"),
prevent_initial_call=True
)
def update_select_lineages_modal_body(get_data_args, last_data_mtime):
"""Populate select lineages modal body.
This is triggered behind the scenes without opening the modal, and
whenever the data is updated.
:param get_data_args: Args for ``get_data``
:type get_data_args: dict
:param last_data_mtime: Last mtime across all data files
:type last_data_mtime: float
:return: Content representing the select lineages modal body
:rtype: list[dbc.FormGroup]
"""
data = read_data(get_data_args, last_data_mtime)
return toolbar_generator.get_select_lineages_modal_body(data)


@app.callback(
Output("select-lineages-modal", "is_open"),
Output("select-lineages-modal-loading", "children"),
Input("open-select-lineages-modal-btn", "n_clicks"),
Input("select-lineages-ok-btn", "n_clicks"),
Input("select-lineages-cancel-btn", "n_clicks"),
Input("deleted-strain", "data"),
State("get-data-args", "data"),
State("last-data-mtime", "data"),
prevent_initial_call=True
)
def toggle_select_lineages_modal(_, __, ___, ____, get_data_args,
last_data_mtime):
def toggle_select_lineages_modal(_, __, ___, ____):
"""Open or close select lineages modal.
Not only is this function in charge of opening or closing the
select lineages modal, it is also in charge of dynamically
populating the select lineages modal body when the modal is opened.
This is a little slow to open, so we return
``select-lineages-modal-loading`` to add a spinner.
:param _: Select lineages button in toolbar was clicked
:param __: OK button in select lineages modal was clicked
:param ___: Cancel button in select lineages modal was clicked
:param ____: OK button in confirm strain deletion modal was clicked
:param get_data_args: Args for ``get_data``
:type get_data_args: dict
:param last_data_mtime: Last mtime across all data files
:type last_data_mtime: float
:return: Boolean representing whether the select lineages modal is
open or closed, content representing the select lineages
modal body, and ``select-lineages-modal-loading`` children.
:rtype: (bool, list[dbc.FormGroup])
open or closed, and ``select-lineages-modal-loading`` children.
:rtype: (bool, bool)
"""
# Current ``get_data`` return val
data = read_data(get_data_args, last_data_mtime)

ctx = dash.callback_context
triggered_prop_id = ctx.triggered[0]["prop_id"]
# We only open the modal when the select lineages modal btn in the
# toolbar is clicked.
if triggered_prop_id == "open-select-lineages-modal-btn.n_clicks":
modal_body = toolbar_generator.get_select_lineages_modal_body(data)
return True, modal_body, None
return True, None
else:
# No need to populate modal body if the modal is closed
return False, None, None
return False, None


@app.callback(
Expand Down Expand Up @@ -1410,7 +1415,8 @@ def update_data(get_data_args, last_data_mtime):
function_name="makeSelectLineagesModalCheckboxesDraggable"
),
Output("make-select-lineages-modal-checkboxes-draggable", "data"),
Input({"type": "select-lineages-modal-checklist", "index": ALL}, "id"),
Input("select-lineages-modal", "is_open"),
State({"type": "select-lineages-modal-checklist", "index": ALL}, "id"),
prevent_initial_call=True
)
app.clientside_callback(
Expand Down
3 changes: 2 additions & 1 deletion assets/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ window.dash_clientside = Object.assign({}, window.dash_clientside, {
/**
* Make the checkboxes in the select lineage modal draggable within their
* respective form groups, using the JQuery UI sortable plugin.
* @param _ Select lineages modal was opened.
* @param {Array<Object>} idArray Dash pattern matching id values for
* checkboxes in select lineages modal.
* @return {Boolean} ``true`` if we successfully made the checkboxes
* draggable.
*/
makeSelectLineagesModalCheckboxesDraggable: (idArray) => {
makeSelectLineagesModalCheckboxesDraggable: (_, idArray) => {
// This function responds to all changes in the select lineages modal
// body. But the checkboxes disappear when the modal is closed, so we
// should do nothing when that happens.
Expand Down
10 changes: 6 additions & 4 deletions generators/toolbar_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def get_toolbar_row(data):
className="my-auto pl-xl-5",
width=2
),
get_select_lineages_modal(),
get_select_lineages_modal(data),
get_confirm_strain_del_modal(),
get_jump_to_modal()
],
Expand All @@ -87,19 +87,21 @@ def get_select_lineages_toolbar_btn():
className="mr-2")


def get_select_lineages_modal():
def get_select_lineages_modal(data):
"""Returns select lineages modal.
This modal is initially closed, and the body is empty.
This modal is initially closed.
:param data: ``get_data`` return value
:type data: dict
:return: Initially closed Dash Bootstrap Components modal for
selecting lineages.
:rtype: dbc.Modal
"""
return dbc.Modal([
dbc.ModalHeader("Select sample groups"),
# Empty at launch; populated when user opens modal
dbc.ModalBody(None,
dbc.ModalBody(get_select_lineages_modal_body(data),
id="select-lineages-modal-body",
style={"height": "50vh", "overflowY": "scroll"}),
dbc.ModalFooter(get_select_lineages_modal_footer())
Expand Down

0 comments on commit a9e6acf

Please sign in to comment.