diff --git a/server/app.py b/server/app.py index deebe49..ac42a61 100644 --- a/server/app.py +++ b/server/app.py @@ -11,7 +11,7 @@ import logging import os import random from urllib.parse import urlencode, quote_plus -from typing import Any, Callable, Dict, Iterable, List, Optional, Union +from typing import Any, Callable, Dict, Iterable, List, Optional, Set, Union from flask import Flask, jsonify, make_response, request, redirect from flask.templating import render_template @@ -174,8 +174,33 @@ def timedelta(seconds: int) -> str: @flask_app.route("/") -def hello_world(): - return 'Collections & Media' +def dashboard(): + # config + pinned_limit = 10 + media_limit = 10 + # for links from pinned collections + pinned_collections: Iterable[MediaCollection] = orm.select(m for m in MediaCollection if m.pinned and not m.ignored).order_by(MediaCollection.release_date, MediaCollection.title, MediaCollection.id) + links_from_pinned_collections: List[MediaCollectionLink] = list() + episodes_from_pinned_collections: Set[MediaElement] = set() + for coll in pinned_collections: + next_link = coll.next_episode + if next_link is not None and next_link.element not in episodes_from_pinned_collections and next_link.element.can_considered: + links_from_pinned_collections.append(next_link) + episodes_from_pinned_collections.add(next_link.element) + if len(links_from_pinned_collections) >= pinned_limit: + break + # for media + media_list: Iterable[MediaElement] = orm.select(m for m in MediaElement if not (m.ignored or m.watched)).order_by(orm.desc(MediaElement.release_date), MediaElement.id) + def get_considerable(): + for element in media_list: + if element not in episodes_from_pinned_collections and element.can_considered: + yield element + # render + return render_template( + "dashboard.htm", + links_from_pinned_collections = links_from_pinned_collections, + media_list = common.limit_iter(get_considerable(), media_limit), + ) @flask_app.route("/collection") diff --git a/server/entertainment_decider/common.py b/server/entertainment_decider/common.py index 59874df..aa884a9 100644 --- a/server/entertainment_decider/common.py +++ b/server/entertainment_decider/common.py @@ -1,5 +1,6 @@ +import itertools import subprocess -from typing import Literal, Union +from typing import Iterable, List, Literal, TypeVar, Union def call(args, check=True, stdin=None) -> subprocess.CompletedProcess: proc = subprocess.run(args, capture_output=True, check=check, text=True, stdin=stdin) @@ -11,3 +12,8 @@ def update_bool_value(old_value: bool, new_value: Union[bool, Literal["toggle"]] if type(new_value) != bool: raise Exception(f"Invalid type of new_value: Expected bool or literal \"toggle\", got type={type(new_value)!r}, value={new_value!r}") return new_value + +T = TypeVar("T") + +def limit_iter(iter: Iterable[T], limit: int) -> List[T]: + return list(itertools.islice(iter, limit)) diff --git a/server/templates/dashboard.htm b/server/templates/dashboard.htm new file mode 100644 index 0000000..ba59c96 --- /dev/null +++ b/server/templates/dashboard.htm @@ -0,0 +1,23 @@ +{% import "macros.htm" as macros %} + + + {% set title = "Dashboard" %} +
+ +| Date | +To Watch | +Actions | +Title | +From Collection | +
|---|---|---|---|---|
| + {{ link.element.release_date.strftime("%d.%m.%Y") }} + | ++ {{ link.element.left_length | timedelta }} + | ++ {{ media_element_buttons(link.element) }} + | ++ {{ link.element.title }} + | ++ {{ link.collection.id }} + {{- link_position_marker(link, prefix=true) -}} + | +