remove obsolete kontor.py #61

Merged
tpeetz merged 166 commits from develop/0.1.0 into main 2025-04-30 15:31:19 +00:00
20 changed files with 331 additions and 22 deletions
Showing only changes of commit 1290a45fb5 - Show all commits
+1
View File
@@ -21,4 +21,5 @@ dependencies = [
"python-dotenv>=1.1.0", "python-dotenv>=1.1.0",
"python-jose>=3.4.0", "python-jose>=3.4.0",
"python-multipart>=0.0.20", "python-multipart>=0.0.20",
"natsort>=8.4.0",
] ]
+29 -1
View File
@@ -1,3 +1,5 @@
from typing import Dict, List
from natsort import natsorted
from sqlalchemy import Column, ForeignKey, Integer, String from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.dialects.mysql import BIT from sqlalchemy.dialects.mysql import BIT
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
@@ -24,7 +26,7 @@ class Comic(Base, BaseMixin):
publisher = relationship("Publisher", back_populates="comics") publisher = relationship("Publisher", back_populates="comics")
current_order = Column(BIT(1)) current_order = Column(BIT(1))
completed = Column(BIT(1)) completed = Column(BIT(1))
issues = relationship("Issue") issues = relationship("Issue", order_by="Issue.issue_number")
story_arcs = relationship("StoryArc") story_arcs = relationship("StoryArc")
trade_paperbacks = relationship("TradePaperback") trade_paperbacks = relationship("TradePaperback")
volumes = relationship("Volume") volumes = relationship("Volume")
@@ -36,6 +38,21 @@ class Comic(Base, BaseMixin):
def __str__(self): def __str__(self):
return f'{self.title}({self.id})' return f'{self.title}({self.id})'
def get_artists(self) -> Dict[str, List[str]]:
works: Dict[str, List[str]] = {}
for work in self.comic_works:
work_type = work.work_type.name
artist = work.artist
if work_type in works:
works[work_type].append(artist)
else:
works[work_type] = [artist]
return works
def sorted_issues(self):
sorted_issues = natsorted(self.issues, key=lambda x: getattr(x, 'issue_number'))
return sorted_issues
class Volume(Base, BaseMixin): class Volume(Base, BaseMixin):
__tablename__ = "volume" __tablename__ = "volume"
@@ -77,6 +94,17 @@ class Artist(Base, BaseMixin):
name = Column(String(length=255), nullable=False) name = Column(String(length=255), nullable=False)
comic_works = relationship("ComicWork") comic_works = relationship("ComicWork")
def get_comics(self) -> Dict[str, List[str]]:
works: Dict[str, List[str]] = {}
for work in self.comic_works:
work_type = work.work_type.name
comic = work.comic
if work_type in works:
works[work_type].append(comic)
else:
works[work_type] = [comic]
return works
class WorkType(Base, BaseMixin): class WorkType(Base, BaseMixin):
__tablename__ = "worktype" __tablename__ = "worktype"
Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 B

