Compare commits
1 Commits
0.3.4
...
a715bcca89
| Author | SHA1 | Date | |
|---|---|---|---|
| a715bcca89 |
@@ -7,9 +7,7 @@ WORKDIR /app
|
|||||||
RUN curl -sSL https://install.python-poetry.org | python3 -
|
RUN curl -sSL https://install.python-poetry.org | python3 -
|
||||||
COPY pyproject.toml poetry.lock README.md ./
|
COPY pyproject.toml poetry.lock README.md ./
|
||||||
RUN poetry config virtualenvs.in-project true
|
RUN poetry config virtualenvs.in-project true
|
||||||
RUN --mount=type=cache,target=/root/.cache/pypoetry/cache \
|
RUN poetry install --with app --no-root
|
||||||
--mount=type=cache,target=/root/.cache/pypoetry/artifacts \
|
|
||||||
poetry install --with app --no-root
|
|
||||||
COPY locales ./locales
|
COPY locales ./locales
|
||||||
RUN cd locales/ru/LC_MESSAGES && msgfmt messages.po
|
RUN cd locales/ru/LC_MESSAGES && msgfmt messages.po
|
||||||
|
|
||||||
@@ -17,8 +15,7 @@ FROM node:24 AS node-builder
|
|||||||
ENV PATH=/app/node_modules/.bin:$PATH
|
ENV PATH=/app/node_modules/.bin:$PATH
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY static/package.json static/package-lock.json ./
|
COPY static/package.json static/package-lock.json ./
|
||||||
RUN --mount=type=cache,target=/root/.npm \
|
RUN npm ci
|
||||||
npm ci
|
|
||||||
COPY static ./
|
COPY static ./
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
@@ -30,6 +27,7 @@ ENV TZ="Europe/Moscow"
|
|||||||
COPY --from=builder /app ./
|
COPY --from=builder /app ./
|
||||||
COPY --from=node-builder /app/dist ./static/dist
|
COPY --from=node-builder /app/dist ./static/dist
|
||||||
COPY gallery gallery/
|
COPY gallery gallery/
|
||||||
|
#COPY --from=builder /app/gallery/easel/route/view/locales /app/gallery/easel/route/view/locales
|
||||||
COPY --from=builder --parents locales/**/*.mo ./
|
COPY --from=builder --parents locales/**/*.mo ./
|
||||||
|
|
||||||
CMD ["uvicorn", "gallery.main:app", "--host", "0.0.0.0", "--port", "80", "--log-config", "gallery/logging.yaml"]
|
CMD ["uvicorn", "gallery.main:app", "--host", "0.0.0.0", "--port", "80", "--log-config", "gallery/logging.yaml"]
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 182 KiB After Width: | Height: | Size: 237 KiB |
@@ -4,7 +4,8 @@ from fastapi.staticfiles import StaticFiles
|
|||||||
from gallery.sketch.bundle import ApiBundle
|
from gallery.sketch.bundle import ApiBundle
|
||||||
from gallery.util import root_path
|
from gallery.util import root_path
|
||||||
|
|
||||||
from .route import api, doc, view
|
from .route import api, doc
|
||||||
|
from .route.view import router as view_router
|
||||||
|
|
||||||
|
|
||||||
def build_app(api_bundle: ApiBundle) -> FastAPI:
|
def build_app(api_bundle: ApiBundle) -> FastAPI:
|
||||||
@@ -16,6 +17,6 @@ def build_app(api_bundle: ApiBundle) -> FastAPI:
|
|||||||
app.state.api = api_bundle
|
app.state.api = api_bundle
|
||||||
app.mount("/static", StaticFiles(directory=root_path / "static/dist"))
|
app.mount("/static", StaticFiles(directory=root_path / "static/dist"))
|
||||||
doc.mount(app)
|
doc.mount(app)
|
||||||
app.include_router(api.router)
|
api.mount(app)
|
||||||
app.include_router(view.router)
|
app.include_router(view_router)
|
||||||
return app
|
return app
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
from fastapi import APIRouter
|
from fastapi import FastAPI
|
||||||
|
|
||||||
from . import schedule, weather
|
from . import schedule, weather
|
||||||
|
|
||||||
router = APIRouter(prefix="/api", tags=["API"])
|
|
||||||
router.include_router(weather.router)
|
def mount(app: FastAPI):
|
||||||
router.include_router(schedule.router)
|
weather.mount(app)
|
||||||
|
schedule.mount(app)
|
||||||
|
|||||||
@@ -1,20 +1,18 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from fastapi import APIRouter
|
from fastapi import FastAPI
|
||||||
|
|
||||||
from gallery.easel.core import AppRequest
|
from gallery.easel.core import AppRequest
|
||||||
from gallery.sketch.schedule.model import ChannelId, Schedule
|
from gallery.sketch.schedule.model import ChannelId, Schedule
|
||||||
|
|
||||||
router = APIRouter(prefix="/schedule")
|
|
||||||
|
|
||||||
|
def mount(app: FastAPI):
|
||||||
@router.get("/channels")
|
@app.get("/api/schedule/channels", tags=["API"])
|
||||||
async def get_api_schedule_channels(request: AppRequest) -> list[ChannelId]:
|
async def get_api_schedule_channels(request: AppRequest) -> list[ChannelId]:
|
||||||
schedule_api = request.app.state.api.schedule
|
schedule_api = request.app.state.api.schedule
|
||||||
return await schedule_api.get_channels()
|
return await schedule_api.get_channels()
|
||||||
|
|
||||||
|
@app.get("/api/schedule/{channel}/{date}", tags=["API"])
|
||||||
@router.get("/{channel}/{date}")
|
|
||||||
async def get_api_schedule_channel_schedule(request: AppRequest, channel: str, date: datetime.date) -> Schedule:
|
async def get_api_schedule_channel_schedule(request: AppRequest, channel: str, date: datetime.date) -> Schedule:
|
||||||
schedule_api = request.app.state.api.schedule
|
schedule_api = request.app.state.api.schedule
|
||||||
return await schedule_api.get_channel_schedule(ChannelId(channel), date)
|
return await schedule_api.get_channel_schedule(ChannelId(channel), date)
|
||||||
|
|||||||
@@ -1,26 +1,23 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from fastapi import APIRouter
|
from fastapi import FastAPI
|
||||||
|
|
||||||
from gallery.easel.core import AppRequest
|
from gallery.easel.core import AppRequest
|
||||||
from gallery.sketch.weather.model import Location, WeatherResponse
|
from gallery.sketch.weather.model import Location, WeatherResponse
|
||||||
|
|
||||||
router = APIRouter(prefix="/weather")
|
|
||||||
|
|
||||||
|
def mount(app: FastAPI):
|
||||||
@router.get("/locations")
|
@app.get("/api/weather/locations", tags=["API"])
|
||||||
async def get_api_weather_locations(request: AppRequest, query: str) -> list[Location]:
|
async def get_api_weather_locations(request: AppRequest, query: str) -> list[Location]:
|
||||||
weather_api = request.app.state.api.weather
|
weather_api = request.app.state.api.weather
|
||||||
return await weather_api.find_locations(query)
|
return await weather_api.find_locations(query)
|
||||||
|
|
||||||
|
@app.get("/api/weather/{location}/day/{date}", tags=["API"])
|
||||||
@router.get("/{location}/day/{date}")
|
|
||||||
async def get_api_weather_day(request: AppRequest, location: str, date: datetime.date) -> WeatherResponse:
|
async def get_api_weather_day(request: AppRequest, location: str, date: datetime.date) -> WeatherResponse:
|
||||||
weather_api = request.app.state.api.weather
|
weather_api = request.app.state.api.weather
|
||||||
return await weather_api.get_day(location, date)
|
return await weather_api.get_day(location, date)
|
||||||
|
|
||||||
|
@app.get("/api/weather/{location}/days/{days}", tags=["API"])
|
||||||
@router.get("/{location}/days/{days}")
|
|
||||||
async def get_api_weather_days(request: AppRequest, location: str, days: int) -> WeatherResponse:
|
async def get_api_weather_days(request: AppRequest, location: str, days: int) -> WeatherResponse:
|
||||||
weather_api = request.app.state.api.weather
|
weather_api = request.app.state.api.weather
|
||||||
return await weather_api.get_days(location, days)
|
return await weather_api.get_days(location, days)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from .schedule import router as schedule_router
|
|||||||
from .translation import set_language
|
from .translation import set_language
|
||||||
from .weather import router as weather_router
|
from .weather import router as weather_router
|
||||||
|
|
||||||
router = APIRouter(tags=["view"], dependencies=[Depends(set_language)])
|
router = APIRouter(dependencies=[Depends(set_language)])
|
||||||
router.include_router(common_router)
|
router.include_router(common_router)
|
||||||
router.include_router(weather_router)
|
router.include_router(weather_router)
|
||||||
router.include_router(schedule_router)
|
router.include_router(schedule_router)
|
||||||
|
|||||||
@@ -30,9 +30,6 @@
|
|||||||
{% block header %}{% endblock %}
|
{% block header %}{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
<ul class="navbar-nav flex-row flex-wrap ms-md-auto">
|
<ul class="navbar-nav flex-row flex-wrap ms-md-auto">
|
||||||
<li class="nav-item me-2">
|
|
||||||
<span class="nav-link">{{ version }}</span>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item dropdown">
|
<li class="nav-item dropdown">
|
||||||
<button class="btn btn-link nav-link py-2 px-0 px-lg-2 dropdown-toggle d-flex align-items-center"
|
<button class="btn btn-link nav-link py-2 px-0 px-lg-2 dropdown-toggle d-flex align-items-center"
|
||||||
id="bd-language"
|
id="bd-language"
|
||||||
@@ -40,7 +37,7 @@
|
|||||||
aria-expanded="false"
|
aria-expanded="false"
|
||||||
data-bs-toggle="dropdown"
|
data-bs-toggle="dropdown"
|
||||||
aria-label="{{_('Select language')}} (default)">
|
aria-label="{{_('Select language')}} (default)">
|
||||||
<span class="fi fir fi-gb me-2 language-icon-active icon-header"></span>
|
<span class="fi fir fi-gb me-2 language-icon-active"></span>
|
||||||
<span class="d-lg-none ms-2"
|
<span class="d-lg-none ms-2"
|
||||||
id="bd-language-text">{{_("Select language")}}</span>
|
id="bd-language-text">{{_("Select language")}}</span>
|
||||||
</button>
|
</button>
|
||||||
@@ -73,7 +70,7 @@
|
|||||||
aria-expanded="false"
|
aria-expanded="false"
|
||||||
data-bs-toggle="dropdown"
|
data-bs-toggle="dropdown"
|
||||||
aria-label="Toggle theme (auto)">
|
aria-label="Toggle theme (auto)">
|
||||||
<span class="bi bi-circle-half me-2 opacity-50 theme-icon-active icon-header"></span>
|
<span class="bi bi-circle-half me-2 opacity-50 theme-icon-active"></span>
|
||||||
<span class="d-lg-none ms-2"
|
<span class="d-lg-none ms-2"
|
||||||
id="bd-theme-text">{{_("Toggle theme")}}</span>
|
id="bd-theme-text">{{_("Toggle theme")}}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import datetime
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from babel.dates import format_date
|
from babel.dates import format_date
|
||||||
@@ -8,7 +7,6 @@ from fastapi.templating import Jinja2Templates
|
|||||||
from gallery.version import __version__
|
from gallery.version import __version__
|
||||||
|
|
||||||
from ...translation import _
|
from ...translation import _
|
||||||
from .tag import TagUtil
|
|
||||||
|
|
||||||
|
|
||||||
def is_widget(request: Request) -> bool:
|
def is_widget(request: Request) -> bool:
|
||||||
@@ -33,9 +31,6 @@ def build_templates(templates_dir: Path | None = None, filters: dict | None = No
|
|||||||
"_": _,
|
"_": _,
|
||||||
"version": __version__,
|
"version": __version__,
|
||||||
"format_date": format_date,
|
"format_date": format_date,
|
||||||
"datetime": datetime,
|
|
||||||
"tag_util": TagUtil,
|
|
||||||
"DATE_FORMAT": "E, d MMMM Y",
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if filters:
|
if filters:
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{{_("TV program")}} | {{response.channel.name}} | {{format_date(response.date, DATE_FORMAT,
|
{{_("TV program")}} | {{response.channel.name}} | {{format_date(response.date, 'E, d MMMM Y', locale=request.state.language)}}
|
||||||
locale=request.state.language)}}
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block header %}
|
{% block header %}
|
||||||
@@ -11,19 +10,13 @@ locale=request.state.language)}}
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h4>
|
<h4>
|
||||||
<a class="icon-link {{'disabled' if response.date == datetime.date.today() else ''}}"
|
<a class="button {{'disabled' if response.date == datetime.date.today() else ''}}"
|
||||||
href="../tag/{{tag_util.create_tag('day', response.date, -1)}}">
|
href="../tag/{{tag_util.create_tag('day', response.date, -1)}}">⬅️</a>
|
||||||
<i class="bi bi-arrow-left-square"></i>
|
<a class="button"
|
||||||
</a>
|
href="../..">⬆️</a>
|
||||||
<a class="icon-link"
|
<span>{{response.channel.name}} | {{format_date(response.date, 'E, d MMMM Y', locale=request.state.language)}}</span>
|
||||||
href="../..">
|
<a class="button"
|
||||||
<i class="bi bi-arrow-up-square"></i>
|
href="../tag/{{tag_util.create_tag('day', response.date, 1)}}">➡️</a>
|
||||||
</a>
|
|
||||||
<span>{{response.channel.name}} | {{format_date(response.date, DATE_FORMAT, locale=request.state.language)}}</span>
|
|
||||||
<a class="icon-link"
|
|
||||||
href="../tag/{{tag_util.create_tag('day', response.date, 1)}}">
|
|
||||||
<i class="bi bi-arrow-right-square"></i>
|
|
||||||
</a>
|
|
||||||
</h4>
|
</h4>
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{{_("Live broadcasts") if live else _("TV program")}} | {{format_date(response.date, DATE_FORMAT,
|
{{_("Live broadcasts") if live else _("TV program")}} | {{format_date(response.date, 'E, d MMMM Y', locale=request.state.language)}}
|
||||||
locale=request.state.language)}}
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block header %}
|
{% block header %}
|
||||||
@@ -11,20 +10,13 @@ locale=request.state.language)}}
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h4>
|
<h4>
|
||||||
<a class="icon-link {{'disabled' if response.date == datetime.date.today() else ''}}"
|
<a class="button {{'disabled' if response.date == datetime.date.today() else ''}}"
|
||||||
href="../tag/{{tag_util.create_tag('day', response.date, -1)}}">
|
href="../tag/{{tag_util.create_tag('day', response.date, -1)}}">⬅️</a>
|
||||||
<i class="bi bi-arrow-left-square"></i>
|
<a class="button"
|
||||||
</a>
|
href="..">⬆️</a>
|
||||||
<a class="icon-link"
|
<span>{{_("Live broadcasts") if live else _("TV program")}} | {{format_date(response.date, 'E, d MMMM Y', locale=request.state.language)}}</span>
|
||||||
href="..">
|
<a class="button"
|
||||||
<i class="bi bi-arrow-up-square"></i>
|
href="../tag/{{tag_util.create_tag('day', response.date, 1)}}">➡️</a>
|
||||||
</a>
|
|
||||||
<span>{{_("Live broadcasts") if live else _("TV program")}} | {{format_date(response.date, DATE_FORMAT,
|
|
||||||
locale=request.state.language)}}</span>
|
|
||||||
<a class="icon-link"
|
|
||||||
href="../tag/{{tag_util.create_tag('day', response.date, 1)}}">
|
|
||||||
<i class="bi bi-arrow-right-square"></i>
|
|
||||||
</a>
|
|
||||||
</h4>
|
</h4>
|
||||||
<div>
|
<div>
|
||||||
<table class="table">
|
<table class="table">
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ def build_weather_response(request: AppRequest, response: WeatherResponse):
|
|||||||
request=request,
|
request=request,
|
||||||
name="weather.html",
|
name="weather.html",
|
||||||
context={
|
context={
|
||||||
|
"tag_util": TagUtil,
|
||||||
|
"datetime": datetime,
|
||||||
"response": response,
|
"response": response,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from gallery.sketch.weather.model import (
|
from gallery.sketch.weather.model import Cloudness, Precipitation, Sky, WindDirection, WindDirectionDeg
|
||||||
Cloudness,
|
|
||||||
Precipitation,
|
|
||||||
Sky,
|
|
||||||
WindDirection,
|
|
||||||
WindDirectionDeg,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def wind_direction_icon(wind_direction_deg: float) -> str:
|
def wind_direction_icon(wind_direction_deg: float) -> str:
|
||||||
|
|||||||
@@ -9,24 +9,16 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<h4>
|
<h4>
|
||||||
{% if response.period == 'day' %}
|
{% if response.period == 'day' %}
|
||||||
<a class="icon-link {{'disabled' if response.date == datetime.date.today() else ''}}"
|
<a class="button {{'disabled' if response.date == datetime.date.today() else ''}}"
|
||||||
href="../tag/{{tag_util.create_tag('day', response.date, -1)}}">
|
href="../tag/{{tag_util.create_tag('day', response.date, -1)}}">⬅️</a>
|
||||||
<i class="bi bi-arrow-left-square"></i>
|
<a class="button"
|
||||||
</a>
|
href="../tag/days-10">⬆️</a>
|
||||||
<a class="icon-link"
|
<span>{{response.location}} | {{format_date(response.date, 'E, d MMMM Y', locale=request.state.language)}}</span>
|
||||||
href="../tag/days-10">
|
<a class="button"
|
||||||
<i class="bi bi-arrow-up-square"></i>
|
href="../tag/{{tag_util.create_tag('day', response.date, 1)}}">➡️</a>
|
||||||
</a>
|
|
||||||
<span>{{response.location}} | {{format_date(response.date, DATE_FORMAT, locale=request.state.language)}}</span>
|
|
||||||
<a class="icon-link"
|
|
||||||
href="../tag/{{tag_util.create_tag('day', response.date, 1)}}">
|
|
||||||
<i class="bi bi-arrow-right-square"></i>
|
|
||||||
</a>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if response.period == 'days' %}
|
{% if response.period == 'days' %}
|
||||||
<span>{{response.location}} | {{format_date(response.date, DATE_FORMAT, locale=request.state.language)}}</span>
|
<span>{{response.location}} | {{format_date(response.date, 'E, d MMMM Y', locale=request.state.language)}}</span>
|
||||||
<span>- {{format_date(response.date + datetime.timedelta(days=(response.values | length - 1)), DATE_FORMAT,
|
|
||||||
locale=request.state.language)}}</span>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</h4>
|
</h4>
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
@@ -66,7 +58,8 @@
|
|||||||
data-bs-toggle="tooltip"
|
data-bs-toggle="tooltip"
|
||||||
data-bs-title="{{ value.sky }}">
|
data-bs-title="{{ value.sky }}">
|
||||||
{% for icon in value.sky | cloudness_icon(value.date, response.period) %}
|
{% for icon in value.sky | cloudness_icon(value.date, response.period) %}
|
||||||
<div class="wi wi-{{icon}} wi-xl text-primary"></div>
|
<div class="wi wi-{{icon}} text-primary"
|
||||||
|
style="font-size: 3.5rem;"></div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</td>
|
</td>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -102,7 +95,7 @@
|
|||||||
<td class="wind"
|
<td class="wind"
|
||||||
data-bs-toggle="tooltip"
|
data-bs-toggle="tooltip"
|
||||||
data-bs-title="{{ value.wind_direction }}">
|
data-bs-title="{{ value.wind_direction }}">
|
||||||
<div class="wi wi-wind-deg wi-{{value.wind_direction | wind_direction_icon}} wi-l text-primary"></div>
|
<div class="wi wi-wind-deg wi-{{value.wind_direction | wind_direction_icon}} fs-1 text-primary"></div>
|
||||||
</td>
|
</td>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -39,11 +39,14 @@ class DateParser(RowParser[datetime.datetime]):
|
|||||||
KEY = "date"
|
KEY = "date"
|
||||||
|
|
||||||
def parse_row(self, tag: Tag) -> Iterable[datetime.datetime]:
|
def parse_row(self, tag: Tag) -> Iterable[datetime.datetime]:
|
||||||
datetime_time_row = tag.select_one(".widget-row.widget-row-datetime-time")
|
datetime_date_tag = tag.select_one(".widget-row.widget-row-datetime-date > .row-item")
|
||||||
if datetime_time_row:
|
if datetime_date_tag:
|
||||||
for item in datetime_time_row.select(".row-item > time-value"):
|
date_str = datetime_date_tag.find(text=True, recursive=False).text
|
||||||
timestamp = int(item.attrs["timestamp"])
|
date = dateparser.parse(date_str, languages=["ru"])
|
||||||
time = datetime.datetime.fromtimestamp(timestamp)
|
for item in tag.select(".widget-row.widget-row-datetime-time > .row-item"):
|
||||||
|
time_str = item.text
|
||||||
|
time = dateparser.parse(time_str, languages=["ru"])
|
||||||
|
time = time.replace(year=date.year, month=date.month, day=date.day)
|
||||||
yield time
|
yield time
|
||||||
else:
|
else:
|
||||||
for item in tag.select(".widget-row.widget-row-date > .row-item"):
|
for item in tag.select(".widget-row.widget-row-date > .row-item"):
|
||||||
@@ -170,12 +173,8 @@ class PrecipitationParser(RowParser[float]):
|
|||||||
KEY = "precipitation"
|
KEY = "precipitation"
|
||||||
|
|
||||||
def parse_row(self, tag: Tag) -> Iterable[float]:
|
def parse_row(self, tag: Tag) -> Iterable[float]:
|
||||||
for item in tag.select(".widget-row[data-row=precipitation-bars] > .row-item"):
|
for item in tag.select(".widget-row[data-row=precipitation-bars] > .row-item > .item-unit"):
|
||||||
value = item.select_one("precipitation-value")
|
yield float(item.text.replace(",", "."))
|
||||||
if value:
|
|
||||||
yield float(value.attrs["value"])
|
|
||||||
else:
|
|
||||||
yield 0
|
|
||||||
|
|
||||||
|
|
||||||
class PressureParser(RowParser[list[int]]):
|
class PressureParser(RowParser[list[int]]):
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
__version__ = "0.2.2"
|
||||||
|
|
||||||
import tomllib
|
import tomllib
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "gallery"
|
name = "gallery"
|
||||||
version = "0.3.4"
|
version = "0.2.3"
|
||||||
description = ""
|
description = ""
|
||||||
authors = ["shmyga <shmyga.z@gmail.com>"]
|
authors = ["shmyga <shmyga.z@gmail.com>"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|||||||
4
static/package-lock.json
generated
4
static/package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "gallery",
|
"name": "gallery",
|
||||||
"version": "0.3.4",
|
"version": "0.2.3",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "gallery",
|
"name": "gallery",
|
||||||
"version": "0.3.4",
|
"version": "0.2.3",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@popperjs/core": "^2.11.8",
|
"@popperjs/core": "^2.11.8",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "gallery",
|
"name": "gallery",
|
||||||
"version": "0.3.4",
|
"version": "0.2.3",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"dev": "vite build --watch"
|
"dev": "vite build --watch"
|
||||||
|
|||||||
19
static/src/lib/bootstrap-icons.scss
vendored
19
static/src/lib/bootstrap-icons.scss
vendored
@@ -1,6 +1,4 @@
|
|||||||
.icon-link {
|
//$bootstrap-icons: "circle-half", "moon-stars-fill", "brightness-high", "gear", "sun-fill", "tv";
|
||||||
vertical-align: -0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bi {
|
.bi {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@@ -15,6 +13,12 @@
|
|||||||
mask-repeat: no-repeat;
|
mask-repeat: no-repeat;
|
||||||
background-color: currentColor;
|
background-color: currentColor;
|
||||||
|
|
||||||
|
//@each $icon in $bootstrap-icons {
|
||||||
|
// &.bi-#{$icon} {
|
||||||
|
// mask-image: url("bootstrap-icons/icons/#{$icon}.svg");
|
||||||
|
// }
|
||||||
|
///
|
||||||
|
|
||||||
&.bi-circle-half {
|
&.bi-circle-half {
|
||||||
mask-image: url(bootstrap-icons/icons/circle-half.svg);
|
mask-image: url(bootstrap-icons/icons/circle-half.svg);
|
||||||
}
|
}
|
||||||
@@ -33,13 +37,4 @@
|
|||||||
&.bi-tv {
|
&.bi-tv {
|
||||||
mask-image: url(bootstrap-icons/icons/tv.svg);
|
mask-image: url(bootstrap-icons/icons/tv.svg);
|
||||||
}
|
}
|
||||||
&.bi-arrow-left-square {
|
|
||||||
mask-image: url(bootstrap-icons/icons/arrow-left-square.svg);
|
|
||||||
}
|
|
||||||
&.bi-arrow-right-square {
|
|
||||||
mask-image: url(bootstrap-icons/icons/arrow-right-square.svg);
|
|
||||||
}
|
|
||||||
&.bi-arrow-up-square {
|
|
||||||
mask-image: url(bootstrap-icons/icons/arrow-up-square.svg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,4 @@
|
|||||||
.fir {
|
.fir {
|
||||||
@extend .fis;
|
@extend .fis;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
height: 1em;
|
|
||||||
border: 1px solid gray;
|
|
||||||
}
|
}
|
||||||
@@ -13,11 +13,4 @@
|
|||||||
mask-position: 50%;
|
mask-position: 50%;
|
||||||
mask-repeat: no-repeat;
|
mask-repeat: no-repeat;
|
||||||
background-color: currentColor;
|
background-color: currentColor;
|
||||||
|
|
||||||
&.wi-l {
|
|
||||||
font-size: 2.5rem;
|
|
||||||
}
|
|
||||||
&.wi-xl {
|
|
||||||
font-size: 3.5rem;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-header {
|
.icon {
|
||||||
@include font-size($h4-font-size);
|
display: inline-block;
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
background-size: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-header {
|
.app-header {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user