Clément Simon commited on
Commit
d29a82e
·
1 Parent(s): 4359f48

fix: html refactoring, removed chunks of deprecated code

Browse files
Files changed (4) hide show
  1. app.py +37 -81
  2. static/layout.html +21 -18
  3. static/script.js +25 -1
  4. static/style.css +29 -18
app.py CHANGED
@@ -1,20 +1,18 @@
 
1
  import os
2
- import sys
3
- from datetime import datetime
4
  from pathlib import Path
 
5
  import plotly.graph_objects as go
6
- import uvicorn
7
  from dotenv import load_dotenv
8
- from fastapi import FastAPI, Depends, Request
 
9
  from fastapi.staticfiles import StaticFiles
 
10
  from mistralai.client import ChatMessage, MistralClient
11
  from pydantic import BaseModel
12
- import json
13
- from fastapi.responses import HTMLResponse, RedirectResponse, Response
14
- from datetime import date
15
- from weather import get_weather
16
- from fastapi.templating import Jinja2Templates
17
 
 
18
 
19
  # code that gives the date of today
20
  today = date.today()
@@ -48,8 +46,6 @@ app.mount("/static", StaticFiles(directory=static_dir), name="static")
48
  templates = Jinja2Templates(directory="static")
49
 
50
 
51
-
52
-
53
  def create_world_map(lat, lon):
54
 
