Clément Simon commited on
Commit
eb89bee
1 Parent(s): c03a978

feat: refactoring HTML/CSS/JS

Browse files
Files changed (5) hide show
  1. app.py +71 -33
  2. static/layout.html +31 -0
  3. static/script.js +9 -0
  4. static/style.css +19 -0
  5. user_location.json +1 -1
app.py CHANGED
@@ -5,7 +5,7 @@ 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
9
  from fastapi.staticfiles import StaticFiles
10
  from mistralai.client import ChatMessage, MistralClient
11
  from pydantic import BaseModel
@@ -13,6 +13,8 @@ import json
13
  from fastapi.responses import HTMLResponse, RedirectResponse, Response
14
  from datetime import date
15
  from weather import get_weather
 
 
16
 
17
  # code that gives the date of today
18
  today = date.today()
@@ -42,9 +44,8 @@ static_dir.mkdir(parents=True, exist_ok=True)
42
  # mount FastAPI StaticFiles server
43
  app.mount("/static", StaticFiles(directory=static_dir), name="static")
44
 
45
-
46
- # Gradio stuff
47
-
48
 
49
 
50
 
@@ -153,16 +154,6 @@ async def set_user_location(user_location: UserLocation):
153
  user_profile = load_user_profile()
154
  weather=load_weather()
155
 
156
- ### BACKEND ###
157
- @app.get("/meteo")
158
- async def read_meteo(location: str, date: str):
159
- # API call to get the weather
160
- pass
161
-
162
-
163
-
164
-
165
-
166
  @app.get("/", response_class=HTMLResponse)
167
  async def enter_location():
168
  return """
@@ -192,8 +183,11 @@ async def enter_location():
192
  """
193
  # Home page : using the user profile, display the weather and chat with Mistral AI
194
  @app.get("/home", response_class=HTMLResponse)
195
- async def home(user_profile: UserProfile = Depends(load_user_profile), weather: Weather = Depends(load_weather)):
196
-
 
 
 
197
 
198
  with open('user_location.json', 'r') as f:
199
  user_location = json.load(f)
@@ -220,23 +214,67 @@ async def home(user_profile: UserProfile = Depends(load_user_profile), weather:
220
  map_file = static_dir / "map.html"
221
  fig.write_html(str(map_file))
222
  # display the map
223
- map_html = f'<iframe src="/static/map.html" width="100%" height="500px"></iframe>'
224
-
225
-
 
 
226
  return f"""
227
- <center>
228
- <h1>Bienvenue !</h1></center>
229
- <div style="display: flex;">
230
- <div style="flex: 50%;">
231
- <h2>Informations du jour</h2>
232
- <p>temperature: {temperature}</p>
233
- <p>weather: {weather}</p>
234
- <h2>Map</h2>
235
- {map_html}
236
- </div>
237
- <div style="flex: 50%;">
238
- <h2>Avez-vous une question ?</h2>
239
- <textarea style="width: 100%; height: 500px;"></textarea>
 
 
 
 
 
 
 
 
 
240
  </div>
 
 
 
 
 
241
  </div>
242
- """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
 
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()
 
44
  # mount FastAPI StaticFiles server
45
  app.mount("/static", StaticFiles(directory=static_dir), name="static")
46
 
47
+ # templating
48
+ templates = Jinja2Templates(directory="static")
 
49
 
50
 
51
 
 
154
  user_profile = load_user_profile()
155
  weather=load_weather()
156
 
 
 
 
 
 
 
 
 
 
 
157
  @app.get("/", response_class=HTMLResponse)
158
  async def enter_location():
159
  return """
 
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)
 
214
  map_file = static_dir / "map.html"
215
  fig.write_html(str(map_file))
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
+ """
static/layout.html ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>
static/script.js ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ document.getElementById('toggleMenu').addEventListener('click', function () {
2
+ var menu = document.getElementById('leftMenu');
3
+ menu.classList.toggle('hidden');
4
+ });
5
+
6
+ document.getElementById('toggleProfile').addEventListener('click', function () {
7
+ var profile = document.getElementById('rightProfile');
8
+ profile.classList.toggle('hidden');
9
+ });
static/style.css ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ }
user_location.json CHANGED
@@ -1 +1 @@
1
- {"city": "Gif-sur-Yvette"}
 
1
+ {"city": "Clamart"}