feat(easel): add localization
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import datetime
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi import APIRouter, FastAPI
|
||||
from fastapi.responses import HTMLResponse, RedirectResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.templating import Jinja2Templates
|
||||
@@ -11,70 +11,77 @@ from gallery.sketch.weather.model import WeatherResponse
|
||||
from gallery.version import __version__
|
||||
|
||||
from ..common.util import TagType, TagUtil
|
||||
from ..translation import _
|
||||
from .filters import cloudness_icon, wind_direction_icon
|
||||
|
||||
|
||||
def mount(app: FastAPI):
|
||||
base_dir = Path(__file__).parent
|
||||
app.mount("/static/weather", StaticFiles(directory=base_dir / "static"))
|
||||
templates = Jinja2Templates(
|
||||
directory=[
|
||||
base_dir.parent / "common/templates",
|
||||
base_dir / "templates",
|
||||
]
|
||||
base_dir = Path(__file__).parent
|
||||
templates = Jinja2Templates(
|
||||
directory=[
|
||||
base_dir.parent / "common/templates",
|
||||
base_dir / "templates",
|
||||
]
|
||||
)
|
||||
templates.env.globals.update({"_": _})
|
||||
templates.env.filters["wind_direction_icon"] = wind_direction_icon
|
||||
templates.env.filters["cloudness_icon"] = cloudness_icon
|
||||
|
||||
|
||||
def build_weather_response(request: AppRequest, response: WeatherResponse):
|
||||
return templates.TemplateResponse(
|
||||
request=request,
|
||||
name="weather.html",
|
||||
context={
|
||||
"version": __version__,
|
||||
"tag_util": TagUtil,
|
||||
"datetime": datetime,
|
||||
"response": response,
|
||||
},
|
||||
)
|
||||
templates.env.filters["wind_direction_icon"] = wind_direction_icon
|
||||
templates.env.filters["cloudness_icon"] = cloudness_icon
|
||||
|
||||
def build_weather_response(request: AppRequest, response: WeatherResponse):
|
||||
return templates.TemplateResponse(
|
||||
request=request,
|
||||
name="weather.html",
|
||||
context={
|
||||
"version": __version__,
|
||||
"tag_util": TagUtil,
|
||||
"datetime": datetime,
|
||||
"response": response,
|
||||
},
|
||||
)
|
||||
router = APIRouter()
|
||||
|
||||
@app.get("/weather", response_class=HTMLResponse)
|
||||
async def get_weather_index(request: AppRequest, query: str | None = None):
|
||||
weather_api = request.app.state.api.weather
|
||||
locations = (await weather_api.find_locations(query)) if query else []
|
||||
return templates.TemplateResponse(
|
||||
request=request,
|
||||
name="index.html",
|
||||
context={
|
||||
"version": __version__,
|
||||
"locations": locations,
|
||||
},
|
||||
)
|
||||
@router.get("/weather", response_class=HTMLResponse)
|
||||
async def get_weather_index(request: AppRequest, query: str | None = None):
|
||||
weather_api = request.app.state.api.weather
|
||||
locations = (await weather_api.find_locations(query)) if query else []
|
||||
return templates.TemplateResponse(
|
||||
request=request,
|
||||
name="index.html",
|
||||
context={
|
||||
"version": __version__,
|
||||
"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/{date}", response_class=HTMLResponse)
|
||||
async def get_weather_day(request: AppRequest, location: str, date: datetime.date):
|
||||
weather_api = request.app.state.api.weather
|
||||
response = await weather_api.get_day(location, date)
|
||||
return build_weather_response(request, response)
|
||||
@router.get("/weather/{location}", response_class=RedirectResponse)
|
||||
async def get_weather_default(location: str):
|
||||
return RedirectResponse(f"{location}/tag/today")
|
||||
|
||||
@app.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
|
||||
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: AppRequest, 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:
|
||||
response = await weather_api.get_days(location, tag_value.days)
|
||||
else:
|
||||
raise ValueError(tag)
|
||||
return build_weather_response(request, response)
|
||||
@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
|
||||
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
|
||||
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):
|
||||
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:
|
||||
response = await weather_api.get_days(location, tag_value.days)
|
||||
else:
|
||||
raise ValueError(tag)
|
||||
return build_weather_response(request, response)
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB |
@@ -1,71 +0,0 @@
|
||||
.header {
|
||||
font-size: 0.9rem;
|
||||
text-align: left;
|
||||
padding-top: 0.25rem;
|
||||
}
|
||||
|
||||
.date {
|
||||
background: rgba(1, 0, 0, 0.1) !important;
|
||||
}
|
||||
|
||||
.date.now {
|
||||
background: rgba(0, 128, 255, 0.2) !important;
|
||||
}
|
||||
|
||||
.date .value a {
|
||||
all: unset;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cloudness {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.cloudness .icon {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.cloudness .icon:first-child {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.temperature {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.temperature .value {
|
||||
padding: 0.1rem 0.4rem;
|
||||
}
|
||||
|
||||
.temperature .value.positive {
|
||||
color: orangered;
|
||||
}
|
||||
|
||||
.temperature .value.negative {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.wind .direction {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.wind .gust {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.precipitation .value {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.pressure {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.pressure .value {
|
||||
padding: 0.1rem 0.4rem;
|
||||
color: blueviolet;
|
||||
}
|
||||
|
||||
.humidity .value {
|
||||
color: blue;
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 9.5 KiB |
@@ -1,13 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Weather{% endblock %}
|
||||
{% block head %}
|
||||
{{ super() }}
|
||||
<link rel="stylesheet"
|
||||
href="/static/weather/style.css?v={{version}}">
|
||||
<link rel="icon"
|
||||
href="/static/weather/favicon.ico?v={{version}}"
|
||||
type="image/x-icon">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Weather</h1>
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Погода | {{response.location}} | {{response.date.strftime('%a, %d %B %Y')}}{% endblock %}
|
||||
{% block head %}
|
||||
{{ super() }}
|
||||
<link rel="stylesheet"
|
||||
href="/static/weather/style.css?v={{version}}">
|
||||
<link rel="icon"
|
||||
href="/static/weather/favicon.ico?v={{version}}"
|
||||
type="image/x-icon">
|
||||
{% block title %}{{_("Weather")}} | {{response.location}} | {{response.date.strftime('%a, %d %B %Y')}}{% endblock %}
|
||||
|
||||
{% block header %}
|
||||
<span class="fs-4 text-body ms-2 me-2">/</span>
|
||||
<app-link href="/weather" icon="brightness-high">{{_("Weather")}}</app-link>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
@@ -25,7 +22,8 @@
|
||||
{% endif %}
|
||||
</h4>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-borderless table-compact text-center w-auto" style="font-size: 130%;">
|
||||
<table class="table table-weather table-borderless table-compact text-center w-auto"
|
||||
style="font-size: 130%;">
|
||||
<tbody>
|
||||
<!-- date -->
|
||||
<tr>
|
||||
|
||||
Reference in New Issue
Block a user