Skip to content

Commit

Permalink
Fix #1627: Loading UI improvements with Segfault (#1661)
Browse files Browse the repository at this point in the history
* issue-1627: loading decorator, UI improvements

* issue-1627: disabled loading for feeds and predictoor pages

* issue-1627: skeleton loading on tables and metrics

* issue-1627: Test fix

* issue-1627: home test fixes

* issue-1627: test fixes

* black fix

* issue-1627: fix css

* issue-1627: removed unused functions

* issue-1627: fix predictoors metrics and clear unnecessary codes

* issue-1627- home fix

* issue-1627: inital call

* issue-1627: table spinner

* removed debug logic

* issue-1627 - fix initial loading

* issue-1627: remove unused import

* issue-1627 - modal loading

* issue-1627 - make the app async completely

* issue-1627 - linter fixes

* issue-1627 - lint fixes

* issue-1627: fix loading process

* homepage fixes

* fixes that Calina suggests

* select the predictoor address with highest profit by default on home screen table

* issue-1627: test fixes

* trig tests

* fix step 1

* removed some feature

* fix some tests

* segfault fix

* issue-1627-segfault

* mypy fix

* segfault fix

* segfault fix 2

* display available data range end date time

---------

Co-authored-by: Norbert <katunanorbert@gmail.com>
  • Loading branch information
kdetry and KatunaNorbert authored Oct 16, 2024
1 parent 4b308c1 commit 9782d79
Show file tree
Hide file tree
Showing 22 changed files with 746 additions and 2,300 deletions.
190 changes: 190 additions & 0 deletions pdr_backend/pdr_dashboard/assets/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,20 @@ body {
display: none;
}

#predictoors_container,
#feeds_container {
position: relative;
}

#plots_container > div {
position: relative;
}

#plots_container #table_spinner {
height: 90%;
margin: 20px;
}

.date-period-radio-items{
margin-right: 2px;
}
Expand Down Expand Up @@ -121,6 +135,182 @@ body {
-webkit-line-clamp: 2;
}

#feeds_page_table_area:has(> *[data-dash-is-loading="true"]) > #feeds_page_table table td div,
#feeds_page_table_area:has(> *[data-dash-is-loading="true"]) > #feeds_page_table table td input,
#predictoors_page_table_area:has(> *[data-dash-is-loading="true"]) > #predictoors_page_table table td div,
#predictoors_page_table_area:has(> *[data-dash-is-loading="true"]) > #predictoors_page_table table td input
{
visibility: hidden;
}

#feeds_page_table_area:has(> *[data-dash-is-loading="true"]) > #feeds_page_table table td,
#predictoors_page_table_area:has(> *[data-dash-is-loading="true"]) > #predictoors_page_table table td {
position: relative;
background-color: #ccc;
color: transparent; /* Hides the text */
overflow: hidden;
border-color: transparent !important;
border-radius: 5px;
cursor: progress;
}

#feeds_page_table_area:has(> *[data-dash-is-loading="true"]) > #feeds_page_table table td::after,
#predictoors_page_table_area:has(> *[data-dash-is-loading="true"]) > #predictoors_page_table table td::after {
content: "";
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0));
animation: shimmer 2s infinite;
}

.metric_unit {
display: flex;
flex-direction: column;
font-size: 20px;
}

.metric_value {
font-weight: bold;
}

#feeds_page_metrics_row[data-dash-is-loading="true"] .metric_value,
#predictoors_page_metrics_row[data-dash-is-loading="true"] .metric_value,
#metrics_container *[data-dash-is-loading="true"],
.initial_metric {
position: relative;
display: block;
background-color: #ccc;
color: transparent !important; /* Hides the text */
overflow: hidden;
border-color: transparent !important;
border-radius: 5px;
width: 100px;
height: 30px;
cursor: progress;
}

#feeds_page_metrics_row[data-dash-is-loading="true"] .metric_value::after,
#predictoors_page_metrics_row[data-dash-is-loading="true"] .metric_value::after,
#metrics_container *[data-dash-is-loading="true"]::after,
.initial_metric::after {
content: "";
display: block;
position: relative;
width: 100%;
height: 100%;
background: linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0));
animation: shimmer 2s infinite;
top: -30px;
z-index: 5;
}

