diff --git a/gallery/easel/__init__.py b/gallery/easel/__init__.py index 28e5faf..5348817 100644 --- a/gallery/easel/__init__.py +++ b/gallery/easel/__init__.py @@ -4,18 +4,20 @@ from fastapi import FastAPI 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: locale.setlocale(locale.LC_TIME, "ru_RU.UTF-8") app = FastAPI( - title="Weather", + title="Gallery", docs_url=None, redoc_url=None, ) app.state.weather_api = weather_api doc.mount(app) - api.mount(app) - view.mount(app) + weather_api_route.mount(app) + weather_view_route.mount(app) return app diff --git a/gallery/easel/route/view/static/index.js b/gallery/easel/route/api/__init__.py similarity index 100% rename from gallery/easel/route/view/static/index.js rename to gallery/easel/route/api/__init__.py diff --git a/gallery/easel/route/api.py b/gallery/easel/route/api/weather.py similarity index 77% rename from gallery/easel/route/api.py rename to gallery/easel/route/api/weather.py index b241cda..583af94 100644 --- a/gallery/easel/route/api.py +++ b/gallery/easel/route/api/weather.py @@ -7,6 +7,11 @@ from gallery.sketch.weather.model import WeatherResponse 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}") async def get_api_weather_day( request: Request, location: str, date: datetime.date diff --git a/gallery/easel/route/view/__init__.py b/gallery/easel/route/view/__init__.py index 6d5b117..e69de29 100644 --- a/gallery/easel/route/view/__init__.py +++ b/gallery/easel/route/view/__init__.py @@ -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) diff --git a/gallery/easel/route/view/weather/__init__.py b/gallery/easel/route/view/weather/__init__.py new file mode 100644 index 0000000..1b7252c --- /dev/null +++ b/gallery/easel/route/view/weather/__init__.py @@ -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) diff --git a/gallery/easel/route/view/filters.py b/gallery/easel/route/view/weather/filters.py similarity index 100% rename from gallery/easel/route/view/filters.py rename to gallery/easel/route/view/weather/filters.py diff --git a/gallery/easel/route/view/static/favicon.ico b/gallery/easel/route/view/weather/static/favicon.ico similarity index 100% rename from gallery/easel/route/view/static/favicon.ico rename to gallery/easel/route/view/weather/static/favicon.ico diff --git a/gallery/easel/route/view/weather/static/index.js b/gallery/easel/route/view/weather/static/index.js new file mode 100644 index 0000000..e69de29 diff --git a/gallery/easel/route/view/static/style.css b/gallery/easel/route/view/weather/static/style.css similarity index 100% rename from gallery/easel/route/view/static/style.css rename to gallery/easel/route/view/weather/static/style.css diff --git a/gallery/easel/route/view/templates/index.html b/gallery/easel/route/view/weather/templates/index.html similarity index 85% rename from gallery/easel/route/view/templates/index.html rename to gallery/easel/route/view/weather/templates/index.html index ef84ef0..87b6138 100644 --- a/gallery/easel/route/view/templates/index.html +++ b/gallery/easel/route/view/weather/templates/index.html @@ -9,9 +9,9 @@ content="ie=edge">