diff --git a/app/app.py b/app/app.py index a83c9fc..797969d 100644 --- a/app/app.py +++ b/app/app.py @@ -1,8 +1,142 @@ -from dash import Dash, html +from typing import Any, Dict, Tuple -app = Dash() +from dash import ( + Dash, + Input, + Output, + State, + callback, + dcc, + get_asset_url, + html, + no_update, +) +from dash.exceptions import PreventUpdate + +from .app_styles import header_style +from .data_chat import send_message + +external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"] + +app = Dash(__name__, external_stylesheets=external_stylesheets) +app.index_string = header_style + +err_style = { + "height": "0px", + "overflow": "hidden", + "transition": "height 0.5s ease-in-out", + "border-radius": "15px", + "background-color": "#FFCCCB", + "text-align": "center", + "color": "#FF6B6B", + "margin-top": "20px", + "margin-left": "20px", + "margin-right": "20px", + "font-weight": "bold", + "display": "flex", + "justify-content": "center", + "align-items": "center", +} + +start_value = "Stelle deine Frage an die Datenbank..." +app.layout = html.Div( + [ + html.Div( + [ + html.H1("Datenbank-Chat", className="heading"), + html.Img(src=get_asset_url("logo.png"), className="logo"), + ], + className="header-container", + ), # Header + dcc.Store( + id="tmp-value", data=start_value, storage_type="session" + ), # Store previous prompt + dcc.Textarea( + id="input-field", + value=start_value, + style={"width": "96%", "height": 200, "margin-left": "20px"}, + ), # Input field + html.Div([]), # Needed for keeping the layout clean + html.Button( + "Abschicken", + id="submit-button", + n_clicks=0, + disabled=False, + style={"margin-left": "20px"}, + ), # Submit button + html.Div( + [html.P("Bitte eine neue Anfrage eingeben.")], id="error", style=err_style + ), # Error message (only visible if input is not updated but submit button is clicked) + dcc.Loading( + id="loading", + type="default", + children=[ + html.Div( + "Hier erscheint die Antwort der Datenbank.", + id="text-output", + style={ + "whiteSpace": "pre-line", + "margin-top": "30px", + "margin-left": "20px", + "margin-right": "20px", + "border": "2px solid #86bc25", + "border-radius": "15px", + "padding": "20px", + }, + ) + ], + ), + ], # Output field + className="container", +) + + +@callback( + Output("text-output", "children"), + Output("tmp-value", "data"), + Output("error", "style"), + Input("submit-button", "n_clicks"), + State("input-field", "value"), + State("tmp-value", "data"), + prevent_initial_call=True, + running=[ + (Output("submit-button", "disabled"), True, False), + ( + Output("submit-button", "style"), + {"opacity": 0.5, "margin-left": "20px"}, + {"opacity": 1.0, "margin-left": "20px"}, + ), + ], +) +def update_output(n_clicks: int, value: str, data: str) -> Tuple[str, str, Dict[str, Any]]: + """Update the output based on user input and button clicks. + + Parameters + ---------- + n_clicks : int + Number of times the submit button has been clicked. + value : str + Current value of the input field. + data : str + Previously stored value. + + Returns + ------- + Tuple[str, str, Dict[str, Any]] + Updated output text, new stored value, and error style. + """ + global err_style + if n_clicks > 0 and value != data: + result = send_message(value) + err_style["height"] = "0px" + return result, value, err_style + elif value == data: + + err_style["height"] = "50px" + return no_update, no_update, err_style + + raise PreventUpdate -app.layout = [html.Div(children="Hello World")] server = app.server diff --git a/app/app_styles.py b/app/app_styles.py new file mode 100644 index 0000000..9d46c7f --- /dev/null +++ b/app/app_styles.py @@ -0,0 +1,37 @@ +header_style = """ + + +
+ {%metas%} +