55
  fig = go.Figure(go.Scattermapbox(
@@ -84,8 +80,6 @@ def chat_with_mistral(user_input):
84
  return chat_response.choices[0].message.content
85
 
86
 
87
-
88
-
89
  # Profile stuff
90
  class UserProfile(BaseModel):
91
  name: str
@@ -94,27 +88,30 @@ class UserProfile(BaseModel):
94
  lat: float
95
  lon: float
96
 
 
97
  class UserLocation(BaseModel):
98
  city: str
99
 
 
100
  class Weather(BaseModel):
101
  temperature: float
102
  weather: str
103
 
104
 
105
-
106
  @app.post("/user_profile")
107
  def save_user_profile(user_profile: UserProfile):
108
  with open('user_profile.json', 'w') as f:
109
  json.dump(user_profile.dict(), f)
110
  return user_profile.dict()
111
 
 
112
  @app.get("/user_profile")
113
  def load_user_profile():
114
  with open('user_profile.json', 'r') as f:
115
  user_profile = json.load(f)
116
  return UserProfile(**user_profile)
117
 
 
118
  @app.put("/user_profile")
119
  def update_user_profile(user_profile: UserProfile):
120
  with open('user_profile.json', 'w') as f:
@@ -122,7 +119,6 @@ def update_user_profile(user_profile: UserProfile):
122
  return user_profile
123
 
124
 
125
-
126
  @app.get("/weather")
127
  def load_weather():
128
  with open('Weather.json', 'r') as f:
@@ -130,17 +126,22 @@ def load_weather():
130
  return Weather(**w)
131
 
132
  # Load user location
 
 
133
  def load_user_location():
134
  with open('user_location.json', 'r') as f:
135
  user_location = json.load(f)
136
  return UserLocation(**user_location)
137
 
138
  # Save weather information
 
 
139
  def save_weather(weather: Weather):
140
 
141
  with open('Weather.json', 'w') as f:
142
  json.dump(weather.dict(), f)
143
 
 
144
  @app.post("/user_location")
145
  async def set_user_location(user_location: UserLocation):
146
  # Save the user location as a JSON file
@@ -152,7 +153,8 @@ async def set_user_location(user_location: UserLocation):
152
 
153
  # load user profile on startup
154
  user_profile = load_user_profile()
155
- weather=load_weather()
 
156
 
157
  @app.get("/", response_class=HTMLResponse)
158
  async def enter_location():
@@ -182,32 +184,37 @@ async def enter_location():
182
  </script>
183
  """
184
  # Home page : using the user profile, display the weather and chat with Mistral AI
 
 
185
  @app.get("/home", response_class=HTMLResponse)
186
  async def home(
187
  request: Request,
188
  user_profile: UserProfile = Depends(load_user_profile),
189
  weather: Weather = Depends(load_weather),
190
  ):
191
-
192
  with open('user_location.json', 'r') as f:
193
  user_location = json.load(f)
194
  # Get weather data for the user location
195
  weather_data, lat, lon = get_weather(user_location['city'], today)
196
  # Convert the keys to datetime objects
197
- weather_times = {datetime.strptime(time, '%Y-%m-%d %H:%M:%S'): info for time, info in weather_data.items()}
 
198
  # Find the time closest to the current time
199
  current_time = datetime.now()
200
- closest_time = min(weather_times.keys(), key=lambda time: abs(time - current_time))
 
201
  # Extract weather information for the closest time
202
  weather_info = weather_times[closest_time]
203
  # Extract temperature and weather from the weather information
204
- temperature = float(weather_info.split(', ')[1].split('°C')[0].split(': ')[1])
 
205
  weather = weather_info.split(', ')[2].split(': ')[1]
206
  # Create a Weather object from the weather data
207
  weather = Weather(temperature=temperature, weather=weather)
208
  temperature = weather.temperature
209
  weather = weather.weather
210
-
211
  # create the map
212
  fig = create_world_map(lat, lon)
213
  # save the map as a file
@@ -216,65 +223,14 @@ async def home(
216
  # display the map
217
  map_html = f'<iframe src="/static/map.html" width="100%" height="100%" ></iframe>'
218
 
219
-
220
  return templates.TemplateResponse("layout.html", {"request": request, "user_profile": user_profile, "weather": weather, "map_html": map_html})
221
 
222
- return f"""
223
- <html>
224
- <head>
225
- <title>{title}</title>
226
- </head>
227
- <body>
228
-
229
- <div id="leftMenu" class="side-menu">
230
- <ul id="Profile">
231
- <li>Name: {user_profile.name}</li>
232
- <li>Age: {user_profile.age}</li>
233
- <li>Location: {user_profile.location}</li>
234
- </ul>
235
- <button id="toggleMenu">Toggle Menu</button>
236
- </div>
237
-
238
- <div id="rightProfile" class="side-menu">
239
- <div id="menu">
240
- <h1>{title}</h1>
241
- <p>{description}</p>
242
- <input type="text" id="user_input" placeholder="{placeholder}">
243
- <button onclick="sendChat()">Send</button>
244
- <ul id="chat"></ul>
245
- </div>
246
- <button id="toggleProfile">Toggle Profile</button>
247
- </div>
248
-
249
- <div id="map">
250
- {map_html}
251
- </div>
252
-
253
- <script>
254
- function sendChat() {{
255
- var user_input = document.getElementById("user_input").value;
256
- var chat = document.getElementById("chat");
257
- var user_message = document.createElement("li");
258
- user_message.appendChild(document.createTextNode(user_input));
259
- chat.appendChild(user_message);
260
- document.getElementById("user_input").value = "";
261
- fetch('/chat', {{
262
- method: 'POST',
263
- headers: {{
264
- 'Content-Type': 'application/json',
265
- }},
266
- body: JSON.stringify({{
267
- user_input: user_input
268
- }}),
269
- }})
270
- .then(response => response.json())
271
- .then(data => {{
272
- var mistral_message = document.createElement("li");
273
- mistral_message.appendChild(document.createTextNode(data.mistral_response));
274
- chat.appendChild(mistral_message);
275
- }});
276
- }}
277
- </script>
278
- </body>
279
- </html>
280
- """
 
1
+ import json
2
  import os
3
+ from datetime import date, datetime
 
4
  from pathlib import Path
5
+
6
  import plotly.graph_objects as go
 
7
  from dotenv import load_dotenv
8
+ from fastapi import Depends, FastAPI, Request
9
+ from fastapi.responses import HTMLResponse, Response
10
  from fastapi.staticfiles import StaticFiles
11
+ from fastapi.templating import Jinja2Templates
12
  from mistralai.client import ChatMessage, MistralClient
13
  from pydantic import BaseModel
 
 
 
 
 
14
 
15
+ from weather import get_weather
16
 
17
  # code that gives the date of today
18
  today = date.today()
 
46
  templates = Jinja2Templates(directory="static")
47
 
48
 
 
 
49
  def create_world_map(lat, lon):
50
 
51
  fig = go.Figure(go.Scattermapbox(
 
80
  return chat_response.choices[0].message.content
81
 
82
 
 
 
83
  # Profile stuff
84
  class UserProfile(BaseModel):
85
  name: str
 
88
  lat: float
89
  lon: float
90
 
91
+
92
  class UserLocation(BaseModel):
93
  city: str
94
 
95
+
96
  class Weather(BaseModel):
97
  temperature: float
98
  weather: str
99
 
100
 
 
101
  @app.post("/user_profile")
102
  def save_user_profile(user_profile: UserProfile):
103
  with open('user_profile.json', 'w') as f:
104
  json.dump(user_profile.dict(), f)
105
  return user_profile.dict()
106
 
107
+
108
  @app.get("/user_profile")
109
  def load_user_profile():
110
  with open('user_profile.json', 'r') as f:
111
  user_profile = json.load(f)
112
  return UserProfile(**user_profile)
113
 
114
+
115
  @app.put("/user_profile")
116
  def update_user_profile(user_profile: UserProfile):
117
  with open('user_profile.json', 'w') as f:
 
119
  return user_profile
120
 
121
 
 
122
  @app.get("/weather")
123
  def load_weather():
124
  with open('Weather.json', 'r') as f:
 
126
  return Weather(**w)
127
 
128
  # Load user location
129
+
130
+
131
  def load_user_location():
132
  with open('user_location.json', 'r') as f:
133
  user_location = json.load(f)
134
  return UserLocation(**user_location)
135
 
136
  # Save weather information
137
+
138
+
139
  def save_weather(weather: Weather):
140
 
141
  with open('Weather.json', 'w') as f:
142
  json.dump(weather.dict(), f)
143
 
144
+
145
  @app.post("/user_location")
146
  async def set_user_location(user_location: UserLocation):
147
  # Save the user location as a JSON file
 
153
 
154
  # load user profile on startup
155
  user_profile = load_user_profile()
156
+ weather = load_weather()
157
+
158
 
159
  @app.get("/", response_class=HTMLResponse)
160
  async def enter_location():
 
184
  </script>
185
  """
186
  # Home page : using the user profile, display the weather and chat with Mistral AI
187
+
188
+
189
  @app.get("/home", response_class=HTMLResponse)
190
  async def home(
191
  request: Request,
192
  user_profile: UserProfile = Depends(load_user_profile),
193
  weather: Weather = Depends(load_weather),
194
  ):
195
+
196
  with open('user_location.json', 'r') as f:
197
  user_location = json.load(f)
198
  # Get weather data for the user location
199
  weather_data, lat, lon = get_weather(user_location['city'], today)
200
  # Convert the keys to datetime objects
201
+ weather_times = {datetime.strptime(
202
+ time, '%Y-%m-%d %H:%M:%S'): info for time, info in weather_data.items()}
203
  # Find the time closest to the current time
204
  current_time = datetime.now()
205
+ closest_time = min(weather_times.keys(),
206
+ key=lambda time: abs(time - current_time))
207
  # Extract weather information for the closest time
208
  weather_info = weather_times[closest_time]
209
  # Extract temperature and weather from the weather information
210
+ temperature = float(weather_info.split(
211
+ ', ')[1].split('°C')[0].split(': ')[1])
212
  weather = weather_info.split(', ')[2].split(': ')[1]
213
  # Create a Weather object from the weather data
214
  weather = Weather(temperature=temperature, weather=weather)
215
  temperature = weather.temperature
216
  weather = weather.weather
217
+
218
  # create the map
219
  fig = create_world_map(lat, lon)
220
  # save the map as a file
 
223
  # display the map
224
  map_html = f'<iframe src="/static/map.html" width="100%" height="100%" ></iframe>'
225
 
 
226
  return templates.TemplateResponse("layout.html", {"request": request, "user_profile": user_profile, "weather": weather, "map_html": map_html})
227
 
228
+
229
+ class ChatInput(BaseModel):
230
+ user_input: str
231
+
232
+
233
+ @app.post("/chat")
234
+ async def chat(chat_input: ChatInput):
235
+ print(chat_input.user_input)
236
+ return chat_with_mistral(chat_input.user_input)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
static/layout.html CHANGED
@@ -1,31 +1,34 @@
1
  <!DOCTYPE html>
2
  <html>
3
- <head>
4
  <title>FastAPI Home</title>
5
- <link rel="stylesheet" href="/static/style.css">
6
- </head>
7
- <body>
 
8
  <div id="leftMenu" class="side-menu">
9
- <ul id="Profile">
10
- <li>Name: {{ user_profile.name }}</li>
11
- <li>Age: {{ user_profile.age }}</li>
12
- <li>Location: {{ user_profile.location }}</li>
13
- </ul>
14
- <button id="toggleMenu">Toggle Menu</button>
15
  </div>
16
 
17
  <div id="mainContent">
18
- <!-- Main content here -->
19
- <div id="map">
20
- {{ map_html | safe }}
21
- </div>
22
  </div>
23
 
24
  <div id="rightProfile" class="side-menu">
25
- <!-- Profile content here -->
26
- <button id="toggleProfile">Toggle Profile</button>
 
 
 
 
 
27
  </div>
28
 
29
  <script src="/static/script.js"></script>
30
- </body>
31
- </html>
 
1
  <!DOCTYPE html>
2
  <html>
3
+ <head>
4
  <title>FastAPI Home</title>
5
+ <link rel="stylesheet" href="/static/style.css" />
6
+ </head>
7
+ <body>
8
+ <h1>FastAPI Home</h1>
9
  <div id="leftMenu" class="side-menu">
10
+ <ul id="Profile">
11
+ <li>Name: {{ user_profile.name }}</li>
12
+ <li>Age: {{ user_profile.age }}</li>
13
+ <li>Location: {{ user_profile.location }}</li>
14
+ </ul>
15
+ <button id="toggleMenu">Toggle Menu</button>
16
  </div>
17
 
18
  <div id="mainContent">
19
+ <div id="map" class="map">{{ map_html | safe }}</div>
 
 
 
20
  </div>
21
 
22
  <div id="rightProfile" class="side-menu">
23
+ <button id="toggleProfile">Toggle Profile</button>
24
+
25
+ <div id="chat">
26
+ <input type="text" id="user_input" placeholder="Enter your message" />
27
+ <button onclick="sendChat()">Send</button>
28
+ <ul id="chat_messages"></ul>
29
+ </div>
30
  </div>
31
 
32
  <script src="/static/script.js"></script>
33
+ </body>
34
+ </html>
static/script.js CHANGED
@@ -6,4 +6,28 @@ document.getElementById('toggleMenu').addEventListener('click', function () {
6
  document.getElementById('toggleProfile').addEventListener('click', function () {
7
  var profile = document.getElementById('rightProfile');
8
  profile.classList.toggle('hidden');
9
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  document.getElementById('toggleProfile').addEventListener('click', function () {
7
  var profile = document.getElementById('rightProfile');
8
  profile.classList.toggle('hidden');
9
+ });
10
+
11
+ function sendChat() {
12
+ var user_input = document.getElementById("user_input").value;
13
+ var chat_messages = document.getElementById("chat_messages");
14
+ var user_message = document.createElement("li");
15
+ user_message.appendChild(document.createTextNode(user_input));
16
+ chat_messages.appendChild(user_message);
17
+ document.getElementById("user_input").value = "";
18
+ fetch('/chat', {
19
+ method: 'POST',
20
+ headers: {
21
+ 'Content-Type': 'application/json',
22
+ },
23
+ body: JSON.stringify({
24
+ user_input: user_input
25
+ }),
26
+ })
27
+ .then(response => response.text())
28
+ .then(data => {
29
+ var mistral_message = document.createElement("li");
30
+ mistral_message.appendChild(document.createTextNode(data));
31
+ chat_messages.appendChild(mistral_message);
32
+ });
33
+ }
static/style.css CHANGED
@@ -1,19 +1,30 @@
1
  .side-menu {
2
- width: 200px; /* Fixed width */
3
- position: fixed;
4
- top: 0;
5
- overflow: auto;
6
- height: 100%;
7
- }
8
-
9
- #leftMenu {
10
- left: 0;
11
- }
12
-
13
- #rightProfile {
14
- right: 0;
15
- }
16
-
17
- .hidden {
18
- display: none;
19
- }
 
 
 
 
 
 
 
 
 
 
 
 
1
  .side-menu {
2
+ width: 200px;
3
+ /* Fixed width */
4
+ position: fixed;
5
+ top: 0;
6
+ overflow: auto;
7
+ height: 100%;
8
+ }
9
+
10
+ #leftMenu {
11
+ left: 0;
12
+ }
13
+
14
+ #rightProfile {
15
+ right: 0;
16
+ }
17
+
18
+ .hidden {
19
+ display: none;
20
+ }
21
+
22
+ .map {
23
+ /* show full screen the iframe */
24
+ position: fixed;
25
+ top: 0;
26
+ left: 0;
27
+ width: 100%;
28
+ height: 100%;
29
+ z-index: -1;
30
+ }