diff --git a/src/aki_prj23_transparenzregister/ui/assets/company_stats.css b/src/aki_prj23_transparenzregister/ui/assets/company_stats.css index cc6c24e..340b3db 100644 --- a/src/aki_prj23_transparenzregister/ui/assets/company_stats.css +++ b/src/aki_prj23_transparenzregister/ui/assets/company_stats.css @@ -27,6 +27,7 @@ width: flex; min-width: 500px; max-width: 900px; + min-height: 150px; display: inline-block; vertical-align: middle; margin-left: 2%; @@ -41,6 +42,16 @@ padding-top: 10px; } +.stats-wrapper .widget-large .widget-content { + color: var(--raisin-black); + margin: 0; + text-align: center; + padding-top: 20px; + padding-bottom: 20px; + padding-left: 10px; + padding-right: 10px; +} + .stats-wrapper .widget-small { background-color: var(--ash-gray); border: 1px solid; diff --git a/src/aki_prj23_transparenzregister/ui/assets/networkx_style.css b/src/aki_prj23_transparenzregister/ui/assets/networkx_style.css index 8db0392..88f5c1a 100644 --- a/src/aki_prj23_transparenzregister/ui/assets/networkx_style.css +++ b/src/aki_prj23_transparenzregister/ui/assets/networkx_style.css @@ -174,3 +174,14 @@ /* background-color: var(--raisin-black); */ } + +.person-network{ + margin-left: 2%; + margin-right: 2%; + margin-top: 20px; + border: 1px solid; + border-color: var(--raisin-black); + border-radius: 20px; + float: left; + width: 96%; +} diff --git a/src/aki_prj23_transparenzregister/ui/pages/person.py b/src/aki_prj23_transparenzregister/ui/pages/person.py index d5b88e6..dff55e3 100644 --- a/src/aki_prj23_transparenzregister/ui/pages/person.py +++ b/src/aki_prj23_transparenzregister/ui/pages/person.py @@ -3,7 +3,7 @@ import dash from cachetools import TTLCache, cached from dash import Input, Output, callback, html -from aki_prj23_transparenzregister.ui import data_elements, header_elements +from aki_prj23_transparenzregister.ui import data_elements, person_elements from aki_prj23_transparenzregister.ui.data_elements import redirect_via_plot_click from aki_prj23_transparenzregister.ui.session_handler import SessionHandler @@ -20,7 +20,7 @@ def layout(value: str = "1") -> html.Div: value: Person id of the chosen person on the home page dropdown. Returns: - The html divs for the person page. + The html divs for the person page including the widgets and the network graph. """ if not value: return html.Div("Diese Seite kann nicht angezeigt werden.") @@ -31,7 +31,12 @@ def layout(value: str = "1") -> html.Div: # get all necessary data of the selected person selected_person_stats = data_elements.get_person_data(session).loc[person_id] selected_person_name = f"{selected_person_stats['person_firstname']} {selected_person_stats['person_lastname']}" - return header_elements.create_selection_header(selected_person_name) + return ( + person_elements.create_person_widgets(person_id, selected_person_name), + html.Div( + className="person-network", children=["Hier kann der Social Graph hin"] + ), + ) @callback( diff --git a/src/aki_prj23_transparenzregister/ui/person_elements.py b/src/aki_prj23_transparenzregister/ui/person_elements.py index dabd8f5..0bfcb7c 100644 --- a/src/aki_prj23_transparenzregister/ui/person_elements.py +++ b/src/aki_prj23_transparenzregister/ui/person_elements.py @@ -1 +1,79 @@ """Dash elements for person page.""" +import networkx as nx +from dash import html + +from aki_prj23_transparenzregister.utils.networkx.networkx_data import ( + get_relations_number_from_id, +) + + +def create_small_widget(title: list[str], values: list[int]) -> html: + """Creates a small widget containing a title and content. + + Args: + title: Title of the widget. + values: Content of the widget. + + Returns: + Returns a html div containing the widget. + """ + return html.Div( + className="widget-small", + children=[ + html.H3( + className="widget-title", + children=title, + ), + html.H1( + className="widget-content", + children=values, + ), + ], + ) + + +def create_person_widgets(selected_person_id: int, selected_person_name: str) -> html: + """Creats the widgets of the company page. + + Args: + selected_person_id: Id of the selected person in the dropdown. + selected_person_name: Firstname and lastname of the selected person in the dropdown. + + Returns: + The html div including all widgets. + """ + try: + first_level, second_level, third_level = get_relations_number_from_id( + selected_person_id + ) + + except nx.exception.NetworkXError: + first_level = second_level = third_level = "n.a." # type: ignore + + return html.Div( + className="stats-wrapper", + children=[ + html.Div( + className="widget-large", + children=[ + html.H3( + className="widget-title", + children="Ausgewählte Person", + ), + html.H1( + className="widget-content", + children=[selected_person_name], + ), + ], + ), + create_small_widget( + ["Anzahl Verbindungen", html.Br(), " - erste Ebene"], [first_level] + ), + create_small_widget( + ["Anzahl Verbindungen", html.Br(), " - dritte Ebene"], [second_level] + ), + create_small_widget( + ["Anzahl Verbindungen", html.Br(), " - dritte Ebene"], [third_level] + ), + ], + ) diff --git a/tests/ui/person_page_test.py b/tests/ui/person_page_test.py index 6d30242..d139706 100644 --- a/tests/ui/person_page_test.py +++ b/tests/ui/person_page_test.py @@ -17,11 +17,11 @@ def _set_session(full_db: Session) -> Generator[None, None, None]: def test_import() -> None: - """Checks if an import of the company page can be made.""" + """Checks if an import of the person page can be made.""" assert person is not None def test_layout() -> None: - """Checks if the company page can be created.""" - selected_company_id = "2" - person.layout(selected_company_id) + """Checks if the person page can be created.""" + selected_person_id = "2" + person.layout(selected_person_id)