-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdashboard.py
150 lines (128 loc) · 4.74 KB
/
dashboard.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
from dash import Dash, html, dcc, Input, Output
import os
from dotenv import load_dotenv
import json
from flask_caching import Cache
from total_listings_KPI_module import total_listings_kpi
from avg_price_KPI_module import average_price_kpi
from avg_price_sqm_KPI_module import average_price_per_sqm_kpi
from heatmap_module import create_heatmap, heatmap_component
from piechart_module import property_age_pie_chart
from barchart_module import horizontal_bar_chart_component
from google.oauth2 import service_account
from google.cloud import bigquery
load_dotenv()
credentials_json = os.getenv("GOOGLE_APPLICATION_CREDENTIALS_JSON")
if not credentials_json:
raise ValueError("The GOOGLE_APPLICATION_CREDENTIALS_JSON environment variable is not set.")
credentials = service_account.Credentials.from_service_account_info(
json.loads(credentials_json)
)
project_id = credentials.project_id
client = bigquery.Client(credentials=credentials, project=project_id)
app = Dash(__name__)
server = app.server
# Configure server-side caching for performance improvement
cache = Cache(server, config={
'CACHE_TYPE': 'simple',
'CACHE_DEFAULT_TIMEOUT': 300
})
app.layout = html.Div([
html.H1("Estonian Condominium Listings by KV.ee", style={
"textAlign": "center",
"fontFamily": "Orbitron",
"fontSize": "36px",
"color": "#FFE1FF",
"margin": "0 0 10px 0",
}),
# KPI Section
html.Div([
html.Div(id="total-listings-kpi-container"),
html.Div(id="avg-price-kpi", children=average_price_kpi(None)),
html.Div(id="avg-price-sqm-kpi", children=average_price_per_sqm_kpi(None)),
], style={
"display": "flex",
"justifyContent": "space-between",
"gap": "10px",
"marginBottom": "10px",
"padding": "0 10px",
}),
# Chart Section
html.Div([
html.Div(heatmap_component(), id="heatmap-container", style={
"width": "700px",
"height": "450px",
"marginRight": "10px",
}),
html.Div(id="pie-chart-container", children=property_age_pie_chart(None), style={
"width": "350px",
"height": "450px",
"marginLeft": "10px",
}),
html.Div(id="bar-chart-container", children=horizontal_bar_chart_component(None), style={
"width": "350px",
"height": "450px",
}),
], style={
"display": "flex",
"justifyContent": "space-between",
"gap": "10px",
"padding": "0 10px",
})
], style={
"backgroundColor": "#433878",
"padding": "10px",
"border": "5px solid #E4B1F0",
"borderRadius": "10px",
"boxSizing": "border-box",
"width": "1460px",
"margin": "0 auto",
"overflow": "hidden",
})
@app.callback(
Output("total-listings-kpi-container", "children"),
Input("heatmap", "clickData"),
memoize=True # Use memoization to cache function results based on inputs
)
@cache.memoize() # Use Flask-Caching here to cache the output based on the click_data input
def update_total_listings_kpi(click_data):
selected_region = click_data["points"][0]["location"] if click_data and "points" in click_data else None
return total_listings_kpi(selected_region)
@app.callback(
Output("heatmap", "figure"),
Input("heatmap", "clickData")
)
def update_heatmap(click_data):
selected_region = click_data["points"][0]["location"] if click_data and "points" in click_data else None
return create_heatmap(selected_region)
@app.callback(
Output("avg-price-kpi", "children"),
Input("heatmap", "clickData")
)
def update_avg_price_kpi(click_data):
selected_region = click_data["points"][0]["location"] if click_data and "points" in click_data else None
return average_price_kpi(selected_region)
@app.callback(
Output("avg-price-sqm-kpi", "children"),
Input("heatmap", "clickData")
)
def update_avg_price_sqm_kpi(click_data):
selected_region = click_data["points"][0]["location"] if click_data and "points" in click_data else None
return average_price_per_sqm_kpi(selected_region)
@app.callback(
Output("pie-chart-container", "children"),
Input("heatmap", "clickData")
)
def update_pie_chart(click_data):
selected_region = click_data["points"][0]["location"] if click_data and "points" in click_data else None
return property_age_pie_chart(selected_region)
@app.callback(
Output("bar-chart-container", "children"),
Input("heatmap", "clickData")
)
def update_bar_chart(click_data):
selected_region = click_data["points"][0]["location"] if click_data and "points" in click_data else None
return horizontal_bar_chart_component(selected_region)
if __name__ == "__main__":
port = int(os.environ.get("PORT", 8050))
app.run_server(host="0.0.0.0", port=port)