.initial_metric::after {
top: 0px;
}

#table_spinner {
text-align: center;
height: 100%;
position: absolute;
left: 0px;
right: 0px;
margin-left: 50px;
margin-right: 50px;
border-radius: 5px;
height: 300px;
background-color: #ccc;
overflow: hidden;
}

#home_page_table_control_predictoors_table,
#home_page_table_control_feeds_table {
display: flex;
position: absolute;
top: 100px;
width: 100%;
}

#home_page_table_control_predictoors_table #table_spinner,
#home_page_table_control_feeds_table #table_spinner {
width: 90%;
position: absolute;
top: 0px;
height: 200px;
margin: auto;
}

#stake_chart[data-dash-is-loading="true"]::before,
#cost_chart[data-dash-is-loading="true"]::before,
#profit_chart[data-dash-is-loading="true"]::before,
#accuracy_chart[data-dash-is-loading="true"]::before,
.modal-dialog[data-dash-is-loading="true"] .modal-graph-item {
display: block;
overflow: hidden;
background-color: #ccc;
border-radius: 5px;
cursor: progress !important;
}

#plots_container *[data-dash-is-loading="true"]::before {
content: "";
width: 95%;
height: 90%;
position: absolute;
top: 20px;
left: 0;
right: 0px;
margin: auto;
z-index: 2;
}

#plots_container *[data-dash-is-loading="true"] .dash-graph,
#plots_container *[data-dash-is-loading="true"] .dash-graph svg,
#plots_container *[data-dash-is-loading="true"] .dash-graph .plot-container,
#plots_container *[data-dash-is-loading="true"] .dash-graph .plot-container .nsewdrag,
#plots_container *[data-dash-is-loading="true"] .dash-graph .plot-container .drag,
.modal-dialog[data-dash-is-loading="true"] .modal-graph-item .dash-graph,
.modal-dialog[data-dash-is-loading="true"] .modal-graph-item .dash-graph svg,
.modal-dialog[data-dash-is-loading="true"] .modal-graph-item .dash-graph .plot-container,
.modal-dialog[data-dash-is-loading="true"] .modal-graph-item .dash-graph .plot-container .nsewdrag,
.modal-dialog[data-dash-is-loading="true"] .modal-graph-item .dash-graph .plot-container .drag {
visibility: hidden;
cursor: progress !important;
}

#plots_container *[data-dash-is-loading="true"]::after,
.modal-dialog[data-dash-is-loading="true"] .modal-graph-item::after,
#table_spinner::after {
content: "";
display: block;
position: relative;
width: 100%;
height: 100%;
background: linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0));
animation: shimmer 2s infinite;
z-index: 5;
}

.modal-dialog[data-dash-is-loading="true"] .modal-graph-item::after {
top: -235px;
}

.modal-dialog[data-dash-is-loading="true"] .modal-graph-item .dash-graph {
visibility: hidden;
}

@keyframes shimmer {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(100%);
}
}

