Skip to content

Commit

Permalink
Merge branch 'main' into issue-1559-profit-metric
Browse files Browse the repository at this point in the history
  • Loading branch information
calina-c authored Oct 4, 2024
2 parents a729354 + 32163a9 commit b9a25e2
Show file tree
Hide file tree
Showing 3 changed files with 230 additions and 24 deletions.
104 changes: 85 additions & 19 deletions pdr_backend/pdr_dashboard/callbacks/callbacks_home.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,23 +85,23 @@ def get_display_data_from_db(

@app.callback(
Output("predictoors_table", "data", allow_duplicate=True),
Output("predictoors_table", "selected_rows"),
Output("predictoors_table", "selected_rows", allow_duplicate=True),
[
Input("search-input-Predictoors", "value"),
Input("predictoors_table", "selected_rows"),
Input("show-favourite-addresses", "value"),
Input("general-lake-date-period-radio-items", "value"),
Input("predictoor-addrs-local-store", "data"),
],
[
State("predictoors_table", "data"),
],
[State("predictoors_table", "data")],
prevent_initial_call=True,
)
def update_predictoors_table_on_search(
search_value,
selected_rows,
show_favourite_addresses,
date_period,
stored_predictoor_addrs,
predictoors_table,
):
if (
Expand All @@ -119,21 +119,24 @@ def update_predictoors_table_on_search(
]

if "show-favourite-addresses.value" in dash.callback_context.triggered_prop_ids:
custom_predictoors = formatted_predictoors_data.filter(
formatted_predictoors_data["full_addr"].is_in(
app.data.favourite_addresses
if len(stored_predictoor_addrs) > 0:
selected_predictoors_addrs = stored_predictoor_addrs
else:
custom_predictoors = formatted_predictoors_data.filter(
formatted_predictoors_data["full_addr"].is_in(
app.data.favourite_addresses
)
)
)
custom_predictoors_addrs = list(custom_predictoors["full_addr"])
custom_predictoors_addrs = list(custom_predictoors["full_addr"])

if show_favourite_addresses:
selected_predictoors_addrs += custom_predictoors_addrs
else:
selected_predictoors_addrs = [
predictoor_addr
for predictoor_addr in selected_predictoors_addrs
if predictoor_addr not in custom_predictoors_addrs
]
if show_favourite_addresses:
selected_predictoors_addrs += custom_predictoors_addrs
else:
selected_predictoors_addrs = [
predictoor_addr
for predictoor_addr in selected_predictoors_addrs
if predictoor_addr not in custom_predictoors_addrs
]

filtered_data = formatted_predictoors_data.clone()
if search_value:
Expand All @@ -149,13 +152,13 @@ def update_predictoors_table_on_search(
)

filtered_data = pl.concat([selected_predictoors, filtered_data])
selected_predictoor_indices = list(range(len(selected_predictoors_addrs)))
selected_predictoor_indices = list(range(len(selected_predictoors)))

return (filtered_data.to_dicts(), selected_predictoor_indices)

@app.callback(
Output("feeds_table", "data"),
Output("feeds_table", "selected_rows"),
Output("feeds_table", "selected_rows", allow_duplicate=True),
[
Input("search-input-Feeds", "value"),
Input("toggle-switch-predictoor-feeds", "value"),
Expand All @@ -165,6 +168,7 @@ def update_predictoors_table_on_search(
[
State("feeds_table", "selected_rows"),
State("feeds_table", "data"),
State("predictoor-addrs-local-store", "data"),
],
prevent_initial_call=True,
)
Expand All @@ -176,6 +180,7 @@ def update_feeds_table_on_search(
predictoors_table,
selected_rows,
feeds_table,
stored_predictoors_addrs,
):
selected_feeds = [feeds_table[i]["contract"] for i in selected_rows]
# Extract selected predictoor addresses
Expand All @@ -187,6 +192,14 @@ def update_feeds_table_on_search(
predictoor_feeds_only, predictoors_addrs, search_value, selected_feeds
)

# if sorted(predictoors_addrs) == sorted(stored_predictoors_addrs)
# it means we are not on the initial page load, so we use
# the feeds selected by the user
if stored_predictoors_addrs and sorted(predictoors_addrs) == sorted(
stored_predictoors_addrs
):
selected_feeds = list(range(len(filtered_data)))

selected_feed_indices = list(range(len(selected_feeds)))

return filtered_data, selected_feed_indices
Expand Down Expand Up @@ -224,3 +237,56 @@ def select_or_clear_all_predictoors(_, __, rows):

ctx = dash.callback_context
return select_or_clear_all_by_table(ctx, "predictoors_table", rows)

@app.callback(
[
Output("predictoor_config_modal", "is_open"),
Output("predictoor_addrs", "value"),
],
[
Input("configure_predictoors", "n_clicks"),
Input("predictoor-addrs-local-store", "data"),
],
prevent_initial_call=True,
)
def open_predictoors_config_modal(n_clicks, predictoor_addrs):
"""
Select or clear all rows in the feeds table.
"""
predictoor_addrs_str = "\n".join(predictoor_addrs) if predictoor_addrs else ""

return (bool(n_clicks > 0), predictoor_addrs_str)

@app.callback(
Output("predictoor-addrs-local-store", "data"),
Input("save_predictoors", "n_clicks"),
State("predictoor_addrs", "value"),
)
def save_predictoors_to_browser_storage(n_clicks, value):
if not value and not n_clicks:
return dash.no_update
addresses = value.split("\n")
addresses = [
addr.strip() for addr in addresses if addr.strip()
] # Remove empty lines

return addresses

@app.callback(
Output("show-favourite-addresses", "value"),
Output("predictoors_table", "selected_rows"),
Output("feeds_table", "selected_rows"),
Input("predictoor-addrs-local-store", "data"),
prevent_initial_call=True,
)
def update_show_favourite_check_and_selected_predictoor_rows(
saved_predictoor_addrs,
):
if not saved_predictoor_addrs and not app.data.favourite_addresses:
return (False, [], [])

return (
True if saved_predictoor_addrs else dash.no_update,
dash.no_update,
dash.no_update,
)
56 changes: 55 additions & 1 deletion pdr_backend/pdr_dashboard/pages/home.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ def layout(self):

def get_main_container(self):
return html.Div(
[self.get_input_column(), self.get_graphs_column()],
[
self.get_input_column(),
self.get_graphs_column(),
self.getPredictoorsConfigModal(),
dcc.Store(id="predictoor-addrs-local-store", storage_type="local"),
],
className="main-container",
)

Expand Down Expand Up @@ -251,6 +256,16 @@ def get_table(self, table_id, columns, data):
),
html.Div(
[
(
html.Button(
"Configure",
id="configure_predictoors",
n_clicks=0,
className="button-select-all",
)
if table_id == "predictoors_table"
else None
),
html.Button(
"Select All",
id=f"select-all-{table_id}",
Expand Down Expand Up @@ -288,3 +303,42 @@ def get_table(self, table_id, columns, data):
),
],
)

def getPredictoorsConfigModal(self):
return dbc.Modal(
html.Div(
[
html.H2("Configure Favourite Predictoor Addresses"),
html.P(
"""Add predictoor addresses to be saved
and automatically selected when the app opens.""",
style={"marginBottom": 0},
),
html.P("Enter one address per line."),
dcc.Textarea(
id="predictoor_addrs",
placeholder="Predictoor addrs...",
value="",
style={"margin": "10px", "width": "60%", "height": 200},
),
html.Button(
"Save",
id="save_predictoors",
className="clear-filters-button",
style={
"width": "100px",
"hight": "100%",
"padding": "5px",
},
),
],
style={
"display": "flex",
"flexDirection": "column",
"alignItems": "center",
"justifyContent": "center",
"widht": "100%",
},
),
id="predictoor_config_modal",
)
94 changes: 90 additions & 4 deletions pdr_backend/pdr_dashboard/test/test_callbacks_home.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import time

import platform
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from pdr_backend.pdr_dashboard.test.resources import (
_input_action,
start_server_and_wait,
Expand Down Expand Up @@ -89,8 +91,7 @@ def test_favourite_addresses_search_input(
fav_addr_toggle.click()
time.sleep(2)
p_all, p_sel = _predictoor_count(dash_duo)
assert len(p_all) == 58
assert len(p_sel) == 0
assert len(p_sel) == 1


def test_checkbox_selection(_sample_app, dash_duo):
Expand Down Expand Up @@ -125,7 +126,6 @@ def test_timeframe_metrics(_sample_app, dash_duo):
time.sleep(2)

dash_duo.find_element("#feeds_table tbody tr:nth-child(2) input").click()
time.sleep(2)

table_profit = dash_duo.find_element(
"#predictoors_table tbody tr:nth-child(2) td:nth-child(3)"
Expand Down Expand Up @@ -169,3 +169,89 @@ def test_predictoors_feed_only_switch(_sample_app, dash_duo):

feeds_table_len = len(dash_duo.find_elements("#feeds_table tbody tr"))
assert feeds_table_len == 21


def test_navigation(_sample_app, dash_duo):
app = _sample_app
start_server_and_wait(dash_duo, app)

# Default page is Home
dash_duo.wait_for_element_by_id("plots_container", timeout=10)

# Navigate to Feeds
dash_duo.wait_for_element("#navbar-container a[href='/feeds']").click()
dash_duo.wait_for_element_by_id("feeds_page_metrics_row", timeout=10)
dash_duo.wait_for_element_by_id("feeds_page_table", timeout=10)

# Navigate to Home
dash_duo.wait_for_element("#navbar-container a[href='/']").click()
dash_duo.wait_for_element_by_id("plots_container", timeout=10)


def test_configure_predictoor_addresses(_sample_app, dash_duo):
app = _sample_app
start_server_and_wait(dash_duo, app)
predictoor_addrs = "0x35842372c513f8f217b968adc57a9296ba573d5c"

# Clear selected predictoors
dash_duo.find_element("#clear-all-predictoors_table").click()
dash_duo.find_element("#clear-all-feeds_table").click()
_, p_sel = _predictoor_count(dash_duo)
_, f_sel = _feed_count(dash_duo)
assert len(p_sel) == 0
assert len(f_sel) == 0

# Open config modal and save predictoor addrs
dash_duo.find_element("#configure_predictoors").click()
search_input = dash_duo.find_element("#predictoor_addrs")
search_input.clear()
search_input.send_keys(predictoor_addrs + Keys.ENTER)
dash_duo.find_element("#save_predictoors").click()

# Check that tables were updated based on the saved predictoor addrs
_, p_sel = _predictoor_count(dash_duo)
_, f_sel = _feed_count(dash_duo)
assert len(p_sel) == 1
assert len(f_sel) > 0

# Find selected predictoors and check that is the one specified inside the input
first_selected_row = p_sel[0].find_element(by=By.XPATH, value="./ancestor::tr")
first_row_second_col_value = first_selected_row.find_element(
by=By.XPATH, value="./td[2]"
).text
assert first_row_second_col_value[:5] == predictoor_addrs[:5]

# Refresh the page
dash_duo.driver.refresh()

# Wait for the page to reload
dash_duo.wait_for_page()

_, p_sel = _predictoor_count(dash_duo)
_, f_sel = _feed_count(dash_duo)
assert len(p_sel) == 1
assert len(f_sel) > 0

# Find selected predictoors and check that is the one specified inside the input
first_selected_row = p_sel[0].find_element(by=By.XPATH, value="./ancestor::tr")
first_row_second_col_value = first_selected_row.find_element(
by=By.XPATH, value="./td[2]"
).text
assert first_row_second_col_value[:5] == predictoor_addrs[:5]

# open config modal by button click
dash_duo.find_element("#configure_predictoors").click()

search_input = dash_duo.find_element("#predictoor_addrs")
select_all_key = Keys.COMMAND if platform.system() == "Darwin" else Keys.CONTROL
search_input.send_keys(select_all_key + "a")
search_input.send_keys(Keys.DELETE)

dash_duo.find_element("#save_predictoors").click()
dash_duo.find_element("#predictoor_config_modal").click()
dash_duo.find_element(".modal").click()

_, p_sel = _predictoor_count(dash_duo)
_, f_sel = _feed_count(dash_duo)
assert len(p_sel) == 0
assert len(f_sel) == 0

0 comments on commit b9a25e2

Please sign in to comment.