@@ -2,14 +2,14 @@
{% block title %} {% block title %}
<title>Comic Detail</title> <title>Artist Detail</title>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<h1 class="display-5">Comic Detail</h1> <h1 class="display-5">Artist Detail</h1>
</div> </div>
</div> </div>
@@ -23,9 +23,14 @@
<tr> <tr>
<th scope="row">Works</th> <th scope="row">Works</th>
<td colspan="2"> <td colspan="2">
{% for work in artist.comic_works %} {% for work in artist.get_comics() %}
<p> <p>
{{work.work_type.name}}: <a href="/comic/comics/{{work.comic.id}}">{{work.comic.title}}</a> {{work}}:
<ul>
{% for comic in artist.get_comics()[work] %}
<li><a href="/comic/comics/{{comic.id}}">{{comic.title}}</a></li>
{% endfor %}
</ul>
</p> </p>
{% endfor %} {% endfor %}
</td> </td>
@@ -6,12 +6,7 @@
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div class="container"> <div class="container">
<div class="row">
<div class="col">
<h1 class="display-5">Comic Detail</h1>
</div>
</div>
<div class="row"> <div class="row">
<table class="table table-striped table-hover"> <table class="table table-striped table-hover">
@@ -26,17 +21,26 @@
</tr> </tr>
<tr> <tr>
<th scope="row">Completed</th> <th scope="row">Completed</th>
<td colspan="2">{{comic.completed}}</td> <td colspan="2">
{% with check=comic.completed %}
{% include "components/check.html" %}
{% endwith %}
</td>
</tr> </tr>
<tr> <tr>
<th scope="row">Works</th> <th scope="row">Works</th>
<td colspan="2"> <td colspan="2">
{% for work in comic.comic_works %} {% for work in comic.get_artists() %}
<p> <p>
{{work.work_type.name}}: <a href="/comic/artists/{{work.artist.id}}">{{work.artist.name}}</a> {{work}}:
<ul>
{% for artist in comic.get_artists()[work] %}
<li><a href="/comic/artists/{{artist.id}}">{{artist.name}}</a></li>
{% endfor %}
</ul>
</p> </p>
{% endfor %} {% endfor %}
</td> </td>
</tr> </tr>
<tr> <tr>
<th scope="row">Data Created</th> <th scope="row">Data Created</th>
@@ -46,6 +50,20 @@
<th scope="row">Data Modified</th> <th scope="row">Data Modified</th>
<td colspan="2">{{comic.last_modified_date}}</td> <td colspan="2">{{comic.last_modified_date}}</td>
</tr> </tr>
<tr>
<th scope="row">Data Version</th>
<td colspan="2">{{comic.version}}</td>
</tr>
<tr>
<th scope="row">Issues</th>
<td colspan="2">
<ul>
{% for issue in comic.sorted_issues() %}
<li><a href="comic/issues/{{issue.id}}">{{issue.issue_number}}</a></li>
{% endfor %}
</ul>
</td>
</tr>
</tbody> </tbody>
</table> </table>
</div> </div>
+1 -2
View File
@@ -19,8 +19,7 @@
<div class="col-lg-4 col-md-3 col-sm-10 mr-auto"> <div class="col-lg-4 col-md-3 col-sm-10 mr-auto">
{% with obj=comic %} {% with obj=comic %}
{% include "components/comic_cards.html" %} {% include "components/comic_cards.html" %}
{% endwith %} {% endwith %}
{% if loop.index %3 %} {% if loop.index %3 %}
</div> </div>
{% else %} {% else %}
@@ -0,0 +1,45 @@
{% extends "shared/base.html" %}
{% block title %}
<title>Publisher Detail</title>
{% endblock %}
{% block content %}
<div class="container">
<div class="row">
<div class="col">
<h1 class="display-5">Publisher Detail</h1>
</div>
</div>
<div class="row">
<table class="table table-striped table-hover">
<tbody>
<tr>
<th scope="row">Publisher Name</th>
<td colspan="2">{{publisher.name}}</td>
</tr>
<tr>
<th scope="row">Comics</th>
<td colspan="2">
<ul>
{% for comic in publisher.comics %}
<li><a href="/comic/comics/{{comic.id}}">{{comic.title}}</a></li>
{% endfor %}
</ul>
</td>
</tr>
<tr>
<th scope="row">Data Created</th>
<td colspan="2">{{publisher.created_date}}</td>
</tr>
<tr>
<th scope="row">Data Modified</th>
<td colspan="2">{{publisher.last_modified_date}}</td>
</tr>
</tbody>
</table>
</div>
</div>
{% endblock %}
@@ -0,0 +1,31 @@
{% extends "shared/base.html" %}
{% block title %}
<title>Publisher List</title>
{% endblock %}
{% block content %}
{% with msg=msg %}
{% include "components/alerts.html" %}
{% endwith %}
<div class="container">
<div class="row">
<div class="col">
<h1 class="display-5">Find Publishers..</h1>
</div>
</div>
<div class="row">
{% for publisher in publishers %}
<div class="col-lg-4 col-md-3 col-sm-10 mr-auto">
{% with obj=publisher %}
{% include "components/publisher_cards.html" %}
{% endwith %}
{% if loop.index %3 %}
</div>
{% else %}
</div></div><br><div class="row">
{% endif %}
{% endfor %}
</div>
</div>
{% endblock %}
@@ -0,0 +1,6 @@
<div class="card shadow p-3 mb-2 bg-body rounded" style="width: 18rem;">
<div class="card-body">
<h5 class="card-title">{{obj.name}}</h5>
<a href="/media/actors/{{obj.id}}" class="btn btn-primary">Read more</a>
</div>
</div>
@@ -0,0 +1,5 @@
{% if check == 1 %}
<img src="{{ url_for('static', path='images/tick.png') }}" alt="" width="24" height="24">
{% else %}
<img src="{{ url_for('static', path='images/cross.png') }}" alt="" width="24" height="24">
{% endif %}
@@ -2,7 +2,7 @@
<div class="card-body"> <div class="card-body">
<h5 class="card-title">{{obj.title}}</h5> <h5 class="card-title">{{obj.title}}</h5>
<p class="card-text">Publisher : {{obj.publisher.name}}</p> <p class="card-text">Publisher : {{obj.publisher.name}}</p>
<p class="card-text">Completed : {{obj.completed}}</p> <p class="card-text">Completed : {% with check=obj.completed %}{% include "components/check.html" %}{% endwith %}</p>
<a href="/comic/comics/{{obj.id}}" class="btn btn-primary">Read more</a> <a href="/comic/comics/{{obj.id}}" class="btn btn-primary">Read more</a>
</div> </div>
</div> </div>
@@ -16,6 +16,7 @@
<ul class="dropdown-menu" aria-labelledby="navbarDropdown"> <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
<li><a class="dropdown-item" href="/comic/comics/">Comics</a></li> <li><a class="dropdown-item" href="/comic/comics/">Comics</a></li>
<li><a class="dropdown-item" href="/comic/artists/">Artists</a></li> <li><a class="dropdown-item" href="/comic/artists/">Artists</a></li>
<li><a class="dropdown-item" href="/comic/publishers/">Publishers</a></li>
<li><hr class="dropdown-divider"></li> <li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#">Something else here</a></li> <li><a class="dropdown-item" href="#">Something else here</a></li>
</ul> </ul>
@@ -0,0 +1,6 @@
<div class="card shadow p-3 mb-2 bg-body rounded" style="width: 18rem;">
<div class="card-body">
<h5 class="card-title">{{obj.name}}</h5>
<a href="/comic/publishers/{{obj.id}}" class="btn btn-primary">Read more</a>
</div>
</div>
@@ -0,0 +1,45 @@
{% extends "shared/base.html" %}
{% block title %}
<title>Actor Detail</title>
{% endblock %}
{% block content %}
<div class="container">
<div class="row">
<div class="col">
<h1 class="display-5">Actor Detail</h1>
</div>
</div>
<div class="row">
<table class="table table-striped table-hover">
<tbody>
<tr>
<th scope="row">Actor Name</th>
<td colspan="2">{{actor.name}}</td>
</tr>
<tr>
<th scope="row">Works</th>
<td colspan="2">
<ul>
{% for media_actor_files in actor.media_actor_files %}
<li><a href="/media/files/{{media_actor_files.media_file.id}}">{{media_actor_files.media_file.title}}</a></li>
{% endfor %}
</ul>
</td>
</tr>
<tr>
<th scope="row">Data Created</th>
<td colspan="2">{{actor.created_date}}</td>
</tr>
<tr>
<th scope="row">Data Modified</th>
<td colspan="2">{{actor.last_modified_date}}</td>
</tr>
</tbody>
</table>
</div>
</div>
{% endblock %}
@@ -0,0 +1,32 @@
{% extends "shared/base.html" %}
{% block title %}
<title>MediaFile Actors</title>
{% endblock %}
{% block content %}
{% with msg=msg %}
{% include "components/alerts.html" %}
{% endwith %}
<div class="container">
<div class="row">
<div class="col">
<h1 class="display-5">Actors..</h1>
</div>
</div>
<div class="row">
{% for actor in actors %}
<div class="col-lg-4 col-md-3 col-sm-10 mr-auto">
{% with obj=actor %}
{% include "components/actor_cards.html" %}
{% endwith %}
{% if loop.index %3 %}
</div>
{% else %}
</div></div><br><div class="row">
{% endif %}
{% endfor %}
</div>
</div>
{% endblock %}
@@ -0,0 +1,65 @@
{% extends "shared/base.html" %}
{% block title %}
<title>MediaFile Detail</title>
{% endblock %}
{% block content %}
<div class="container">
<div class="row">
<div class="col">
<h1 class="display-5">MediaFile Detail</h1>
</div>
</div>
<div class="row">
<table class="table table-striped table-hover">
<tbody>
<tr>
<th scope="row">MediaFile Title</th>
<td colspan="2">{{mediafile.title}}</td>
</tr>
<tr>
<th scope="row">MediaFile URL</th>
<td colspan="2">{{mediafile.url}}</td>
</tr>
<tr>
<th scope="row">MediaFile Cloudlink</th>
<td colspan="2">{{mediafile.cloud_link}}</td>
</tr>
<tr>
<th scope="row">MediaFile Download?</th>
<td colspan="2">{{mediafile.should_download}}</td>
</tr>
<tr>
<th scope="row">MediaFile Review?</th>
<td colspan="2">{{mediafile.review}}</td>
</tr>
<tr>
<th scope="row">Actors</th>
<td colspan="2">
<ul>
{% for media_actor_files in mediafile.media_actor_files %}
<li><a href="/media/actors/{{media_actor_files.media_actor.id}}">{{media_actor_files.media_actor.name}}</a></li>
{% endfor %}
</ul>
</td>
</tr>
<tr>
<th scope="row">Data Created</th>
<td colspan="2">{{mediafile.created_date}}</td>
</tr>
<tr>
<th scope="row">Data Modified</th>
<td colspan="2">{{mediafile.last_modified_date}}</td>
</tr>
<tr>
<th scope="row">Data Version</th>
<td colspan="2">{{mediafile.version}}</td>
</tr>
</tbody>
</table>
</div>
</div>
{% endblock %}
+13 -2
View File
@@ -4,8 +4,7 @@ from fastapi import APIRouter, Request
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
from src.apis.utils import SessionDep from src.apis.utils import SessionDep
from src.db.models.comic import Comic, Artist from src.db.models.comic import Comic, Artist, Publisher
from src.schema.comics.comic import get_comic_details
templates = Jinja2Templates(directory="src/templates") templates = Jinja2Templates(directory="src/templates")
router = APIRouter(include_in_schema=False, prefix="/comic") router = APIRouter(include_in_schema=False, prefix="/comic")
@@ -29,3 +28,15 @@ def get_artists(db: SessionDep, request: Request, msg: str = None):
def artist_detail(artist_id: UUID, request: Request, db: SessionDep): def artist_detail(artist_id: UUID, request: Request, db: SessionDep):
artist = db.get(Artist, artist_id) artist = db.get(Artist, artist_id)
return templates.TemplateResponse("comic/artist_detail.html", {"request": request, "artist": artist}) return templates.TemplateResponse("comic/artist_detail.html", {"request": request, "artist": artist})
@router.get("/publishers")
def get_publishers(db: SessionDep, request: Request, msg: str = None):
publishers = db.query(Publisher).all()
return templates.TemplateResponse("comic/publishers.html", {"request": request, "publishers": publishers})
@router.get("/publishers/{publisher_id}")
def publisher_details(publisher_id: UUID, request: Request, db: SessionDep, msg: str = None):
publisher = db.get(Publisher, publisher_id)
if publisher is None:
msg = "Could not find Publisher"
return templates.TemplateResponse("comic/publisher_detail.html", {"request": request, "msg": msg, "publisher": publisher})
+2 -2
View File
@@ -27,6 +27,6 @@ def get_actors(db: SessionDep, request: Request, msg: str = None):
@router.get("/actors/{actor_id}") @router.get("/actors/{actor_id}")
def artist_detail(actor_id: UUID, request: Request, db: SessionDep): def artist_detail(actor_id: UUID, request: Request, db: SessionDep):
mediaactor = db.get(MediaActor, actor_id) actor = db.get(MediaActor, actor_id)
return templates.TemplateResponse("media/artist_detail.html", {"request": request, "mediaactor": mediaactor}) return templates.TemplateResponse("media/actor_detail.html", {"request": request, "actor": actor})
+11
View File
@@ -284,6 +284,7 @@ dependencies = [
{ name = "fastapi", extra = ["standard"] }, { name = "fastapi", extra = ["standard"] },
{ name = "httpx" }, { name = "httpx" },
{ name = "mariadb" }, { name = "mariadb" },
{ name = "natsort" },
{ name = "pathlib" }, { name = "pathlib" },
{ name = "platformdirs" }, { name = "platformdirs" },
{ name = "pytest" }, { name = "pytest" },
@@ -302,6 +303,7 @@ requires-dist = [
{ name = "fastapi", extras = ["standard"], specifier = ">=0.115.12" }, { name = "fastapi", extras = ["standard"], specifier = ">=0.115.12" },
{ name = "httpx", specifier = "==0.24.1" }, { name = "httpx", specifier = "==0.24.1" },
{ name = "mariadb", specifier = ">=1.1.12" }, { name = "mariadb", specifier = ">=1.1.12" },
{ name = "natsort", specifier = ">=8.4.0" },
{ name = "pathlib", specifier = ">=1.0.1" }, { name = "pathlib", specifier = ">=1.0.1" },
{ name = "platformdirs", specifier = ">=4.3.7" }, { name = "platformdirs", specifier = ">=4.3.7" },
{ name = "pytest", specifier = "==7.4.0" }, { name = "pytest", specifier = "==7.4.0" },
@@ -376,6 +378,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload_time = "2022-08-14T12:40:09.779Z" }, { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload_time = "2022-08-14T12:40:09.779Z" },
] ]
[[package]]
name = "natsort"
version = "8.4.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/e2/a9/a0c57aee75f77794adaf35322f8b6404cbd0f89ad45c87197a937764b7d0/natsort-8.4.0.tar.gz", hash = "sha256:45312c4a0e5507593da193dedd04abb1469253b601ecaf63445ad80f0a1ea581", size = 76575, upload_time = "2023-06-20T04:17:19.925Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ef/82/7a9d0550484a62c6da82858ee9419f3dd1ccc9aa1c26a1e43da3ecd20b0d/natsort-8.4.0-py3-none-any.whl", hash = "sha256:4732914fb471f56b5cce04d7bae6f164a592c7712e1c85f9ef585e197299521c", size = 38268, upload_time = "2023-06-20T04:17:17.522Z" },
]
[[package]] [[package]]
name = "packaging" name = "packaging"
version = "25.0" version = "25.0"