button {
background-color: var(--main-color) !important;
color: white;
Expand Down
45 changes: 38 additions & 7 deletions pdr_backend/pdr_dashboard/callbacks/callbacks_common.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from dash import Input, Output
from dash import Input, Output, dash

from pdr_backend.pdr_dashboard.dash_components.view_elements import (
NAV_ITEMS,
Expand All @@ -7,10 +7,26 @@
from pdr_backend.pdr_dashboard.pages.feeds import FeedsPage
from pdr_backend.pdr_dashboard.pages.home import HomePage
from pdr_backend.pdr_dashboard.pages.predictoors import PredictoorsPage
from pdr_backend.pdr_dashboard.util.helpers import get_date_period_text_header
from pdr_backend.pdr_dashboard.util.helpers import (
get_date_period_text_header,
with_loading,
check_data_loaded,
)


def get_callbacks_common(app):
@app.callback(
Output("is-initial-data-loaded", "data"),
Input("is-initial-data-loaded", "data"),
)
def initial_data_load(is_data_loaded):
if not is_data_loaded or not is_data_loaded["loaded"]:
if not app.data.is_initial_data_loaded:
app.data.initial_process() # Call the initial process
return {"loaded": True}

return dash.no_update

@app.callback(
Output("page-content", "children"),
Output("navbar-container", "children"),
Expand All @@ -25,18 +41,33 @@ def display_page(pathname):

@app.callback(
Output("start-date", "data"),
[Input("general-lake-date-period-radio-items", "value")],
[
Input("general-lake-date-period-radio-items", "value"),
Input("is-initial-data-loaded", "data"),
],
)
def set_period_start_date(selected_period_start):
@check_data_loaded(output_count=1)
def set_period_start_date(
selected_period_start,
_,
):
app.data.set_start_date_from_period(int(selected_period_start))

return app.data.start_date

@app.callback(
Output("available-data-text", "children"),
[Input("page-content", "children")],
[
Input("page-content", "children"),
Input("is-initial-data-loaded", "data"),
],
prevent_initial_call=True,
)
def display_available_data(_):
@with_loading("loading-available-period")
@check_data_loaded(output_count=1, alternative_output="")
def display_available_data(
_,
_is_initial_data_loaded,
):
return get_date_period_text_header(
app.data.min_timestamp, app.data.max_timestamp
)
Expand Down
56 changes: 40 additions & 16 deletions pdr_backend/pdr_dashboard/callbacks/callbacks_feeds.py
Original file line number Diff line number Diff line change
@@ -1,39 +1,63 @@
import dash
from dash import Input, Output, State
from dash import Input, Output, State, html

from pdr_backend.pdr_dashboard.dash_components.modal import ModalContent
from pdr_backend.pdr_dashboard.pages.feeds import get_metric
from pdr_backend.pdr_dashboard.util.filters import (
check_conditions,
filter_table_by_range,
)
from pdr_backend.pdr_dashboard.util.format import format_df
from pdr_backend.pdr_dashboard.util.helpers import toggle_modal_helper
from pdr_backend.pdr_dashboard.util.format import format_value, format_df
from pdr_backend.pdr_dashboard.util.helpers import (
toggle_modal_helper,
produce_feeds_filter_options,
check_data_loaded,
)


def get_callbacks_feeds(app):
@app.callback(
Output("feeds_page_table", "data", allow_duplicate=True),
Output("feeds_page_metrics_row", "children"),
[Input("start-date", "data")],
prevent_initial_call=True,
Output("feeds_page_table", "data"),
Output("feeds_page_Feeds_metric", "children"),
Output("feeds_page_Accuracy_metric", "children"),
Output("feeds_page_Volume_metric", "children"),
Output("feeds_page_Sales_metric", "children"),
Output("feeds_page_Revenue_metric", "children"),
Output("feeds_page_table_control", "children"),
Output("base_token", "options"),
Output("quote_token", "options"),
Output("source", "options"),
Output("timeframe", "options"),
[
Input("start-date", "data"),
Input("is-initial-data-loaded", "data"),
],
)
def update_page_data(_start_date):
@check_data_loaded(output_count=11)
def update_page_data(
_start_date,
_is_initial_data_loaded,
):
app.data.refresh_feeds_data()

filter_options = produce_feeds_filter_options(app.data.feeds_data.clone())

metrics_children_data = [
get_metric(
label=key,
value=value,
value_id=f"feeds_page_{key}_metric",
)
format_value(value, f"feeds_page_{key}_metric")
for key, value in app.data.feeds_metrics_data.items()
]

return app.data.feeds_table_data.to_dicts(), metrics_children_data
return (
app.data.feeds_table_data.to_dicts(),
*metrics_children_data,
html.Div(),
filter_options[0],
filter_options[1],
filter_options[2],
filter_options[3],
)

@app.callback(
Output("feeds_page_table", "data"),
Output("feeds_page_table", "data", allow_duplicate=True),
[
Input("base_token", "value"),
Input("quote_token", "value"),
Expand Down
Loading

0 comments on commit 9782d79

Please sign in to comment.