Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable buttons until required inputs supplied #126

Merged
merged 8 commits into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 21 additions & 4 deletions dp_creator_ii/app/analysis_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def analysis_ui():
log_slider("log_epsilon_slider", 0.1, 10.0),
ui.output_text("epsilon"),
output_code_sample("Privacy Loss", "privacy_loss_python"),
ui.input_action_button("go_to_results", "Download results"),
ui.output_ui("download_results_button_ui"),
value="analysis_panel",
)

Expand All @@ -41,6 +41,10 @@ def analysis_server(
contributions=None,
is_demo=None,
): # pragma: no cover
@reactive.calc
def button_enabled():
column_ids_selected = input.columns_checkbox_group()
return len(column_ids_selected) > 0

weights = reactive.value({})

Expand All @@ -67,9 +71,9 @@ def _update_checkbox_group():

@reactive.effect
@reactive.event(input.columns_checkbox_group)
def _update_weights():
column_ids_to_keep = input.columns_checkbox_group()
clear_column_weights(column_ids_to_keep)
def _on_column_set_change():
column_ids_selected = input.columns_checkbox_group()
clear_column_weights(column_ids_selected)

@render.ui
def columns_ui():
Expand Down Expand Up @@ -115,3 +119,16 @@ def privacy_loss_python():
@reactive.event(input.go_to_results)
def go_to_results():
ui.update_navs("top_level_nav", selected="results_panel")

@render.ui
def download_results_button_ui():
button = ui.input_action_button(
"go_to_results", "Download results", disabled=not button_enabled()
)

if button_enabled():
return button
return [
button,
"Select one or more columns before proceeding.",
]
23 changes: 22 additions & 1 deletion dp_creator_ii/app/dataset_panel.py
mccalluc marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ def dataset_ui():
"contributions",
["Contributions", ui.output_ui("contributions_demo_tooltip_ui")],
cli_info.contributions,
min=1,
),
ui.output_ui("python_tooltip_ui"),
output_code_sample("Unit of Privacy", "unit_of_privacy_python"),
ui.input_action_button("go_to_analysis", "Define analysis"),
ui.output_ui("define_analysis_button_ui"),
value="dataset_panel",
)

Expand All @@ -52,6 +53,14 @@ def _on_csv_path_change():
def _on_contributions_change():
contributions.set(input.contributions())

@reactive.calc
def button_enabled():
contributions_is_set = input.contributions() is not None
csv_path_is_set = (
input.csv_path() is not None and len(input.csv_path()) > 0
) or is_demo
return contributions_is_set and csv_path_is_set

@render.ui
def choose_csv_demo_tooltip_ui():
return demo_tooltip(
Expand All @@ -78,6 +87,18 @@ def python_tooltip_ui():
"for the entire calculation.",
)

@render.ui
def define_analysis_button_ui():
button = ui.input_action_button(
"go_to_analysis", "Define analysis", disabled=not button_enabled()
)
if button_enabled():
return button
return [
button,
"Choose CSV and Contributions before proceeding.",
]

@render.code
def unit_of_privacy_python():
return make_privacy_unit_block(contributions())
Expand Down
15 changes: 13 additions & 2 deletions tests/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,17 @@ def expect_no_error():
expect_visible("dp.unit_of(contributions=42)")
expect_no_error()

# Button disabled until upload:
define_analysis_button = page.get_by_role("button", name="Define analysis")
assert define_analysis_button.is_disabled()

# Now upload:
csv_path = Path(__file__).parent / "fixtures" / "fake.csv"
page.get_by_label("Choose CSV file").set_input_files(csv_path.resolve())
expect_no_error()

# -- Define analysis --
page.get_by_role("button", name="Define analysis").click()
define_analysis_button.click()
expect_not_visible(pick_dataset_text)
expect_visible(perform_analysis_text)
expect_not_visible(download_results_text)
Expand All @@ -72,12 +77,18 @@ def expect_no_error():
expect_visible("Epsilon: 0.316")
page.locator(".irs-bar").click()
expect_visible("Epsilon: 0.158")

# Button disabled until column selected:
download_results_button = page.get_by_role("button", name="Download results")
assert download_results_button.is_disabled()

# Set column details:
page.get_by_label("grade").check()
page.get_by_label("Min").click()
page.get_by_label("Min").fill("0")
# TODO: All these recalculations cause timeouts:
# It is still rerendering the graph after hitting "Download results".
# https://github.com/opendp/dp-creator-ii/issues/116
# page.get_by_label("Max").click()
# page.get_by_label("Max").fill("100")
# page.get_by_label("Bins").click()
Expand All @@ -86,7 +97,7 @@ def expect_no_error():
expect_no_error()

# -- Download results --
page.get_by_role("button", name="Download results").click()
download_results_button.click()
expect_not_visible(pick_dataset_text)
expect_not_visible(perform_analysis_text)
expect_visible(download_results_text)
Expand Down
Loading