refactor(easel): add weather routes

This commit is contained in:
2024-08-11 21:14:01 +03:00
parent 72fd378c40
commit 6db33ca669
13 changed files with 101 additions and 97 deletions

View File

@@ -4,18 +4,20 @@ from fastapi import FastAPI
from gallery.sketch.weather.api import WeatherApi from gallery.sketch.weather.api import WeatherApi
from .route import api, doc, view from .route import doc
from .route.api import weather as weather_api_route
from .route.view import weather as weather_view_route
def build_app(weather_api: WeatherApi) -> FastAPI: def build_app(weather_api: WeatherApi) -> FastAPI:
locale.setlocale(locale.LC_TIME, "ru_RU.UTF-8") locale.setlocale(locale.LC_TIME, "ru_RU.UTF-8")
app = FastAPI( app = FastAPI(
title="Weather", title="Gallery",
docs_url=None, docs_url=None,
redoc_url=None, redoc_url=None,
) )
app.state.weather_api = weather_api app.state.weather_api = weather_api
doc.mount(app) doc.mount(app)
api.mount(app) weather_api_route.mount(app)
view.mount(app) weather_view_route.mount(app)
return app return app

View File

@@ -7,6 +7,11 @@ from gallery.sketch.weather.model import WeatherResponse
def mount(app: FastAPI): def mount(app: FastAPI):
@app.get("/api/weather/locations")
async def get_api_weather_locations(request: Request) -> list[str]:
weather_api: WeatherApi = request.app.state.weather_api
return await weather_api.get_locations()
@app.get("/api/weather/{location}/day/{date}") @app.get("/api/weather/{location}/day/{date}")
async def get_api_weather_day( async def get_api_weather_day(
request: Request, location: str, date: datetime.date request: Request, location: str, date: datetime.date

View File

@@ -1,87 +0,0 @@
import datetime
from pathlib import Path
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from gallery.sketch.weather.api import WeatherApi
from gallery.sketch.weather.mock import WEATHER_MOCK_DATA
from gallery.sketch.weather.model import WeatherResponse
from ..util import TagType, TagUtil
from .filters import cloudness_icon, wind_direction_icon
def mount(app: FastAPI):
base_dir = Path(__file__).parent
app.mount("/static", StaticFiles(directory=base_dir / "static"), name="static")
templates = Jinja2Templates(directory=base_dir / "templates")
templates.env.filters["wind_direction_icon"] = wind_direction_icon
templates.env.filters["cloudness_icon"] = cloudness_icon
def build_weather_response(request: Request, response: WeatherResponse):
return templates.TemplateResponse(
request=request,
name="weather.html",
context={
"tag_util": TagUtil,
"datetime": datetime,
"response": response,
},
)
@app.get("/", response_class=RedirectResponse)
async def get_weather_root():
return RedirectResponse("weather")
@app.get("/weather", response_class=HTMLResponse)
async def get_weather_list(request: Request):
weather_api: WeatherApi = request.app.state.weather_api
locations = await weather_api.get_locations()
return templates.TemplateResponse(
request=request,
name="index.html",
context={
"locations": locations,
},
)
@app.get("/weather/{location}", response_class=RedirectResponse)
async def get_weather_default(location: str):
return RedirectResponse(f"{location}/tag/today")
@app.get("/weather/{location}/day/mock", response_class=HTMLResponse)
async def get_weather_day_mock(request: Request):
response = WEATHER_MOCK_DATA.get_response("day")
return build_weather_response(request, response)
@app.get("/weather/{location}/days/mock", response_class=HTMLResponse)
async def get_weather_days_mock(request: Request):
response = WEATHER_MOCK_DATA.get_response("days")
return build_weather_response(request, response)
@app.get("/weather/{location}/day/{date}", response_class=HTMLResponse)
async def get_weather_day(request: Request, location: str, date: datetime.date):
weather_api: WeatherApi = request.app.state.weather_api
response = await weather_api.get_day(location, date)
return build_weather_response(request, response)
@app.get("/weather/{location}/days/{days}", response_class=HTMLResponse)
async def get_weather_days(request: Request, location: str, days: int):
weather_api: WeatherApi = request.app.state.weather_api
response = await weather_api.get_days(location, days)
return build_weather_response(request, response)
@app.get("/weather/{location}/tag/{tag}", response_class=HTMLResponse)
async def get_weather_tag(request: Request, location: str, tag: str):
tag_value = TagUtil.parse_tag(tag)
weather_api: WeatherApi = request.app.state.weather_api
if tag_value.type == TagType.DAY:
response = await weather_api.get_day(location, tag_value.date)
elif tag_value.type == TagType.DAYS:
response = await weather_api.get_days(location, tag_value.days)
else:
raise ValueError(tag)
return build_weather_response(request, response)

View File

@@ -0,0 +1,85 @@
import datetime
from pathlib import Path
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from gallery.sketch.weather.api import WeatherApi
from gallery.sketch.weather.mock import WEATHER_MOCK_DATA
from gallery.sketch.weather.model import WeatherResponse
from .filters import cloudness_icon, wind_direction_icon
from .util import TagType, TagUtil
def mount(app: FastAPI):
base_dir = Path(__file__).parent
app.mount(
"/weather/static", StaticFiles(directory=base_dir / "static"), name="static"
)
templates = Jinja2Templates(directory=base_dir / "templates")
templates.env.filters["wind_direction_icon"] = wind_direction_icon
templates.env.filters["cloudness_icon"] = cloudness_icon
def build_weather_response(request: Request, response: WeatherResponse):
return templates.TemplateResponse(
request=request,
name="weather.html",
context={
"tag_util": TagUtil,
"datetime": datetime,
"response": response,
},
)
@app.get("/weather", response_class=HTMLResponse)
async def get_weather_list(request: Request):
weather_api: WeatherApi = request.app.state.weather_api
locations = await weather_api.get_locations()
return templates.TemplateResponse(
request=request,
name="index.html",
context={
"locations": locations,
},
)
@app.get("/weather/{location}", response_class=RedirectResponse)
async def get_weather_default(location: str):
return RedirectResponse(f"{location}/tag/today")
@app.get("/weather/{location}/day/mock", response_class=HTMLResponse)
async def get_weather_day_mock(request: Request):
response = WEATHER_MOCK_DATA.get_response("day")
return build_weather_response(request, response)
@app.get("/weather/{location}/days/mock", response_class=HTMLResponse)
async def get_weather_days_mock(request: Request):
response = WEATHER_MOCK_DATA.get_response("days")
return build_weather_response(request, response)
@app.get("/weather/{location}/day/{date}", response_class=HTMLResponse)
async def get_weather_day(request: Request, location: str, date: datetime.date):
weather_api: WeatherApi = request.app.state.weather_api
response = await weather_api.get_day(location, date)
return build_weather_response(request, response)
@app.get("/weather/{location}/days/{days}", response_class=HTMLResponse)
async def get_weather_days(request: Request, location: str, days: int):
weather_api: WeatherApi = request.app.state.weather_api
response = await weather_api.get_days(location, days)
return build_weather_response(request, response)
@app.get("/weather/{location}/tag/{tag}", response_class=HTMLResponse)
async def get_weather_tag(request: Request, location: str, tag: str):
tag_value = TagUtil.parse_tag(tag)
weather_api: WeatherApi = request.app.state.weather_api
if tag_value.type == TagType.DAY:
response = await weather_api.get_day(location, tag_value.date)
elif tag_value.type == TagType.DAYS:
response = await weather_api.get_days(location, tag_value.days)
else:
raise ValueError(tag)
return build_weather_response(request, response)

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -9,9 +9,9 @@
content="ie=edge"> content="ie=edge">
<title>Погода</title> <title>Погода</title>
<link rel="stylesheet" <link rel="stylesheet"
href="/static/style.css?v=1"> href="/weather/static/style.css?v=1">
<link rel="icon" <link rel="icon"
href="/static/favicon.ico" href="/weather/static/favicon.ico"
type="image/x-icon"> type="image/x-icon">
</head> </head>

View File

@@ -9,9 +9,9 @@
content="ie=edge"> content="ie=edge">
<title>Погода | {{response.location}} | {{response.date.strftime('%a, %d %B %Y')}}</title> <title>Погода | {{response.location}} | {{response.date.strftime('%a, %d %B %Y')}}</title>
<link rel="stylesheet" <link rel="stylesheet"
href="/static/style.css?v=1"> href="/weather/static/style.css?v=1">
<link rel="icon" <link rel="icon"
href="/static/favicon.ico" href="/weather/static/favicon.ico"
type="image/x-icon"> type="image/x-icon">
</head> </head>

View File

@@ -1,5 +1,4 @@
import json import json
from pathlib import Path
class MockData: class MockData:
@@ -11,5 +10,5 @@ class MockData:
return (self._data_dir / f"{key}.html").read_text() return (self._data_dir / f"{key}.html").read_text()
def get_json(self, key: str) -> dict: def get_json(self, key: str) -> dict:
data = json.loads((Path(__file__).parent / f"data/{key}.json").read_text()) data = json.loads((self._data_dir / f"{key}.json").read_text())
return data return data