Added redirection callbacks to the person and the company page. (#423)

This commit is contained in:
Philipp Horstenkamp 2023-12-04 19:11:22 +01:00 committed by GitHub
parent 92d14b5824
commit 319ca3b8ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 76 additions and 40 deletions

View File

@ -48,6 +48,7 @@ app.layout = html.Div(
Output("url", "href", allow_duplicate=True),
Input("home-button", "n_clicks"),
prevent_initial_call=True,
allow_duplicate=True,
)
def go_to_home(click: int) -> str:
"""Updates pages after using the home button.
@ -58,6 +59,7 @@ def go_to_home(click: int) -> str:
Returns:
Returns the href of the home page.
"""
_ = click
if home_path := os.getenv("DASH_URL_BASE_PATHNAME"):
return f"{home_path}"
return "/"

View File

@ -1,11 +1,14 @@
"""Data elements for Dash."""
import os
import dash
import pandas as pd
import sqlalchemy as sa
from cachetools import TTLCache, cached
from loguru import logger
from sqlalchemy.orm import Session
from aki_prj23_transparenzregister.ui.session_handler import SessionHandler
from aki_prj23_transparenzregister.utils.sql import entities
@ -38,7 +41,6 @@ def get_person_data(session: Session) -> pd.DataFrame:
A dataframe containing all available company data including the corresponding district court.
"""
query_person = session.query(entities.Person)
engine = session.bind
if not isinstance(engine, sa.engine.Engine):
raise TypeError
@ -223,3 +225,35 @@ def get_last_article_of_one_company(
if not data:
return pd.DataFrame()
return pd.DataFrame(dict(data), index=[0])
def redirect_via_plot_click(click_data: dict) -> str:
"""Redirects on clicking on a plotted entity to that entity."""
if not click_data:
return dash.no_update
logger.debug(click_data)
db = SessionHandler.session
if not db:
raise ValueError("No SQL session defined.")
home_path = os.getenv("DASH_URL_BASE_PATHNAME", "")
id = (
db.query(entities.Company.id)
.filter(entities.Company.name == click_data["points"][0]["text"])
.first()
)
if id:
url = f"{home_path}/unternehmensdetails/{id[0]}"
logger.debug(f"Redirecting to detail page: {url}")
return url
concatenated_name = entities.Person.firstname + " " + entities.Person.lastname
id = (
db.query(entities.Person.id)
.filter(concatenated_name == click_data["points"][0]["text"])
.first()
)
if id:
url = f"{home_path}/personendetails/{id[0]}"
logger.debug(f"Redirecting to detail page: {url}")
return url
return dash.no_update
# Prevent update if no data point was clicked

View File

@ -1,13 +1,14 @@
"""Company detail page."""
import dash
from cachetools import TTLCache, cached
from dash import html
from dash import Input, Output, callback, html
from aki_prj23_transparenzregister.ui import (
company_elements,
data_elements,
header_elements,
)
from aki_prj23_transparenzregister.ui.data_elements import redirect_via_plot_click
from aki_prj23_transparenzregister.ui.session_handler import SessionHandler
dash.register_page(
@ -44,3 +45,13 @@ def layout(value: str = "1") -> html:
),
company_elements.create_tabs(session, company_id),
)
@callback(
Output("url", "href", allow_duplicate=True),
[Input("company-graph", "clickData")],
prevent_initial_call=True,
)
def redirect_from_company_graph(click_data: dict) -> str:
"""Redirects on clicking on a plotted entity to that entity."""
return redirect_via_plot_click(click_data)

View File

@ -1,5 +1,4 @@
"""Content of home page."""
import os
from functools import lru_cache
from typing import Final
@ -12,7 +11,9 @@ from cachetools import TTLCache, cached
from dash import Input, Output, callback, dash_table, dcc, html
from loguru import logger
from aki_prj23_transparenzregister.ui.session_handler import SessionHandler
from aki_prj23_transparenzregister.ui.data_elements import (
redirect_via_plot_click,
)
from aki_prj23_transparenzregister.utils.networkx.network_2d import (
create_2d_graph,
)
@ -28,7 +29,6 @@ from aki_prj23_transparenzregister.utils.networkx.networkx_data import (
get_all_company_relations,
get_all_person_relations,
)
from aki_prj23_transparenzregister.utils.sql import entities
COLORS: Final[dict[str, str]] = {
"light": "#edefef",
@ -416,37 +416,15 @@ def update_graph_data(
return graph, metrics, nodes_tmp, edges_tmp
@callback(Output("url", "href"), [Input("my-graph", "clickData")])
def redirect(click_data: dict) -> str:
"""Redirects on clicking on an entity to that entity."""
if not click_data:
return dash.no_update
logger.debug(click_data)
db = SessionHandler.session
if not db:
raise ValueError("No SQL session defined.")
home_path = os.getenv("DASH_URL_BASE_PATHNAME", "")
id = (
db.query(entities.Company.id)
.filter(entities.Company.name == click_data["points"][0]["text"])
.first()
@callback(
Output("url", "href"),
[Input("my-graph", "clickData")],
prevent_initial_call=True,
allow_duplicate=True,
)
if id:
url = f"{home_path}/unternehmensdetails/{id[0]}"
logger.info("Redirecting to detail page: url")
return url
concatenated_name = entities.Person.firstname + " " + entities.Person.lastname
id = (
db.query(entities.Person.id)
.filter(concatenated_name == click_data["points"][0]["text"])
.first()
)
if id:
url = f"{home_path}/personendetails/{id[0]}"
logger.info("Redirecting to detail page: url")
return url
return dash.no_update
# Prevent update if no data point was clicked
def redirect_from_home_graph(click_data: dict) -> str:
"""Redirects on clicking on a plotted entity to that entity."""
return redirect_via_plot_click(click_data)
@callback(

View File

@ -1,9 +1,10 @@
"""Person detail page."""
import dash
from cachetools import TTLCache, cached
from dash import html
from dash import Input, Output, callback, html
from aki_prj23_transparenzregister.ui import data_elements, header_elements
from aki_prj23_transparenzregister.ui.data_elements import redirect_via_plot_click
from aki_prj23_transparenzregister.ui.session_handler import SessionHandler
dash.register_page(
@ -31,3 +32,13 @@ def layout(value: str = "1") -> html.Div:
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)
@callback(
Output("url", "href", allow_duplicate=True),
[Input("person-graph", "clickData")],
prevent_initial_call=True,
)
def redirect_from_person_graph(click_data: dict) -> str:
"""Redirects on clicking on a plotted entity to that entity."""
return redirect_via_plot_click(click_data)

View File

@ -213,13 +213,13 @@ def test_layout() -> None:
@pytest.mark.parametrize("empty", ["", None, {}])
def test_redirect_empty(empty: Any) -> None:
"""Tests the redirection on clicking on the plot with an empty argument."""
assert home.redirect(empty) == dash.no_update # type: ignore
assert home.redirect_from_home_graph(empty) == dash.no_update # type: ignore
def test_redirect_content_without_db() -> None:
"""Tests the error when no SQL session is defined."""
with pytest.raises(ValueError, match="No SQL session defined."):
assert home.redirect({"empty": ""})
assert home.redirect_from_home_graph({"empty": ""})
@pytest.mark.usefixtures("_set_session")
@ -236,4 +236,4 @@ def test_redirect_content_without_db() -> None:
)
def test_redirect(click_on: dict, redirect_to: Any) -> None:
"""Tests the redirection when clicking on a plot."""
assert home.redirect({"points": [click_on]}) == redirect_to
assert home.redirect_from_home_graph({"points": [click_on]}) == redirect_to