Deploy folkugat web
This commit is contained in:
15
README.org
15
README.org
@@ -1,25 +1,20 @@
|
|||||||
#+title: Readme
|
#+title: Readme
|
||||||
|
|
||||||
* Tasques
|
* Tasques
|
||||||
** TODO Refactor organitzatiu
|
** TODO Ordenar els resultats de la cerca de temes
|
||||||
|
** TODO Suport per a diverses organitzacions (no només jam de Sant Cugat)
|
||||||
|
** TODO Usuaris i permisos granulars
|
||||||
|
** TODO Lilypond support (o similar)
|
||||||
|
*** TODO Fer cançoners "en directe"
|
||||||
* Idees
|
* Idees
|
||||||
** Jams
|
** Jams
|
||||||
*** Properes jams
|
*** Properes jams
|
||||||
**** Data i lloc de les properes jams
|
|
||||||
**** Info dels temes que es tocaràn (a la slow jam)
|
**** Info dels temes que es tocaràn (a la slow jam)
|
||||||
*** Live jam
|
|
||||||
**** Quin tema està sonant ara
|
|
||||||
*** Historial de jams
|
|
||||||
**** Veure a cada jam passada quins temes s'han tocat
|
|
||||||
** Temes
|
** Temes
|
||||||
*** Navegació
|
*** Navegació
|
||||||
**** Cerca de temes
|
**** Cerca de temes
|
||||||
***** Per nom, tonalitat, compàs, tipus, (shazam!?!?!)
|
***** Per nom, tonalitat, compàs, tipus, (shazam!?!?!)
|
||||||
***** Per tocats recentment
|
***** Per tocats recentment
|
||||||
**** Informació
|
|
||||||
***** Nom
|
|
||||||
***** Tonalitat i compàs
|
|
||||||
***** Vegades que s'ha tocat
|
|
||||||
* Referències
|
* Referències
|
||||||
Fonts d'inspiració i altres materials de referència per fer la web de folkugat
|
Fonts d'inspiració i altres materials de referència per fer la web de folkugat
|
||||||
** Simple Site
|
** Simple Site
|
||||||
|
|||||||
8
build.sh
Executable file
8
build.sh
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
tailwindcss -i folkugat_web/assets/static/src/tw.css -o folkugat_web/assets/static/css/main.css --minify
|
||||||
|
|
||||||
|
docker build -t marc.sastre.cat/folkugat-web -f deploy/Dockerfile .
|
||||||
|
|
||||||
|
docker push marc.sastre.cat/folkugat-web:latest
|
||||||
11
deploy/Dockerfile
Normal file
11
deploy/Dockerfile
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
FROM python:3.11
|
||||||
|
|
||||||
|
WORKDIR /folkugat
|
||||||
|
|
||||||
|
COPY deploy/requirements.txt /folkugat/requirements.txt
|
||||||
|
|
||||||
|
RUN pip install --no-cache-dir --upgrade -r /folkugat/requirements.txt
|
||||||
|
|
||||||
|
COPY folkugat_web /folkugat/folkugat_web
|
||||||
|
|
||||||
|
CMD ["uvicorn", "folkugat_web.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"]
|
||||||
11
deploy/requirements.in
Normal file
11
deploy/requirements.in
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# API
|
||||||
|
fastapi
|
||||||
|
python-multipart
|
||||||
|
jinja2
|
||||||
|
uvicorn
|
||||||
|
# Files
|
||||||
|
python-magic
|
||||||
|
# Auth
|
||||||
|
pyjwt
|
||||||
|
# Search
|
||||||
|
levenshtein
|
||||||
48
deploy/requirements.txt
Normal file
48
deploy/requirements.txt
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#
|
||||||
|
# This file is autogenerated by pip-compile with Python 3.11
|
||||||
|
# by the following command:
|
||||||
|
#
|
||||||
|
# pip-compile --output-file=deploy/requirements.txt deploy/requirements.in
|
||||||
|
#
|
||||||
|
annotated-types==0.7.0
|
||||||
|
# via pydantic
|
||||||
|
anyio==4.9.0
|
||||||
|
# via starlette
|
||||||
|
click==8.1.8
|
||||||
|
# via uvicorn
|
||||||
|
fastapi==0.115.12
|
||||||
|
# via -r deploy/requirements.in
|
||||||
|
h11==0.14.0
|
||||||
|
# via uvicorn
|
||||||
|
idna==3.10
|
||||||
|
# via anyio
|
||||||
|
jinja2==3.1.6
|
||||||
|
# via -r deploy/requirements.in
|
||||||
|
levenshtein==0.27.1
|
||||||
|
# via -r deploy/requirements.in
|
||||||
|
markupsafe==3.0.2
|
||||||
|
# via jinja2
|
||||||
|
pydantic==2.10.6
|
||||||
|
# via fastapi
|
||||||
|
pydantic-core==2.27.2
|
||||||
|
# via pydantic
|
||||||
|
pyjwt==2.10.1
|
||||||
|
# via -r deploy/requirements.in
|
||||||
|
python-magic==0.4.27
|
||||||
|
# via -r deploy/requirements.in
|
||||||
|
python-multipart==0.0.20
|
||||||
|
# via -r deploy/requirements.in
|
||||||
|
rapidfuzz==3.12.2
|
||||||
|
# via levenshtein
|
||||||
|
sniffio==1.3.1
|
||||||
|
# via anyio
|
||||||
|
starlette==0.46.1
|
||||||
|
# via fastapi
|
||||||
|
typing-extensions==4.12.2
|
||||||
|
# via
|
||||||
|
# anyio
|
||||||
|
# fastapi
|
||||||
|
# pydantic
|
||||||
|
# pydantic-core
|
||||||
|
uvicorn==0.34.0
|
||||||
|
# via -r deploy/requirements.in
|
||||||
20
docker-compose.yml
Normal file
20
docker-compose.yml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
services:
|
||||||
|
folkugat:
|
||||||
|
# image: "marc.sastre.cat/quinto-cua:latest"
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: deploy/Dockerfile
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- JWT_SECRET=12345
|
||||||
|
- ADMIN_PASSWORD=prova
|
||||||
|
- DB_DIR=/folkugat/files
|
||||||
|
volumes:
|
||||||
|
- /home/marc/tmp/folkugat:/folkugat/files
|
||||||
|
ports:
|
||||||
|
- "8001:80"
|
||||||
|
networks:
|
||||||
|
- folkugat
|
||||||
|
|
||||||
|
networks:
|
||||||
|
folkugat:
|
||||||
@@ -22,6 +22,8 @@
|
|||||||
pytest
|
pytest
|
||||||
setuptools
|
setuptools
|
||||||
ipython
|
ipython
|
||||||
|
# To compile requirements
|
||||||
|
pip-tools
|
||||||
];
|
];
|
||||||
|
|
||||||
projectDependencies = with pythonPackages; [
|
projectDependencies = with pythonPackages; [
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from fastapi.responses import HTMLResponse
|
|||||||
from folkugat_web.api import router
|
from folkugat_web.api import router
|
||||||
from folkugat_web.fragments import tema, temes
|
from folkugat_web.fragments import tema, temes
|
||||||
from folkugat_web.services import auth
|
from folkugat_web.services import auth
|
||||||
|
from folkugat_web.services import files as files_service
|
||||||
from folkugat_web.services.temes import links as links_service
|
from folkugat_web.services.temes import links as links_service
|
||||||
from folkugat_web.services.temes import lyrics as lyrics_service
|
from folkugat_web.services.temes import lyrics as lyrics_service
|
||||||
from folkugat_web.services.temes import properties as properties_service
|
from folkugat_web.services.temes import properties as properties_service
|
||||||
@@ -46,6 +47,7 @@ def contingut(request: Request, logged_in: auth.LoggedIn, tema_id: int):
|
|||||||
@router.delete("/api/tema/{tema_id}")
|
@router.delete("/api/tema/{tema_id}")
|
||||||
def delete_tema(_: auth.RequireLogin, tema_id: int):
|
def delete_tema(_: auth.RequireLogin, tema_id: int):
|
||||||
temes_w.delete_tema(tema_id=tema_id)
|
temes_w.delete_tema(tema_id=tema_id)
|
||||||
|
files_service.clean_orphan_files()
|
||||||
return HTMLResponse(headers={
|
return HTMLResponse(headers={
|
||||||
'HX-Redirect': '/temes'
|
'HX-Redirect': '/temes'
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ from fastapi.responses import HTMLResponse
|
|||||||
from folkugat_web.api import router
|
from folkugat_web.api import router
|
||||||
from folkugat_web.fragments.tema import links as links_fragments
|
from folkugat_web.fragments.tema import links as links_fragments
|
||||||
from folkugat_web.model import temes as model
|
from folkugat_web.model import temes as model
|
||||||
from folkugat_web.services import auth, files
|
from folkugat_web.services import auth
|
||||||
|
from folkugat_web.services import files as files_service
|
||||||
from folkugat_web.services.temes import links as links_service
|
from folkugat_web.services.temes import links as links_service
|
||||||
|
from folkugat_web.services.temes import query as temes_q
|
||||||
|
|
||||||
|
|
||||||
@router.get("/api/tema/{tema_id}/link/{link_id}")
|
@router.get("/api/tema/{tema_id}/link/{link_id}")
|
||||||
@@ -30,7 +32,7 @@ async def set_link(
|
|||||||
upload_file: Annotated[UploadFile | None, File()] = None,
|
upload_file: Annotated[UploadFile | None, File()] = None,
|
||||||
):
|
):
|
||||||
if upload_file:
|
if upload_file:
|
||||||
url = await files.store_file(tema_id=tema_id, upload_file=upload_file)
|
url = await files_service.store_file(tema_id=tema_id, upload_file=upload_file)
|
||||||
|
|
||||||
link_type = links_service.guess_link_type(url or '')
|
link_type = links_service.guess_link_type(url or '')
|
||||||
new_link = model.Link(
|
new_link = model.Link(
|
||||||
@@ -66,6 +68,7 @@ def delete_link(
|
|||||||
link_id: int,
|
link_id: int,
|
||||||
):
|
):
|
||||||
links_service.delete_link(link_id=link_id, tema_id=tema_id)
|
links_service.delete_link(link_id=link_id, tema_id=tema_id)
|
||||||
|
files_service.clean_orphan_files()
|
||||||
return HTMLResponse(
|
return HTMLResponse(
|
||||||
headers={
|
headers={
|
||||||
"HX-Trigger": f"reload-tema-{tema_id}-score"
|
"HX-Trigger": f"reload-tema-{tema_id}-score"
|
||||||
@@ -102,10 +105,14 @@ def get_score(
|
|||||||
logged_in: auth.LoggedIn,
|
logged_in: auth.LoggedIn,
|
||||||
tema_id: int,
|
tema_id: int,
|
||||||
):
|
):
|
||||||
|
tema = temes_q.get_tema_by_id(tema_id)
|
||||||
|
if not tema:
|
||||||
|
raise HTTPException(status_code=404, detail="Could not find tune")
|
||||||
|
tema = links_service.add_links_to_tema(tema)
|
||||||
return links_fragments.score(
|
return links_fragments.score(
|
||||||
request=request,
|
request=request,
|
||||||
logged_in=logged_in,
|
logged_in=logged_in,
|
||||||
tema_id=tema_id,
|
tema=tema,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,5 +1,5 @@
|
|||||||
<div class="h-4/5 min-h-[400px] flex flex-col items-center justify-center">
|
<div class="h-4/5 min-h-[400px] flex flex-col items-center justify-center">
|
||||||
<img src="{{ url_for('static', path='img/folkugat.svg') }}"
|
<img src="{{ url_for(request, 'static', path='img/folkugat.svg') }}"
|
||||||
class="{% if animate %} opacity-0 animate-fade-in-one {% endif %} m-3"
|
class="{% if animate %} opacity-0 animate-fade-in-one {% endif %} m-3"
|
||||||
width="100"
|
width="100"
|
||||||
alt="Folkugat"/>
|
alt="Folkugat"/>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<!-- PDF Viewer -->
|
<!-- PDF Viewer -->
|
||||||
<script type="module">
|
<script type="module">
|
||||||
const pdfViewer = await import("{{ url_for('static', path='js/pdf_viewer.js') }}");
|
const pdfViewer = await import("{{ url_for(request, 'static', path='js/pdf_viewer.js') }}");
|
||||||
const options = {
|
const options = {
|
||||||
url: '{{ pdf_url }}',
|
url: '{{ pdf_url }}',
|
||||||
// PDF Canvas (where the pdf will be displayed)
|
// PDF Canvas (where the pdf will be displayed)
|
||||||
@@ -24,13 +24,13 @@
|
|||||||
<!-- </a> -->
|
<!-- </a> -->
|
||||||
<!-- </div> -->
|
<!-- </div> -->
|
||||||
<div class="flex flex-row flex-nowrap items-center justify-center w-full">
|
<div class="flex flex-row flex-nowrap items-center justify-center w-full">
|
||||||
<button id="prev" class="flex-none text-xl text-beige mx-3">
|
<button id="prev" class="flex-none text-xl text-beige mr-2">
|
||||||
<i class="fa fa-chevron-left" aria-hidden="true"></i>
|
<i class="fa fa-chevron-left" aria-hidden="true"></i>
|
||||||
</button>
|
</button>
|
||||||
<canvas class="flex-auto m-2 w-1/2 max-w-3xl"
|
<canvas class="flex-auto m-2 w-1/2 max-w-3xl"
|
||||||
id="the-canvas">
|
id="the-canvas">
|
||||||
</canvas>
|
</canvas>
|
||||||
<button id="next" class="flex-none text-xl text-beige mx-3">
|
<button id="next" class="flex-none text-xl text-beige ml-2">
|
||||||
<i class="fa fa-chevron-right" aria-hidden="true"></i>
|
<i class="fa fa-chevron-right" aria-hidden="true"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -14,15 +14,15 @@
|
|||||||
referrerpolicy="no-referrer" />
|
referrerpolicy="no-referrer" />
|
||||||
|
|
||||||
<!-- Taiwind CSS -->
|
<!-- Taiwind CSS -->
|
||||||
<link rel="stylesheet" href="{{ url_for('static', path='css/main.css') }}" type="text/css" />
|
<link rel="stylesheet" href="{{ url_for(request, 'static', path='css/main.css') }}" type="text/css" />
|
||||||
|
|
||||||
<!-- HTMX -->
|
<!-- HTMX -->
|
||||||
<script src="{{ url_for('static', path='js/htmx.min.js') }}"></script>
|
<script src="{{ url_for(request, 'static', path='js/htmx.min.js') }}"></script>
|
||||||
|
|
||||||
<!-- Favicon! -->
|
<!-- Favicon! -->
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="{{ url_for('static', path='favicon/apple-touch-icon.png') }}">
|
<link rel="apple-touch-icon" sizes="180x180" href="{{ url_for(request, 'static', path='favicon/apple-touch-icon.png') }}">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="{{ url_for('static', path='favicon/favicon-32x32.png') }}">
|
<link rel="icon" type="image/png" sizes="32x32" href="{{ url_for(request, 'static', path='favicon/favicon-32x32.png') }}">
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="{{ url_for('static', path='favicon/favicon-16x16.png') }}">
|
<link rel="icon" type="image/png" sizes="16x16" href="{{ url_for(request, 'static', path='favicon/favicon-16x16.png') }}">
|
||||||
<link rel="manifest" href="/site.webmanifest">
|
<link rel="manifest" href="/site.webmanifest">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
3
folkugat_web/config/api.py
Normal file
3
folkugat_web/config/api.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
URL_SCHEME = os.getenv("URL_SCHEME", "http")
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
from fastapi import HTTPException, Request
|
from fastapi import Request
|
||||||
from folkugat_web.model import temes as model
|
from folkugat_web.model import temes as model
|
||||||
from folkugat_web.services.temes import query as temes_q
|
|
||||||
from folkugat_web.services.temes.links import guess_link_type
|
|
||||||
from folkugat_web.templates import templates
|
from folkugat_web.templates import templates
|
||||||
|
|
||||||
|
|
||||||
@@ -73,10 +71,7 @@ def link_icon(request: Request, logged_in: bool, link: model.Link):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def score(request: Request, logged_in: bool, tema_id: int):
|
def score(request: Request, logged_in: bool, tema: model.Tema):
|
||||||
tema = temes_q.get_tema_by_id(tema_id)
|
|
||||||
if not tema:
|
|
||||||
raise HTTPException(status_code=404, detail="Could not find tune")
|
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
"fragments/tema/score.html",
|
"fragments/tema/score.html",
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -90,4 +90,10 @@ class Tema:
|
|||||||
return link.link_type is LinkType.IMAGE
|
return link.link_type is LinkType.IMAGE
|
||||||
|
|
||||||
def score(self) -> Link | None:
|
def score(self) -> Link | None:
|
||||||
return next(filter(self._is_score, self.links), None)
|
result = next(filter(self._is_score, self.links), None)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class TemaCols(enum.Enum):
|
||||||
|
NOM = "nom"
|
||||||
|
COPS_TOCAT = "cops_tocat"
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
import mimetypes
|
import mimetypes
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
import uuid
|
import uuid
|
||||||
|
from collections.abc import Iterator
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import magic
|
import magic
|
||||||
from fastapi import HTTPException, UploadFile
|
from fastapi import HTTPException, UploadFile
|
||||||
from folkugat_web.config import db
|
from folkugat_web.config import db
|
||||||
|
from folkugat_web.dal.sql.temes import links as links_dal
|
||||||
|
from folkugat_web.log import logger
|
||||||
|
|
||||||
|
|
||||||
async def get_mimetype(upload_file: UploadFile) -> str:
|
async def get_mimetype(upload_file: UploadFile) -> str:
|
||||||
@@ -56,3 +60,17 @@ async def store_file(tema_id: int, upload_file: UploadFile) -> str:
|
|||||||
def list_files(tema_id: str) -> list[str]:
|
def list_files(tema_id: str) -> list[str]:
|
||||||
filedir = db.DB_FILES_DIR / str(tema_id)
|
filedir = db.DB_FILES_DIR / str(tema_id)
|
||||||
return [get_db_file_path(f) for f in filedir.iterdir()]
|
return [get_db_file_path(f) for f in filedir.iterdir()]
|
||||||
|
|
||||||
|
|
||||||
|
def get_orphan_files() -> Iterator[Path]:
|
||||||
|
alive_files = {link.url for link in links_dal.get_links()}
|
||||||
|
return filter(
|
||||||
|
lambda p: p.is_file() and get_db_file_path(p) not in alive_files,
|
||||||
|
db.DB_FILES_DIR.rglob("*"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def clean_orphan_files():
|
||||||
|
for path in get_orphan_files():
|
||||||
|
logger.info(f"Deleting the orphan file: {path}")
|
||||||
|
os.remove(path)
|
||||||
|
|||||||
@@ -1,27 +1,31 @@
|
|||||||
from typing import Optional
|
|
||||||
|
|
||||||
from folkugat_web.dal.sql import Connection
|
from folkugat_web.dal.sql import Connection
|
||||||
from folkugat_web.dal.sql._connection import get_connection
|
from folkugat_web.dal.sql._connection import get_connection
|
||||||
from folkugat_web.dal.sql.playlists import query, write
|
from folkugat_web.dal.sql.playlists import query, write
|
||||||
|
from folkugat_web.log import logger
|
||||||
from folkugat_web.model import playlists
|
from folkugat_web.model import playlists
|
||||||
|
from folkugat_web.services.temes import links as links_service
|
||||||
from folkugat_web.services.temes import query as temes_query
|
from folkugat_web.services.temes import query as temes_query
|
||||||
|
|
||||||
|
|
||||||
def add_temes_to_playlist(playlist: playlists.Playlist) -> playlists.Playlist:
|
def add_temes_to_playlist(playlist: playlists.Playlist) -> playlists.Playlist:
|
||||||
for set_ in playlist.sets:
|
for set_ in playlist.sets:
|
||||||
add_temes_to_set(set_)
|
_ = add_temes_to_set(set_)
|
||||||
return playlist
|
return playlist
|
||||||
|
|
||||||
|
|
||||||
def add_temes_to_set(set_: playlists.Set) -> playlists.Set:
|
def add_temes_to_set(set_: playlists.Set) -> playlists.Set:
|
||||||
for tema_in_set in set_.temes:
|
for tema_in_set in set_.temes:
|
||||||
add_tema_to_tema_in_set(tema_in_set)
|
_ = add_tema_to_tema_in_set(tema_in_set)
|
||||||
return set_
|
return set_
|
||||||
|
|
||||||
|
|
||||||
def add_tema_to_tema_in_set(tema_in_set: playlists.TemaInSet) -> playlists.TemaInSet:
|
def add_tema_to_tema_in_set(tema_in_set: playlists.TemaInSet) -> playlists.TemaInSet:
|
||||||
if tema_in_set.tema_id is not None:
|
if tema_in_set.tema_id is not None:
|
||||||
tema_in_set.tema = temes_query.get_tema_by_id(tema_in_set.tema_id)
|
tema_in_set.tema = temes_query.get_tema_by_id(tema_in_set.tema_id)
|
||||||
|
if not tema_in_set.tema:
|
||||||
|
logger.error("fCould not load tune in set: {tema_in_set}")
|
||||||
|
else:
|
||||||
|
_ = links_service.add_links_to_tema(tema_in_set.tema)
|
||||||
return tema_in_set
|
return tema_in_set
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -84,7 +84,6 @@ def _apply_limit_offset(limit: int, offset: int) -> Callable[[Iterable[model.Tem
|
|||||||
|
|
||||||
def busca_temes(query: str, hidden: bool = False, limit: int = 10, offset: int = 0) -> list[model.Tema]:
|
def busca_temes(query: str, hidden: bool = False, limit: int = 10, offset: int = 0) -> list[model.Tema]:
|
||||||
t0 = time.time()
|
t0 = time.time()
|
||||||
|
|
||||||
with get_connection() as con:
|
with get_connection() as con:
|
||||||
result = (
|
result = (
|
||||||
FnChain.transform(temes_q.get_tema_id_to_ngrams(con).items()) |
|
FnChain.transform(temes_q.get_tema_id_to_ngrams(con).items()) |
|
||||||
|
|||||||
@@ -1,5 +1,20 @@
|
|||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from fastapi import Request
|
||||||
from fastapi.templating import Jinja2Templates
|
from fastapi.templating import Jinja2Templates
|
||||||
|
|
||||||
from folkugat_web.config import directories as config
|
from folkugat_web.config import api as api_config
|
||||||
|
from folkugat_web.config import directories as directories_config
|
||||||
|
|
||||||
templates = Jinja2Templates(directory=config.TEMPLATES_DIR)
|
templates = Jinja2Templates(directory=directories_config.TEMPLATES_DIR)
|
||||||
|
|
||||||
|
|
||||||
|
def url_for(request: Request, name: str, **path_params: Any) -> str:
|
||||||
|
http_url = request.url_for(name, **path_params)
|
||||||
|
if api_config.URL_SCHEME == "http":
|
||||||
|
return str(http_url)
|
||||||
|
# Replace 'http' with 'https'
|
||||||
|
return str(http_url.replace(scheme=api_config.URL_SCHEME))
|
||||||
|
|
||||||
|
|
||||||
|
templates.env.globals["url_for"] = url_for
|
||||||
|
|||||||
Reference in New Issue
Block a user