feat(easel): add api provider

This commit is contained in:
2026-06-17 21:15:01 +03:00
parent 657a62eab5
commit e37ca6eeac
12 changed files with 124 additions and 53 deletions

View File

@@ -1,22 +1,39 @@
import datetime
from pathlib import Path
from typing import Annotated
from fastapi import APIRouter
from fastapi import APIRouter, Depends
from fastapi.responses import HTMLResponse, RedirectResponse
from gallery.easel.core import AppRequest
from gallery.sketch.weather.api import WeatherApi
from gallery.sketch.weather.model import WeatherResponse
from ..common.utils.tag import TagType, TagUtil
from ..common.utils.template import build_templates
from .filters import cloudness_icon, wind_direction_icon
async def get_weather_api(request: AppRequest, provider: str | None = None) -> WeatherApi:
return request.app.state.api.get_weather(provider)
WeatherApiDepends = Annotated[WeatherApi, Depends(get_weather_api)]
def context_procesor(request: AppRequest) -> dict:
return {
"providers": request.app.state.api.get_api_providers(WeatherApi.TYPE),
}
templates = build_templates(
Path(__file__).parent / "templates",
{
"wind_direction_icon": wind_direction_icon,
"cloudness_icon": cloudness_icon,
},
context_procesor,
)
@@ -30,12 +47,11 @@ def build_weather_response(request: AppRequest, response: WeatherResponse):
)
router = APIRouter()
router = APIRouter(prefix="/weather")
@router.get("/weather", response_class=HTMLResponse)
async def get_weather_index(request: AppRequest, query: str | None = None):
weather_api = request.app.state.api.weather
@router.get("/", response_class=HTMLResponse)
async def get_weather_index(request: AppRequest, weather_api: WeatherApiDepends, query: str | None = None):
locations = (await weather_api.find_locations(query)) if query else []
return templates.TemplateResponse(
request=request,
@@ -46,29 +62,31 @@ async def get_weather_index(request: AppRequest, query: str | None = None):
)
@router.get("/weather/{location}", response_class=RedirectResponse)
@router.get("/{location}", response_class=RedirectResponse)
async def get_weather_default(location: str):
return RedirectResponse(f"{location}/tag/today")
@router.get("/weather/{location}/day/{date}", response_class=HTMLResponse)
async def get_weather_day(request: AppRequest, location: str, date: datetime.date):
weather_api = request.app.state.api.weather
@router.get("/{location}/day/{date}", response_class=HTMLResponse)
async def get_weather_day(
request: AppRequest,
weather_api: WeatherApiDepends,
location: str,
date: datetime.date,
):
response = await weather_api.get_day(location, date)
return build_weather_response(request, response)
@router.get("/weather/{location}/days/{days}", response_class=HTMLResponse)
async def get_weather_days(request: AppRequest, location: str, days: int):
weather_api = request.app.state.api.weather
@router.get("/{location}/days/{days}", response_class=HTMLResponse)
async def get_weather_days(request: AppRequest, weather_api: WeatherApiDepends, location: str, days: int):
response = await weather_api.get_days(location, days)
return build_weather_response(request, response)
@router.get("/weather/{location}/tag/{tag}", response_class=HTMLResponse)
async def get_weather_tag(request: AppRequest, location: str, tag: str):
@router.get("/{location}/tag/{tag}", response_class=HTMLResponse)
async def get_weather_tag(request: AppRequest, weather_api: WeatherApiDepends, location: str, tag: str):
tag_value = TagUtil.parse_tag(tag)
weather_api = request.app.state.api.weather
if tag_value.type == TagType.DAY:
response = await weather_api.get_day(location, tag_value.date)
elif tag_value.type == TagType.DAYS:

View File

@@ -1,6 +1,23 @@
{% extends "base.html" %}
{% block title %}{{_("Weather")}}{% endblock %}
{# {% block header %}
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle"
type="button"
data-bs-toggle="dropdown"
aria-expanded="false">
{{provider or providers[0]}}
</button>
<ul class="dropdown-menu">
{% for provider in providers %}
<li><a class="dropdown-item"
href="{{ url_for('get_weather_index').include_query_params(provider=provider) }}">{{provider}}</a></li>
{% endfor %}
</ul>
</div>
{% endblock %} #}
{% block content %}
<h1>{{_("Weather")}}</h1>
<form action=""
@@ -19,7 +36,7 @@
<ul id="locations"
class="list-group mb-5">
{% for location in locations %}
<a href="weather/{{location.id}}"
<a href="{{location.id}}"
class="list-group-item list-group-item-action px-4"
onclick="saveLocation({id:'{{location.id}}', name:'{{location.name}}'});">
<span class="fi fi-{{location.country_code}} me-1"></span>
@@ -39,7 +56,7 @@
container.innerHTML = '';
for (const [id, name] of Object.entries(locations)) {
const element = document.createElement('a');
element.href = `weather/${id}`;
element.href = `${id}`;
element.className = 'list-group-item list-group-item-action px-4 d-flex justify-content-between align-items-start';
element.innerHTML = `
<span class="text-primary me-auto">${name}</span>