From c574baaa53e870fd926838e88134cb620c997d25 Mon Sep 17 00:00:00 2001 From: fe51 <55736935+fe51@users.noreply.github.com> Date: Sun, 26 Jan 2025 16:03:56 +0100 Subject: [PATCH 01/10] style: Updated padding --- app/components/alerts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/alerts.py b/app/components/alerts.py index d37be843..9f6d94ba 100644 --- a/app/components/alerts.py +++ b/app/components/alerts.py @@ -22,7 +22,7 @@ def create_event_list(): event_list_style = { "height": "calc(100vh - 120px)", # Adjust the height as required "overflowY": "scroll", # Enable vertical scrolling - "padding": "10px", + "padding-right": "10px", # Prevent scroll bar from touching alerts list } return html.Div( From 198d092feb7c36e242c95e82275993f8e6ab9a7e Mon Sep 17 00:00:00 2001 From: fe51 <55736935+fe51@users.noreply.github.com> Date: Sun, 26 Jan 2025 16:04:59 +0100 Subject: [PATCH 02/10] feat: css: Added new classes & Updated styles --- app/assets/css/style.css | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/app/assets/css/style.css b/app/assets/css/style.css index 69efe08b..8efa2e84 100644 --- a/app/assets/css/style.css +++ b/app/assets/css/style.css @@ -1,5 +1,9 @@ /* style.css */ - +.btn-primary{ + --bs-btn-bg: #054546; + --bs-btn-hover-bg: #032626; + --bs-btn-active-bg: #032626; +} /* Style the scrollbar itself (width, color) */ ::-webkit-scrollbar { width: 10px; /* Scrollbar width */ @@ -25,6 +29,7 @@ display: flex; align-items: center; justify-content: center; + min-height: 60px; } /* Custom link style */ @@ -34,8 +39,8 @@ a.no-underline { /* Common style for containers and panels */ .common-style { - border: 2px solid #044448; - border-radius: 10px; + border: 1px solid #044448; + border-radius: 4px; background-color: rgba(4, 68, 72, 0.1); } @@ -43,7 +48,6 @@ a.no-underline { border: 2px solid #044448; border-radius: 10px; background-color: rgba(4, 68, 72, 0.1); - margin-top: 10px; } @@ -53,3 +57,23 @@ a.no-underline { font-weight: bold; text-align: center; } + +.alert-card { + background-color: #FFE2C2; + margin-bottom: 12px; + padding: 8px; + border-radius: 4px; + width: 100%; + border: 1px solid; +} + +#alert-information-styling-container { + display: flex; + flex-direction: column; + gap: 8px; + padding: 8px; +} + +.alert-information-title { + font-weight: bold; +} From 9fc3b206239dfe2c1b26d4cf6d6a5a8e589ccc5c Mon Sep 17 00:00:00 2001 From: fe51 <55736935+fe51@users.noreply.github.com> Date: Sun, 26 Jan 2025 16:05:16 +0100 Subject: [PATCH 03/10] feat: Added play-pause icon --- app/assets/images/play-pause.svg | 1 + 1 file changed, 1 insertion(+) create mode 100644 app/assets/images/play-pause.svg diff --git a/app/assets/images/play-pause.svg b/app/assets/images/play-pause.svg new file mode 100644 index 00000000..4dac52c7 --- /dev/null +++ b/app/assets/images/play-pause.svg @@ -0,0 +1 @@ + \ No newline at end of file From a3f9acaa7568d61996c738b986e8f700e4d4a061 Mon Sep 17 00:00:00 2001 From: fe51 <55736935+fe51@users.noreply.github.com> Date: Sun, 26 Jan 2025 16:05:42 +0100 Subject: [PATCH 04/10] feat: Updated style --- app/utils/display.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/app/utils/display.py b/app/utils/display.py index c47afcdf..1376cf4a 100644 --- a/app/utils/display.py +++ b/app/utils/display.py @@ -190,13 +190,7 @@ def create_event_list_from_alerts(api_events): html.Div(event["created_at"].strftime("%Y-%m-%d %H:%M")), ], n_clicks=0, - style={ - "backgroundColor": "#FC816B", - "margin": "10px", - "padding": "10px", - "borderRadius": "20px", - "width": "100%", - }, + className="alert-card" ) for _, event in filtered_events.iterrows() ] From a12d3bcca5a972956a7a8ab9e21e65fe53a18e7d Mon Sep 17 00:00:00 2001 From: fe51 <55736935+fe51@users.noreply.github.com> Date: Sun, 26 Jan 2025 16:06:25 +0100 Subject: [PATCH 05/10] feat: updated alert cards style --- app/callbacks/display_callbacks.py | 33 ++++++++++++++---------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/app/callbacks/display_callbacks.py b/app/callbacks/display_callbacks.py index 285b3df9..0b97054b 100644 --- a/app/callbacks/display_callbacks.py +++ b/app/callbacks/display_callbacks.py @@ -119,23 +119,13 @@ def select_event_with_button(n_clicks, button_ids, local_alerts, event_id_on_dis if button["index"] == button_index: styles.append( { - "backgroundColor": "#2C796E", - "margin": "10px", - "padding": "10px", - "borderRadius": "20px", - "color": "white", - "width": "100%", + "backgroundColor": "#feba6a", + }, ) # Highlight style else: styles.append( - { - "backgroundColor": "#FC816B", - "margin": "10px", - "padding": "10px", - "borderRadius": "20px", - "width": "100%", - }, + {}, ) # Default style return [styles, button_index, 1, "reset_zoom"] @@ -280,21 +270,25 @@ def toggle_bbox_visibility(n_clicks, button_style): """ if n_clicks % 2 == 0: bbox_style = {"display": "block"} # Show the bounding box - button_style["backgroundColor"] = "#FEBA6A" # Original button color + button_style["background-color"] = "#054546" # Original button color else: bbox_style = {"display": "none"} # Hide the bounding box - button_style["backgroundColor"] = "#C96A00" # Darker color for the button + button_style["background-color"] = "#098386" # Darker color for the button return bbox_style, button_style @app.callback( - Output("auto-move-state", "data"), + [ + Output("auto-move-state", "data"), + Output("auto-move-button", "style"), # Update the style of the button + ], Input("auto-move-button", "n_clicks"), State("auto-move-state", "data"), + State("auto-move-button", "style"), # Get the current style of the button prevent_initial_call=True, ) -def toggle_auto_move(n_clicks, data): +def toggle_auto_move(n_clicks, data, button_style): """ Toggles the automatic movement of the image slider based on button clicks. @@ -307,9 +301,12 @@ def toggle_auto_move(n_clicks, data): """ if n_clicks % 2 == 0: # Toggle between on and off states data["active"] = False + button_style["background-color"] = "#098386" # Darker color for the button + else: data["active"] = True - return data + button_style["background-color"] = "#054546" # Original button color + return data, button_style @app.callback( From ae350cf165dfc2dc67ff6c641a9910728dc6db59 Mon Sep 17 00:00:00 2001 From: fe51 <55736935+fe51@users.noreply.github.com> Date: Sun, 26 Jan 2025 16:08:10 +0100 Subject: [PATCH 06/10] =?UTF-8?q?feat:=20Added=20play-pause=20button=20&?= =?UTF-8?q?=20remove=20"activer/d=C3=A9sactiver=20animation"=20button?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/pages/homepage.py | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/app/pages/homepage.py b/app/pages/homepage.py index 1005ea41..f2dd3961 100644 --- a/app/pages/homepage.py +++ b/app/pages/homepage.py @@ -17,7 +17,6 @@ def homepage_layout(user_headers, user_credentials, lang="fr"): translate = { "fr": { - "animate_on_off": "Activer / Désactiver l'animation", "show_hide_prediction": "Afficher / Cacher la prédiction", "download_image": "Télécharger l'image", "acknowledge_alert": "Acquitter l'alerte", @@ -31,7 +30,6 @@ def homepage_layout(user_headers, user_credentials, lang="fr"): "no_alert_default_image": "./assets/images/no-alert-default.png", }, "es": { - "animate_on_off": "Activar / Desactivar la animación", "show_hide_prediction": "Mostrar / Ocultar la predicción", "download_image": "Descargar la imagen", "acknowledge_alert": "Descartar la alerta", @@ -98,31 +96,38 @@ def homepage_layout(user_headers, user_credentials, lang="fr"): ), ], ), - html.Div( - dcc.Slider(id="image-slider", min=0, max=10, step=1, value=0), - id="slider-container", - className="common-style-slider", - style={"display": "none", "marginTop": "10px"}, - ), dbc.Row( [ dbc.Col( dbc.Button( - translate[lang]["animate_on_off"], + html.Img(src="assets/images/play-pause.svg"), id="auto-move-button", n_clicks=1, - className="btn-uniform common-style", - style={"backgroundColor": "#FD5252"}, + style={"height": "100%", "width": "100%"} ), - width=3, + width=1 ), + dbc.Col( + html.Div( + dcc.Slider(id="image-slider", min=0, max=10, step=1, value=0), + id="slider-container", + className="common-style-slider", + style={"display": "none"} + ), + width=11 + ) + + ], style={"marginTop": "10px"} + ), + dbc.Row( + [ dbc.Col( dbc.Button( translate[lang]["show_hide_prediction"], id="hide-bbox-button", n_clicks=0, - className="btn-uniform common-style", - style={"backgroundColor": "#FEBA6A"}, + className="btn-uniform", + style={}, # Will be overwritten dynamically ), width=3, ), @@ -130,8 +135,7 @@ def homepage_layout(user_headers, user_credentials, lang="fr"): html.A( dbc.Button( translate[lang]["download_image"], - className="btn-uniform common-style", - style={"backgroundColor": "#2C796E"}, + className="btn-uniform", id="dl-image-button", ), className="no-underline", @@ -147,17 +151,17 @@ def homepage_layout(user_headers, user_credentials, lang="fr"): translate[lang]["acknowledge_alert"], id="acknowledge-button", n_clicks=0, - className="btn-uniform common-style", - style={"backgroundColor": "#054546"}, + className="btn-uniform", ), width=3, ), ], className="mb-4", - style={"display": "flex", "marginTop": "10px"}, + style={"display": "flex", "marginTop": "10px", "justify-content": "space-evenly"}, ), ], width=8, + style={"padding": "0"} ), dbc.Col( [ From 8f38ae392a196ee7f9507a03a131fff41814930d Mon Sep 17 00:00:00 2001 From: fe51 <55736935+fe51@users.noreply.github.com> Date: Sun, 26 Jan 2025 16:09:27 +0100 Subject: [PATCH 07/10] feat: Updated style & position in right panel --- app/pages/homepage.py | 92 +++++++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 35 deletions(-) diff --git a/app/pages/homepage.py b/app/pages/homepage.py index f2dd3961..1710fd0f 100644 --- a/app/pages/homepage.py +++ b/app/pages/homepage.py @@ -165,88 +165,110 @@ def homepage_layout(user_headers, user_credentials, lang="fr"): ), dbc.Col( [ - dbc.Row( - dbc.Button( - translate[lang]["enlarge_map"], - className="common-style", - style={"backgroundColor": "#FEBA6A"}, - id="map-button", - ), - className="mb-2", - ), - dbc.Row( - dbc.Col( - build_alerts_map(user_headers, user_credentials), - className="common-style", - style={ - "position": "relative", - "width": "100%", - "paddingTop": "100%", - }, - ), - ), - dbc.Row( + html.Div( html.Div( id="alert-information", className="common-style", - style={"display": "none"}, + style={"display": "none", "padding": "8px"}, children=[ html.Div( id="alert-information-styling-container", - style={"padding": "5px"}, children=[ - html.H4(translate[lang]["alert_information"]), + html.H5(translate[lang]["alert_information"], + style={"text-align": "center"}), html.Div( id="alert-camera", - style={"marginBottom": "10px"}, children=[ html.Span( - id="alert-camera-header", children=translate[lang]["camera"] + id="alert-camera-header", + children=translate[lang]["camera"], + className="alert-information-title" + ), + html.Span( + id="alert-camera-value", + children=[], ), - html.Span(id="alert-camera-value", children=[]), ], ), html.Div( id="camera-location", - style={"marginBottom": "10px"}, children=[ html.Span( id="camera-location-header", children=translate[lang]["camera_location"], + className="alert-information-title" + ), + html.Span( + id="camera-location-value", + children=[], ), - html.Span(id="camera-location-value", children=[]), ], ), html.Div( id="alert-azimuth", - style={"marginBottom": "10px"}, children=[ html.Span( id="alert-azimuth-header", children=translate[lang]["detection_azimuth"], + className="alert-information-title" + ), + html.Span( + id="alert-azimuth-value", + children=[], ), - html.Span(id="alert-azimuth-value", children=[]), ], ), html.Div( id="alert-date", children=[ html.Span( - id="alert-date-header", children=translate[lang]["date"] + id="alert-date-header", + children=translate[lang]["date"], + className="alert-information-title" + ), + html.Span( + id="alert-date-value", + children=[], ), - html.Span(id="alert-date-value", children=[]), ], ), ], ), ], ), - className="mt-4", id="alert-panel", ), + + html.Div( + dbc.Col( + build_alerts_map(user_headers, user_credentials), + className="common-style", + style={ + "position": "relative", + "width": "100%", + "paddingTop": "100%", + }, + ), + ), + html.Div( + dbc.Button( + translate[lang]["enlarge_map"], + className="common-style", + style={ + "backgroundColor": "#FEBA6A", + "color": "black", + "width": "100%" + }, + id="map-button", + ), + ), ], width=2, - className="mb-4", + style={ + "display" : "flex", + "flex-direction": "column", + "gap" : "16px", + }, ), ] ), From 5f79f1fe49931c3c0f1c3b4782238455c3ac329a Mon Sep 17 00:00:00 2001 From: fe51 <55736935+fe51@users.noreply.github.com> Date: Sun, 26 Jan 2025 16:36:14 +0100 Subject: [PATCH 08/10] style : ruff --- app/callbacks/data_callbacks.py | 10 +- app/callbacks/display_callbacks.py | 11 +- app/components/alerts.py | 10 +- app/layouts/main_layout.py | 88 +++---- app/pages/homepage.py | 408 ++++++++++++++--------------- app/pages/login.py | 82 +++--- app/utils/display.py | 12 +- 7 files changed, 298 insertions(+), 323 deletions(-) diff --git a/app/callbacks/data_callbacks.py b/app/callbacks/data_callbacks.py index b4638356..0ee6343d 100644 --- a/app/callbacks/data_callbacks.py +++ b/app/callbacks/data_callbacks.py @@ -190,12 +190,10 @@ def api_watcher(n_intervals, user_credentials, local_alerts, user_headers): if len(api_alerts) == 0: return [ - json.dumps( - { - "data": pd.DataFrame().to_json(orient="split"), - "data_loaded": True, - } - ) + json.dumps({ + "data": pd.DataFrame().to_json(orient="split"), + "data_loaded": True, + }) ] else: diff --git a/app/callbacks/display_callbacks.py b/app/callbacks/display_callbacks.py index 0b97054b..82ec29bb 100644 --- a/app/callbacks/display_callbacks.py +++ b/app/callbacks/display_callbacks.py @@ -120,7 +120,6 @@ def select_event_with_button(n_clicks, button_ids, local_alerts, event_id_on_dis styles.append( { "backgroundColor": "#feba6a", - }, ) # Highlight style else: @@ -155,12 +154,10 @@ def update_display_data(event_id_on_display, local_alerts): raise PreventUpdate if event_id_on_display == 0: - return json.dumps( - { - "data": pd.DataFrame().to_json(orient="split"), - "data_loaded": True, - } - ) + return json.dumps({ + "data": pd.DataFrame().to_json(orient="split"), + "data_loaded": True, + }) else: if event_id_on_display == 0: event_id_on_display = local_alerts["id"].values[0] diff --git a/app/components/alerts.py b/app/components/alerts.py index 9f6d94ba..1331c1e0 100644 --- a/app/components/alerts.py +++ b/app/components/alerts.py @@ -22,11 +22,9 @@ def create_event_list(): event_list_style = { "height": "calc(100vh - 120px)", # Adjust the height as required "overflowY": "scroll", # Enable vertical scrolling - "padding-right": "10px", # Prevent scroll bar from touching alerts list + "padding-right": "10px", # Prevent scroll bar from touching alerts list } - return html.Div( - [ - html.Div(id="alert-list-container", style=event_list_style, children=[]), # Empty container - ] - ) + return html.Div([ + html.Div(id="alert-list-container", style=event_list_style, children=[]), # Empty container + ]) diff --git a/app/layouts/main_layout.py b/app/layouts/main_layout.py index ba9e3827..8bbe019a 100644 --- a/app/layouts/main_layout.py +++ b/app/layouts/main_layout.py @@ -26,51 +26,43 @@ def get_main_layout(): - return html.Div( - [ - dcc.Location(id="url", refresh=False), - html.Div( - id="custom_js_trigger", - className="custom_js_trigger", - title="none", - style={"display": "none"}, - ), - html.Div( - [ - Navbar(), # This includes the navbar at the top of the page - html.Div(id="page-content"), - ] - ), - dcc.Interval(id="main_api_fetch_interval", interval=30 * 1000), - dcc.Store( - id="store_api_alerts_data", - storage_type="session", - data=json.dumps( - { - "data": pd.DataFrame().to_json(orient="split"), - "data_loaded": False, - } - ), - ), - dcc.Store( - id="alert_on_display", - storage_type="session", - data=json.dumps( - { - "data": pd.DataFrame().to_json(orient="split"), - "data_loaded": False, - } - ), - ), - dcc.Store(id="event_id_on_display", data=0), - dcc.Store(id="auto-move-state", data={"active": True}), - # Add this to your app.layout - dcc.Store(id="bbox_visibility", data={"visible": True}), - # Storage components saving the user's headers and credentials - dcc.Store(id="user_headers", storage_type="session", data=user_headers), - # [TEMPORARY FIX] Storing the user's credentials to refresh the token when needed - dcc.Store(id="user_credentials", storage_type="session", data=user_credentials), - dcc.Store(id="to_acknowledge", data=0), - dcc.Store(id="trigger_no_events", data=False), - ] - ) + return html.Div([ + dcc.Location(id="url", refresh=False), + html.Div( + id="custom_js_trigger", + className="custom_js_trigger", + title="none", + style={"display": "none"}, + ), + html.Div([ + Navbar(), # This includes the navbar at the top of the page + html.Div(id="page-content"), + ]), + dcc.Interval(id="main_api_fetch_interval", interval=30 * 1000), + dcc.Store( + id="store_api_alerts_data", + storage_type="session", + data=json.dumps({ + "data": pd.DataFrame().to_json(orient="split"), + "data_loaded": False, + }), + ), + dcc.Store( + id="alert_on_display", + storage_type="session", + data=json.dumps({ + "data": pd.DataFrame().to_json(orient="split"), + "data_loaded": False, + }), + ), + dcc.Store(id="event_id_on_display", data=0), + dcc.Store(id="auto-move-state", data={"active": True}), + # Add this to your app.layout + dcc.Store(id="bbox_visibility", data={"visible": True}), + # Storage components saving the user's headers and credentials + dcc.Store(id="user_headers", storage_type="session", data=user_headers), + # [TEMPORARY FIX] Storing the user's credentials to refresh the token when needed + dcc.Store(id="user_credentials", storage_type="session", data=user_credentials), + dcc.Store(id="to_acknowledge", data=0), + dcc.Store(id="trigger_no_events", data=False), + ]) diff --git a/app/pages/homepage.py b/app/pages/homepage.py index 1710fd0f..5461f04f 100644 --- a/app/pages/homepage.py +++ b/app/pages/homepage.py @@ -46,232 +46,226 @@ def homepage_layout(user_headers, user_credentials, lang="fr"): return dbc.Container( [ - dbc.Row( - [ - dbc.Col([create_event_list()], width=2, className="mb-4"), - dbc.Col( - [ + dbc.Row([ + dbc.Col([create_event_list()], width=2, className="mb-4"), + dbc.Col( + [ + html.Div( + id="zoom-containement-container", + className="common-style", + style={"overflow": "hidden"}, + children=[ + html.Div( + id="image-container-with-bbox", + style={"position": "relative"}, + children=[ + html.Div( + id="image-container", + children=[ + html.Img( + id="main-image", + src=translate[lang]["no_alert_default_image"], + className="zoomable-image", + style={"maxWidth": "100%", "height": "auto"}, + ) + ], + ), + html.Div( + id="bbox-container", + style={"display": "block"}, + children=[ + html.Div( + id="bbox-positioning", + style={"display": "none"}, + children=[ + html.Div( + id="bbox-styling", + style={ + "border": "2px solid red", + "height": "100%", + "width": "100%", + "zIndex": "10", + }, + ), + ], + ) + ], + ), + ], + ), + ], + ), + dbc.Row( + [ + dbc.Col( + dbc.Button( + html.Img(src="assets/images/play-pause.svg"), + id="auto-move-button", + n_clicks=1, + style={"height": "100%", "width": "100%"}, + ), + width=1, + ), + dbc.Col( + html.Div( + dcc.Slider(id="image-slider", min=0, max=10, step=1, value=0), + id="slider-container", + className="common-style-slider", + style={"display": "none"}, + ), + width=11, + ), + ], + style={"marginTop": "10px"}, + ), + dbc.Row( + [ + dbc.Col( + dbc.Button( + translate[lang]["show_hide_prediction"], + id="hide-bbox-button", + n_clicks=0, + className="btn-uniform", + style={}, # Will be overwritten dynamically + ), + width=3, + ), + dbc.Col( + html.A( + dbc.Button( + translate[lang]["download_image"], + className="btn-uniform", + id="dl-image-button", + ), + className="no-underline", + id="download-link", + download="", + href="", + target="_blank", + ), + width=3, + ), + dbc.Col( + dbc.Button( + translate[lang]["acknowledge_alert"], + id="acknowledge-button", + n_clicks=0, + className="btn-uniform", + ), + width=3, + ), + ], + className="mb-4", + style={"display": "flex", "marginTop": "10px", "justify-content": "space-evenly"}, + ), + ], + width=8, + style={"padding": "0"}, + ), + dbc.Col( + [ + html.Div( html.Div( - id="zoom-containement-container", + id="alert-information", className="common-style", - style={"overflow": "hidden"}, + style={"display": "none", "padding": "8px"}, children=[ html.Div( - id="image-container-with-bbox", - style={"position": "relative"}, + id="alert-information-styling-container", children=[ + html.H5( + translate[lang]["alert_information"], style={"text-align": "center"} + ), html.Div( - id="image-container", + id="alert-camera", children=[ - html.Img( - id="main-image", - src=translate[lang]["no_alert_default_image"], - className="zoomable-image", - style={"maxWidth": "100%", "height": "auto"}, - ) + html.Span( + id="alert-camera-header", + children=translate[lang]["camera"], + className="alert-information-title", + ), + html.Span( + id="alert-camera-value", + children=[], + ), ], ), html.Div( - id="bbox-container", - style={"display": "block"}, + id="camera-location", children=[ - html.Div( - id="bbox-positioning", - style={"display": "none"}, - children=[ - html.Div( - id="bbox-styling", - style={ - "border": "2px solid red", - "height": "100%", - "width": "100%", - "zIndex": "10", - }, - ), - ], - ) + html.Span( + id="camera-location-header", + children=translate[lang]["camera_location"], + className="alert-information-title", + ), + html.Span( + id="camera-location-value", + children=[], + ), ], ), - ], - ), - ], - ), - dbc.Row( - [ - dbc.Col( - dbc.Button( - html.Img(src="assets/images/play-pause.svg"), - id="auto-move-button", - n_clicks=1, - style={"height": "100%", "width": "100%"} - ), - width=1 - ), - dbc.Col( - html.Div( - dcc.Slider(id="image-slider", min=0, max=10, step=1, value=0), - id="slider-container", - className="common-style-slider", - style={"display": "none"} - ), - width=11 - ) - - ], style={"marginTop": "10px"} - ), - dbc.Row( - [ - dbc.Col( - dbc.Button( - translate[lang]["show_hide_prediction"], - id="hide-bbox-button", - n_clicks=0, - className="btn-uniform", - style={}, # Will be overwritten dynamically - ), - width=3, - ), - dbc.Col( - html.A( - dbc.Button( - translate[lang]["download_image"], - className="btn-uniform", - id="dl-image-button", + html.Div( + id="alert-azimuth", + children=[ + html.Span( + id="alert-azimuth-header", + children=translate[lang]["detection_azimuth"], + className="alert-information-title", + ), + html.Span( + id="alert-azimuth-value", + children=[], + ), + ], ), - className="no-underline", - id="download-link", - download="", - href="", - target="_blank", - ), - width=3, - ), - dbc.Col( - dbc.Button( - translate[lang]["acknowledge_alert"], - id="acknowledge-button", - n_clicks=0, - className="btn-uniform", - ), - width=3, + html.Div( + id="alert-date", + children=[ + html.Span( + id="alert-date-header", + children=translate[lang]["date"], + className="alert-information-title", + ), + html.Span( + id="alert-date-value", + children=[], + ), + ], + ), + ], ), ], - className="mb-4", - style={"display": "flex", "marginTop": "10px", "justify-content": "space-evenly"}, - ), - ], - width=8, - style={"padding": "0"} - ), - dbc.Col( - [ - html.Div( - html.Div( - id="alert-information", - className="common-style", - style={"display": "none", "padding": "8px"}, - children=[ - html.Div( - id="alert-information-styling-container", - children=[ - html.H5(translate[lang]["alert_information"], - style={"text-align": "center"}), - html.Div( - id="alert-camera", - children=[ - html.Span( - id="alert-camera-header", - children=translate[lang]["camera"], - className="alert-information-title" - ), - html.Span( - id="alert-camera-value", - children=[], - ), - ], - ), - html.Div( - id="camera-location", - children=[ - html.Span( - id="camera-location-header", - children=translate[lang]["camera_location"], - className="alert-information-title" - ), - html.Span( - id="camera-location-value", - children=[], - ), - ], - ), - html.Div( - id="alert-azimuth", - children=[ - html.Span( - id="alert-azimuth-header", - children=translate[lang]["detection_azimuth"], - className="alert-information-title" - ), - html.Span( - id="alert-azimuth-value", - children=[], - ), - ], - ), - html.Div( - id="alert-date", - children=[ - html.Span( - id="alert-date-header", - children=translate[lang]["date"], - className="alert-information-title" - ), - html.Span( - id="alert-date-value", - children=[], - ), - ], - ), - ], - ), - ], - ), - id="alert-panel", ), - - html.Div( - dbc.Col( - build_alerts_map(user_headers, user_credentials), - className="common-style", - style={ - "position": "relative", - "width": "100%", - "paddingTop": "100%", - }, - ), + id="alert-panel", + ), + html.Div( + dbc.Col( + build_alerts_map(user_headers, user_credentials), + className="common-style", + style={ + "position": "relative", + "width": "100%", + "paddingTop": "100%", + }, ), - html.Div( - dbc.Button( - translate[lang]["enlarge_map"], - className="common-style", - style={ - "backgroundColor": "#FEBA6A", - "color": "black", - "width": "100%" - }, - id="map-button", - ), + ), + html.Div( + dbc.Button( + translate[lang]["enlarge_map"], + className="common-style", + style={"backgroundColor": "#FEBA6A", "color": "black", "width": "100%"}, + id="map-button", ), - ], - width=2, - style={ - "display" : "flex", - "flex-direction": "column", - "gap" : "16px", - }, - ), - ] - ), + ), + ], + width=2, + style={ + "display": "flex", + "flex-direction": "column", + "gap": "16px", + }, + ), + ]), dcc.Interval(id="auto-slider-update", interval=500, n_intervals=0), dbc.Modal( [ diff --git a/app/pages/login.py b/app/pages/login.py index 97f5b8b4..de9698cc 100644 --- a/app/pages/login.py +++ b/app/pages/login.py @@ -27,45 +27,43 @@ def login_layout(lang="fr"): """ This function creates and returns the login page, which opens at the beginning of each session for user authentication. """ - return html.Div( - [ - html.Center( - [ - html.Div(style={"height": "10px"}), - html.Img(src=pyro_logo, width="30%"), - html.Div(style={"height": "30px"}), - dbc.Input( - id="username_input", - type="text", - placeholder=translate[lang]["username_placeholder"], - style={"width": "250px"}, - autoFocus=True, - ), - html.Div(style={"height": "15px"}), # Spacing - dbc.Input( - id="password_input", - type="password", - placeholder=translate[lang]["password_placeholder"], - style={"width": "250px"}, - ), - html.Div(style={"height": "15px"}), # Spacing - dbc.Button( - translate[lang]["login_button_text"], - id="send_form_button", - color="primary", - className="ml-3", - ), - html.Div(style={"height": "15px"}), # Spacing - # Feedback message area - html.Div(id="form_feedback_area"), - html.Div( - dbc.Spinner(), - id="loading_spinner", - style={"display": "none"}, - ), - # Store the current language - dcc.Store(id="language", data=lang), - ], - ), - ] - ) + return html.Div([ + html.Center( + [ + html.Div(style={"height": "10px"}), + html.Img(src=pyro_logo, width="30%"), + html.Div(style={"height": "30px"}), + dbc.Input( + id="username_input", + type="text", + placeholder=translate[lang]["username_placeholder"], + style={"width": "250px"}, + autoFocus=True, + ), + html.Div(style={"height": "15px"}), # Spacing + dbc.Input( + id="password_input", + type="password", + placeholder=translate[lang]["password_placeholder"], + style={"width": "250px"}, + ), + html.Div(style={"height": "15px"}), # Spacing + dbc.Button( + translate[lang]["login_button_text"], + id="send_form_button", + color="primary", + className="ml-3", + ), + html.Div(style={"height": "15px"}), # Spacing + # Feedback message area + html.Div(id="form_feedback_area"), + html.Div( + dbc.Spinner(), + id="loading_spinner", + style={"display": "none"}, + ), + # Store the current language + dcc.Store(id="language", data=lang), + ], + ), + ]) diff --git a/app/utils/display.py b/app/utils/display.py index 1376cf4a..9687311a 100644 --- a/app/utils/display.py +++ b/app/utils/display.py @@ -88,12 +88,10 @@ def build_sites_markers(user_headers, user_credentials): icon=icon, children=[ dl.Tooltip(site_name), - dl.Popup( - [ - html.H2(f"Site {site_name}"), - html.P(f"Coordonnées : ({lat}, {lon})"), - ] - ), + dl.Popup([ + html.H2(f"Site {site_name}"), + html.P(f"Coordonnées : ({lat}, {lon})"), + ]), ], ) ) @@ -190,7 +188,7 @@ def create_event_list_from_alerts(api_events): html.Div(event["created_at"].strftime("%Y-%m-%d %H:%M")), ], n_clicks=0, - className="alert-card" + className="alert-card", ) for _, event in filtered_events.iterrows() ] From f21a7b2de36239ea8ecc5b95956790b220aa82cc Mon Sep 17 00:00:00 2001 From: fe51 <55736935+fe51@users.noreply.github.com> Date: Mon, 27 Jan 2025 14:07:30 +0100 Subject: [PATCH 09/10] style : Updated border radius, alert default color & info panel style --- app/assets/css/style.css | 20 ++++++++++++-------- app/pages/homepage.py | 2 +- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/app/assets/css/style.css b/app/assets/css/style.css index 8efa2e84..15f758df 100644 --- a/app/assets/css/style.css +++ b/app/assets/css/style.css @@ -12,7 +12,7 @@ /* Handle */ ::-webkit-scrollbar-thumb { background: #FEBA6A; /* Scrollbar handle color */ - border-radius: 5px; + border-radius: 8px; } /* Handle on hover */ @@ -39,14 +39,14 @@ a.no-underline { /* Common style for containers and panels */ .common-style { - border: 1px solid #044448; - border-radius: 4px; + border: 0px solid #044448; + border-radius: 8px; background-color: rgba(4, 68, 72, 0.1); } .common-style-slider { - border: 2px solid #044448; - border-radius: 10px; + border: 0px solid #044448; + border-radius: 8px; background-color: rgba(4, 68, 72, 0.1); } @@ -59,12 +59,13 @@ a.no-underline { } .alert-card { - background-color: #FFE2C2; + background-color: #FFEBD6; margin-bottom: 12px; padding: 8px; - border-radius: 4px; + border-radius: 8px; width: 100%; - border: 1px solid; + border: 0px solid; + box-shadow: 0px 3px 1px -2px rgba(0,0,0,0.2),0px 2px 2px 0px rgba(0,0,0,0.14),0px 1px 5px 0px rgba(0,0,0,0.12); } #alert-information-styling-container { @@ -72,6 +73,9 @@ a.no-underline { flex-direction: column; gap: 8px; padding: 8px; + border-radius: 8px; + border: 1px solid rgba(4, 68, 72, 0.1); + background-color: white; } .alert-information-title { diff --git a/app/pages/homepage.py b/app/pages/homepage.py index 5461f04f..ec7907de 100644 --- a/app/pages/homepage.py +++ b/app/pages/homepage.py @@ -102,7 +102,7 @@ def homepage_layout(user_headers, user_credentials, lang="fr"): html.Img(src="assets/images/play-pause.svg"), id="auto-move-button", n_clicks=1, - style={"height": "100%", "width": "100%"}, + style={"height": "100%", "width": "100%", "border": "0"}, ), width=1, ), From aa327e8ed978c7eb1f63565433efdbbd9d9573f9 Mon Sep 17 00:00:00 2001 From: fe51 <55736935+fe51@users.noreply.github.com> Date: Tue, 28 Jan 2025 08:51:48 +0100 Subject: [PATCH 10/10] style: black --- app/callbacks/data_callbacks.py | 10 +- app/callbacks/display_callbacks.py | 10 +- app/components/alerts.py | 8 +- app/layouts/main_layout.py | 88 ++++--- app/pages/homepage.py | 404 +++++++++++++++-------------- app/pages/login.py | 82 +++--- app/utils/display.py | 10 +- 7 files changed, 316 insertions(+), 296 deletions(-) diff --git a/app/callbacks/data_callbacks.py b/app/callbacks/data_callbacks.py index 0ee6343d..b4638356 100644 --- a/app/callbacks/data_callbacks.py +++ b/app/callbacks/data_callbacks.py @@ -190,10 +190,12 @@ def api_watcher(n_intervals, user_credentials, local_alerts, user_headers): if len(api_alerts) == 0: return [ - json.dumps({ - "data": pd.DataFrame().to_json(orient="split"), - "data_loaded": True, - }) + json.dumps( + { + "data": pd.DataFrame().to_json(orient="split"), + "data_loaded": True, + } + ) ] else: diff --git a/app/callbacks/display_callbacks.py b/app/callbacks/display_callbacks.py index 82ec29bb..f853927a 100644 --- a/app/callbacks/display_callbacks.py +++ b/app/callbacks/display_callbacks.py @@ -154,10 +154,12 @@ def update_display_data(event_id_on_display, local_alerts): raise PreventUpdate if event_id_on_display == 0: - return json.dumps({ - "data": pd.DataFrame().to_json(orient="split"), - "data_loaded": True, - }) + return json.dumps( + { + "data": pd.DataFrame().to_json(orient="split"), + "data_loaded": True, + } + ) else: if event_id_on_display == 0: event_id_on_display = local_alerts["id"].values[0] diff --git a/app/components/alerts.py b/app/components/alerts.py index 1331c1e0..3a631354 100644 --- a/app/components/alerts.py +++ b/app/components/alerts.py @@ -25,6 +25,8 @@ def create_event_list(): "padding-right": "10px", # Prevent scroll bar from touching alerts list } - return html.Div([ - html.Div(id="alert-list-container", style=event_list_style, children=[]), # Empty container - ]) + return html.Div( + [ + html.Div(id="alert-list-container", style=event_list_style, children=[]), # Empty container + ] + ) diff --git a/app/layouts/main_layout.py b/app/layouts/main_layout.py index 8bbe019a..ba9e3827 100644 --- a/app/layouts/main_layout.py +++ b/app/layouts/main_layout.py @@ -26,43 +26,51 @@ def get_main_layout(): - return html.Div([ - dcc.Location(id="url", refresh=False), - html.Div( - id="custom_js_trigger", - className="custom_js_trigger", - title="none", - style={"display": "none"}, - ), - html.Div([ - Navbar(), # This includes the navbar at the top of the page - html.Div(id="page-content"), - ]), - dcc.Interval(id="main_api_fetch_interval", interval=30 * 1000), - dcc.Store( - id="store_api_alerts_data", - storage_type="session", - data=json.dumps({ - "data": pd.DataFrame().to_json(orient="split"), - "data_loaded": False, - }), - ), - dcc.Store( - id="alert_on_display", - storage_type="session", - data=json.dumps({ - "data": pd.DataFrame().to_json(orient="split"), - "data_loaded": False, - }), - ), - dcc.Store(id="event_id_on_display", data=0), - dcc.Store(id="auto-move-state", data={"active": True}), - # Add this to your app.layout - dcc.Store(id="bbox_visibility", data={"visible": True}), - # Storage components saving the user's headers and credentials - dcc.Store(id="user_headers", storage_type="session", data=user_headers), - # [TEMPORARY FIX] Storing the user's credentials to refresh the token when needed - dcc.Store(id="user_credentials", storage_type="session", data=user_credentials), - dcc.Store(id="to_acknowledge", data=0), - dcc.Store(id="trigger_no_events", data=False), - ]) + return html.Div( + [ + dcc.Location(id="url", refresh=False), + html.Div( + id="custom_js_trigger", + className="custom_js_trigger", + title="none", + style={"display": "none"}, + ), + html.Div( + [ + Navbar(), # This includes the navbar at the top of the page + html.Div(id="page-content"), + ] + ), + dcc.Interval(id="main_api_fetch_interval", interval=30 * 1000), + dcc.Store( + id="store_api_alerts_data", + storage_type="session", + data=json.dumps( + { + "data": pd.DataFrame().to_json(orient="split"), + "data_loaded": False, + } + ), + ), + dcc.Store( + id="alert_on_display", + storage_type="session", + data=json.dumps( + { + "data": pd.DataFrame().to_json(orient="split"), + "data_loaded": False, + } + ), + ), + dcc.Store(id="event_id_on_display", data=0), + dcc.Store(id="auto-move-state", data={"active": True}), + # Add this to your app.layout + dcc.Store(id="bbox_visibility", data={"visible": True}), + # Storage components saving the user's headers and credentials + dcc.Store(id="user_headers", storage_type="session", data=user_headers), + # [TEMPORARY FIX] Storing the user's credentials to refresh the token when needed + dcc.Store(id="user_credentials", storage_type="session", data=user_credentials), + dcc.Store(id="to_acknowledge", data=0), + dcc.Store(id="trigger_no_events", data=False), + ] + ) diff --git a/app/pages/homepage.py b/app/pages/homepage.py index ec7907de..82528fd6 100644 --- a/app/pages/homepage.py +++ b/app/pages/homepage.py @@ -46,226 +46,228 @@ def homepage_layout(user_headers, user_credentials, lang="fr"): return dbc.Container( [ - dbc.Row([ - dbc.Col([create_event_list()], width=2, className="mb-4"), - dbc.Col( - [ - html.Div( - id="zoom-containement-container", - className="common-style", - style={"overflow": "hidden"}, - children=[ - html.Div( - id="image-container-with-bbox", - style={"position": "relative"}, - children=[ - html.Div( - id="image-container", - children=[ - html.Img( - id="main-image", - src=translate[lang]["no_alert_default_image"], - className="zoomable-image", - style={"maxWidth": "100%", "height": "auto"}, - ) - ], - ), - html.Div( - id="bbox-container", - style={"display": "block"}, - children=[ - html.Div( - id="bbox-positioning", - style={"display": "none"}, - children=[ - html.Div( - id="bbox-styling", - style={ - "border": "2px solid red", - "height": "100%", - "width": "100%", - "zIndex": "10", - }, - ), - ], - ) - ], - ), - ], - ), - ], - ), - dbc.Row( - [ - dbc.Col( - dbc.Button( - html.Img(src="assets/images/play-pause.svg"), - id="auto-move-button", - n_clicks=1, - style={"height": "100%", "width": "100%", "border": "0"}, - ), - width=1, - ), - dbc.Col( - html.Div( - dcc.Slider(id="image-slider", min=0, max=10, step=1, value=0), - id="slider-container", - className="common-style-slider", - style={"display": "none"}, - ), - width=11, - ), - ], - style={"marginTop": "10px"}, - ), - dbc.Row( - [ - dbc.Col( - dbc.Button( - translate[lang]["show_hide_prediction"], - id="hide-bbox-button", - n_clicks=0, - className="btn-uniform", - style={}, # Will be overwritten dynamically - ), - width=3, - ), - dbc.Col( - html.A( - dbc.Button( - translate[lang]["download_image"], - className="btn-uniform", - id="dl-image-button", - ), - className="no-underline", - id="download-link", - download="", - href="", - target="_blank", - ), - width=3, - ), - dbc.Col( - dbc.Button( - translate[lang]["acknowledge_alert"], - id="acknowledge-button", - n_clicks=0, - className="btn-uniform", - ), - width=3, - ), - ], - className="mb-4", - style={"display": "flex", "marginTop": "10px", "justify-content": "space-evenly"}, - ), - ], - width=8, - style={"padding": "0"}, - ), - dbc.Col( - [ - html.Div( + dbc.Row( + [ + dbc.Col([create_event_list()], width=2, className="mb-4"), + dbc.Col( + [ html.Div( - id="alert-information", + id="zoom-containement-container", className="common-style", - style={"display": "none", "padding": "8px"}, + style={"overflow": "hidden"}, children=[ html.Div( - id="alert-information-styling-container", + id="image-container-with-bbox", + style={"position": "relative"}, children=[ - html.H5( - translate[lang]["alert_information"], style={"text-align": "center"} - ), - html.Div( - id="alert-camera", - children=[ - html.Span( - id="alert-camera-header", - children=translate[lang]["camera"], - className="alert-information-title", - ), - html.Span( - id="alert-camera-value", - children=[], - ), - ], - ), html.Div( - id="camera-location", + id="image-container", children=[ - html.Span( - id="camera-location-header", - children=translate[lang]["camera_location"], - className="alert-information-title", - ), - html.Span( - id="camera-location-value", - children=[], - ), + html.Img( + id="main-image", + src=translate[lang]["no_alert_default_image"], + className="zoomable-image", + style={"maxWidth": "100%", "height": "auto"}, + ) ], ), html.Div( - id="alert-azimuth", + id="bbox-container", + style={"display": "block"}, children=[ - html.Span( - id="alert-azimuth-header", - children=translate[lang]["detection_azimuth"], - className="alert-information-title", - ), - html.Span( - id="alert-azimuth-value", - children=[], - ), - ], - ), - html.Div( - id="alert-date", - children=[ - html.Span( - id="alert-date-header", - children=translate[lang]["date"], - className="alert-information-title", - ), - html.Span( - id="alert-date-value", - children=[], - ), + html.Div( + id="bbox-positioning", + style={"display": "none"}, + children=[ + html.Div( + id="bbox-styling", + style={ + "border": "2px solid red", + "height": "100%", + "width": "100%", + "zIndex": "10", + }, + ), + ], + ) ], ), ], ), ], ), - id="alert-panel", - ), - html.Div( - dbc.Col( - build_alerts_map(user_headers, user_credentials), - className="common-style", - style={ - "position": "relative", - "width": "100%", - "paddingTop": "100%", - }, + dbc.Row( + [ + dbc.Col( + dbc.Button( + html.Img(src="assets/images/play-pause.svg"), + id="auto-move-button", + n_clicks=1, + style={"height": "100%", "width": "100%", "border": "0"}, + ), + width=1, + ), + dbc.Col( + html.Div( + dcc.Slider(id="image-slider", min=0, max=10, step=1, value=0), + id="slider-container", + className="common-style-slider", + style={"display": "none"}, + ), + width=11, + ), + ], + style={"marginTop": "10px"}, ), - ), - html.Div( - dbc.Button( - translate[lang]["enlarge_map"], - className="common-style", - style={"backgroundColor": "#FEBA6A", "color": "black", "width": "100%"}, - id="map-button", + dbc.Row( + [ + dbc.Col( + dbc.Button( + translate[lang]["show_hide_prediction"], + id="hide-bbox-button", + n_clicks=0, + className="btn-uniform", + style={}, # Will be overwritten dynamically + ), + width=3, + ), + dbc.Col( + html.A( + dbc.Button( + translate[lang]["download_image"], + className="btn-uniform", + id="dl-image-button", + ), + className="no-underline", + id="download-link", + download="", + href="", + target="_blank", + ), + width=3, + ), + dbc.Col( + dbc.Button( + translate[lang]["acknowledge_alert"], + id="acknowledge-button", + n_clicks=0, + className="btn-uniform", + ), + width=3, + ), + ], + className="mb-4", + style={"display": "flex", "marginTop": "10px", "justify-content": "space-evenly"}, ), - ), - ], - width=2, - style={ - "display": "flex", - "flex-direction": "column", - "gap": "16px", - }, - ), - ]), + ], + width=8, + style={"padding": "0"}, + ), + dbc.Col( + [ + html.Div( + html.Div( + id="alert-information", + className="common-style", + style={"display": "none", "padding": "8px"}, + children=[ + html.Div( + id="alert-information-styling-container", + children=[ + html.H5( + translate[lang]["alert_information"], style={"text-align": "center"} + ), + html.Div( + id="alert-camera", + children=[ + html.Span( + id="alert-camera-header", + children=translate[lang]["camera"], + className="alert-information-title", + ), + html.Span( + id="alert-camera-value", + children=[], + ), + ], + ), + html.Div( + id="camera-location", + children=[ + html.Span( + id="camera-location-header", + children=translate[lang]["camera_location"], + className="alert-information-title", + ), + html.Span( + id="camera-location-value", + children=[], + ), + ], + ), + html.Div( + id="alert-azimuth", + children=[ + html.Span( + id="alert-azimuth-header", + children=translate[lang]["detection_azimuth"], + className="alert-information-title", + ), + html.Span( + id="alert-azimuth-value", + children=[], + ), + ], + ), + html.Div( + id="alert-date", + children=[ + html.Span( + id="alert-date-header", + children=translate[lang]["date"], + className="alert-information-title", + ), + html.Span( + id="alert-date-value", + children=[], + ), + ], + ), + ], + ), + ], + ), + id="alert-panel", + ), + html.Div( + dbc.Col( + build_alerts_map(user_headers, user_credentials), + className="common-style", + style={ + "position": "relative", + "width": "100%", + "paddingTop": "100%", + }, + ), + ), + html.Div( + dbc.Button( + translate[lang]["enlarge_map"], + className="common-style", + style={"backgroundColor": "#FEBA6A", "color": "black", "width": "100%"}, + id="map-button", + ), + ), + ], + width=2, + style={ + "display": "flex", + "flex-direction": "column", + "gap": "16px", + }, + ), + ] + ), dcc.Interval(id="auto-slider-update", interval=500, n_intervals=0), dbc.Modal( [ diff --git a/app/pages/login.py b/app/pages/login.py index de9698cc..97f5b8b4 100644 --- a/app/pages/login.py +++ b/app/pages/login.py @@ -27,43 +27,45 @@ def login_layout(lang="fr"): """ This function creates and returns the login page, which opens at the beginning of each session for user authentication. """ - return html.Div([ - html.Center( - [ - html.Div(style={"height": "10px"}), - html.Img(src=pyro_logo, width="30%"), - html.Div(style={"height": "30px"}), - dbc.Input( - id="username_input", - type="text", - placeholder=translate[lang]["username_placeholder"], - style={"width": "250px"}, - autoFocus=True, - ), - html.Div(style={"height": "15px"}), # Spacing - dbc.Input( - id="password_input", - type="password", - placeholder=translate[lang]["password_placeholder"], - style={"width": "250px"}, - ), - html.Div(style={"height": "15px"}), # Spacing - dbc.Button( - translate[lang]["login_button_text"], - id="send_form_button", - color="primary", - className="ml-3", - ), - html.Div(style={"height": "15px"}), # Spacing - # Feedback message area - html.Div(id="form_feedback_area"), - html.Div( - dbc.Spinner(), - id="loading_spinner", - style={"display": "none"}, - ), - # Store the current language - dcc.Store(id="language", data=lang), - ], - ), - ]) + return html.Div( + [ + html.Center( + [ + html.Div(style={"height": "10px"}), + html.Img(src=pyro_logo, width="30%"), + html.Div(style={"height": "30px"}), + dbc.Input( + id="username_input", + type="text", + placeholder=translate[lang]["username_placeholder"], + style={"width": "250px"}, + autoFocus=True, + ), + html.Div(style={"height": "15px"}), # Spacing + dbc.Input( + id="password_input", + type="password", + placeholder=translate[lang]["password_placeholder"], + style={"width": "250px"}, + ), + html.Div(style={"height": "15px"}), # Spacing + dbc.Button( + translate[lang]["login_button_text"], + id="send_form_button", + color="primary", + className="ml-3", + ), + html.Div(style={"height": "15px"}), # Spacing + # Feedback message area + html.Div(id="form_feedback_area"), + html.Div( + dbc.Spinner(), + id="loading_spinner", + style={"display": "none"}, + ), + # Store the current language + dcc.Store(id="language", data=lang), + ], + ), + ] + ) diff --git a/app/utils/display.py b/app/utils/display.py index 9687311a..5c6a8e5a 100644 --- a/app/utils/display.py +++ b/app/utils/display.py @@ -88,10 +88,12 @@ def build_sites_markers(user_headers, user_credentials): icon=icon, children=[ dl.Tooltip(site_name), - dl.Popup([ - html.H2(f"Site {site_name}"), - html.P(f"Coordonnées : ({lat}, {lon})"), - ]), + dl.Popup( + [ + html.H2(f"Site {site_name}"), + html.P(f"Coordonnées : ({lat}, {lon})"), + ] + ), ], ) )