new style
* new style with picocss * djlint * rate distribution * collection item drag to order * discover available for guest * search combine movie tv
This commit is contained in:
parent
cef2e0e617
commit
0ffd47ca96
163 changed files with 8699 additions and 5252 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -23,6 +23,7 @@ tox.ini
|
|||
# generated css
|
||||
/common/static/css/boofilsic.min.css
|
||||
/common/static/css/boofilsic.css
|
||||
/common/static/scss/neodb.css
|
||||
|
||||
# debug log file
|
||||
/log
|
||||
|
|
|
@ -10,3 +10,10 @@ repos:
|
|||
hooks:
|
||||
- id: black
|
||||
language_version: python3.11
|
||||
repos:
|
||||
- repo: https://github.com/Riverside-Healthcare/djLint
|
||||
rev: v1.28.0
|
||||
hooks:
|
||||
- id: djlint-reformat-django
|
||||
- id: djlint-django
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ https://docs.djangoproject.com/en/3.0/ref/settings/
|
|||
|
||||
import os
|
||||
|
||||
PROJECT_ROOT = os.path.abspath(os.path.dirname(__name__))
|
||||
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
@ -52,6 +53,7 @@ INSTALLED_APPS = [
|
|||
"django_rq",
|
||||
"django_bleach",
|
||||
"tz_detect",
|
||||
"sass_processor",
|
||||
"simple_history",
|
||||
"markdownx",
|
||||
"polymorphic",
|
||||
|
@ -210,6 +212,11 @@ STATIC_URL = "/static/"
|
|||
STATIC_ROOT = os.path.join(BASE_DIR, "static/")
|
||||
|
||||
STATICFILES_STORAGE = "django.contrib.staticfiles.storage.ManifestStaticFilesStorage"
|
||||
STATICFILES_FINDERS = [
|
||||
"django.contrib.staticfiles.finders.FileSystemFinder",
|
||||
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
|
||||
"sass_processor.finders.CssFinder",
|
||||
]
|
||||
|
||||
AUTH_USER_MODEL = "users.User"
|
||||
|
||||
|
@ -221,9 +228,9 @@ SILENCED_SYSTEM_CHECKS = [
|
|||
MEDIA_URL = "/media/"
|
||||
MEDIA_ROOT = os.path.join(BASE_DIR, "media/")
|
||||
|
||||
PROJECT_ROOT = os.path.abspath(os.path.dirname(__name__))
|
||||
SITE_INFO = {
|
||||
"site_name": "NiceDB",
|
||||
"site_url": "https://nicedb.org",
|
||||
"support_link": "https://github.com/doubaniux/boofilsic/issues",
|
||||
"social_link": "https://donotban.com/@testie",
|
||||
"donation_link": "https://patreon.com/tertius",
|
||||
|
@ -237,6 +244,7 @@ CLIENT_NAME = os.environ.get("APP_NAME", "NiceDB")
|
|||
SITE_INFO["site_name"] = os.environ.get("APP_NAME", "NiceDB")
|
||||
APP_WEBSITE = os.environ.get("APP_URL", "https://nicedb.org")
|
||||
REDIRECT_URIS = APP_WEBSITE + "/users/OAuth2_login/"
|
||||
SITE_INFO["site_url"] = APP_WEBSITE
|
||||
|
||||
|
||||
# Path to save report related images, ends with slash
|
||||
|
@ -408,3 +416,5 @@ MAINTENANCE_MODE_IGNORE_ADMIN_SITE = True
|
|||
MAINTENANCE_MODE_IGNORE_SUPERUSER = True
|
||||
MAINTENANCE_MODE_IGNORE_ANONYMOUS_USER = True
|
||||
MAINTENANCE_MODE_IGNORE_URLS = (r"^/users/connect/", r"^/users/OAuth2_login/")
|
||||
|
||||
DISCORD_WEBHOOKS = {}
|
||||
|
|
|
@ -277,9 +277,9 @@ class MockResponse:
|
|||
return json.load(StringIO(self.text))
|
||||
|
||||
def html(self):
|
||||
return html.fromstring(
|
||||
return html.fromstring( # may throw exception unexpectedly due to OS bug, see https://github.com/neodb-social/neodb/issues/5
|
||||
self.text
|
||||
) # may throw exception unexpectedly due to OS bug, see https://github.com/neodb-social/neodb/issues/5
|
||||
)
|
||||
|
||||
@property
|
||||
def headers(self):
|
||||
|
|
|
@ -8,6 +8,9 @@ from django.utils import timezone
|
|||
from django.db.models import Count
|
||||
|
||||
|
||||
MAX_GALLERY_ITEMS = 42
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "catalog app utilities"
|
||||
|
||||
|
@ -18,9 +21,21 @@ class Command(BaseCommand):
|
|||
help="generate discover data",
|
||||
)
|
||||
|
||||
def get_popular_item_ids(self, category, days):
|
||||
self.stdout.write(f"Generating popular {category} items for {days} days...")
|
||||
item_ids = [
|
||||
m["item_id"]
|
||||
for m in ShelfMember.objects.filter(query_item_category(category))
|
||||
.filter(created_time__gt=timezone.now() - timedelta(days=days))
|
||||
.values("item_id")
|
||||
.annotate(num=Count("item_id"))
|
||||
.order_by("-num")[:MAX_GALLERY_ITEMS]
|
||||
]
|
||||
return item_ids
|
||||
|
||||
def handle(self, *args, **options):
|
||||
if options["update"]:
|
||||
cache_key = "public_gallery_list"
|
||||
cache_key = "public_gallery"
|
||||
gallery_categories = [
|
||||
ItemCategory.Book,
|
||||
ItemCategory.Movie,
|
||||
|
@ -31,22 +46,19 @@ class Command(BaseCommand):
|
|||
]
|
||||
gallery_list = []
|
||||
for category in gallery_categories:
|
||||
item_ids = [
|
||||
m["item_id"]
|
||||
for m in ShelfMember.objects.filter(query_item_category(category))
|
||||
.filter(created_time__gt=timezone.now() - timedelta(days=42))
|
||||
.values("item_id")
|
||||
.annotate(num=Count("item_id"))
|
||||
.order_by("-num")[:100]
|
||||
]
|
||||
days = 14
|
||||
item_ids = []
|
||||
while len(item_ids) < MAX_GALLERY_ITEMS / 2 and days < 150:
|
||||
item_ids = self.get_popular_item_ids(category, days)
|
||||
days *= 3
|
||||
items = Item.objects.filter(id__in=item_ids)
|
||||
gallery_list.append(
|
||||
{
|
||||
"name": "popular_" + category.value,
|
||||
"title": "热门"
|
||||
+ (category.label if category != ItemCategory.Book else "图书"),
|
||||
"item_ids": item_ids,
|
||||
"items": items,
|
||||
}
|
||||
)
|
||||
cache.set(cache_key, gallery_list, timeout=None)
|
||||
|
||||
self.stdout.write(self.style.SUCCESS(f"Done."))
|
||||
|
|
|
@ -75,6 +75,16 @@ class Album(Item):
|
|||
bandcamp_album_id = jsondata.CharField(blank=True, default="", max_length=500)
|
||||
disc_count = jsondata.IntegerField(_("碟片数"), blank=True, default="", max_length=500)
|
||||
|
||||
def get_embed_link(self):
|
||||
for res in self.external_resources.all():
|
||||
if res.id_type == IdType.Bandcamp.value and res.metadata.get(
|
||||
"bandcamp_album_id"
|
||||
):
|
||||
return f"https://bandcamp.com/EmbeddedPlayer/album={res.metadata.get('bandcamp_album_id')}/size=large/bgcol=ffffff/linkcol=19A2CA/artwork=small/transparent=true/"
|
||||
if res.id_type == IdType.Spotify_Album.value:
|
||||
return res.url.replace("open.spotify.com/", "open.spotify.com/embed/")
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def lookup_id_type_choices(cls):
|
||||
id_types = [
|
||||
|
|
|
@ -16,19 +16,22 @@ class SearchResultItem:
|
|||
self, category, source_site, source_url, title, subtitle, brief, cover_url
|
||||
):
|
||||
self.category = category
|
||||
self.external_resources = {
|
||||
"all": [{"url": source_url, "site_name": {"label": source_site}}]
|
||||
}
|
||||
self.source_site = source_site
|
||||
self.source_url = source_url
|
||||
self.title = title
|
||||
self.subtitle = subtitle
|
||||
self.brief = brief
|
||||
self.cover_url = cover_url
|
||||
self.cover_image_url = cover_url
|
||||
|
||||
@property
|
||||
def verbose_category_name(self):
|
||||
return self.category.label
|
||||
|
||||
@property
|
||||
def link(self):
|
||||
def url(self):
|
||||
return f"/search?q={quote_plus(self.source_url)}"
|
||||
|
||||
@property
|
||||
|
@ -272,7 +275,7 @@ class ExternalSources:
|
|||
results = []
|
||||
if c == "" or c is None:
|
||||
c = "all"
|
||||
if c == "all" or c == "movie" or c == "tv":
|
||||
if c == "all" or c == "movietv":
|
||||
results.extend(TheMovieDatabase.search(q, page))
|
||||
if c == "all" or c == "book":
|
||||
results.extend(GoogleBooks.search(q, page))
|
||||
|
|
|
@ -236,6 +236,9 @@ class Indexer:
|
|||
def search(cls, q, page=1, category=None, tag=None, sort=None):
|
||||
f = []
|
||||
if category:
|
||||
if category == "movietv":
|
||||
f.append("category:= [movie,tv]")
|
||||
else:
|
||||
f.append("category:= " + category)
|
||||
if tag:
|
||||
f.append(f"tags:= '{tag}'")
|
||||
|
@ -254,6 +257,7 @@ class Indexer:
|
|||
|
||||
try:
|
||||
r = cls.instance().collections[INDEX_NAME].documents.search(options)
|
||||
print(r)
|
||||
results.items = list(
|
||||
[
|
||||
x
|
||||
|
|
|
@ -80,6 +80,7 @@ def fetch(request, url, is_refetch: bool = False, site: AbstractSite = None):
|
|||
"fetch_pending.html",
|
||||
{
|
||||
"site": site,
|
||||
"sites": SiteName.labels,
|
||||
"job_id": job_id,
|
||||
},
|
||||
)
|
||||
|
@ -99,6 +100,7 @@ def search(request):
|
|||
"search_results.html",
|
||||
{
|
||||
"items": None,
|
||||
"sites": SiteName.labels,
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -150,7 +152,7 @@ def search(request):
|
|||
),
|
||||
"categories": ["book", "movie", "music", "game"],
|
||||
"sites": SiteName.labels,
|
||||
"hide_category": category is not None,
|
||||
"hide_category": category is not None and category != "movietv",
|
||||
},
|
||||
)
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ _logger = logging.getLogger(__name__)
|
|||
class Bandcamp(AbstractSite):
|
||||
SITE_NAME = SiteName.Bandcamp
|
||||
ID_TYPE = IdType.Bandcamp
|
||||
URL_PATTERNS = [r"https://([a-z0-9\-]+.bandcamp.com/album/[^?#/]+)"]
|
||||
URL_PATTERN_FALLBACK = r"https://([a-z0-9\-\.]+/album/[^?#/]+)"
|
||||
URL_PATTERNS = [r"https://([a-z0-9\-]+.bandcamp.com/album/[^?#/]+).*"]
|
||||
URL_PATTERN_FALLBACK = r"https://([a-z0-9\-\.]+/album/[^?#/]+).*"
|
||||
WIKI_PROPERTY_ID = ""
|
||||
DEFAULT_MODEL = Album
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ spotify_token_expire_time = time.time()
|
|||
class Spotify(AbstractSite):
|
||||
SITE_NAME = SiteName.Spotify
|
||||
ID_TYPE = IdType.Spotify_Album
|
||||
URL_PATTERNS = [r"\w+://open\.spotify\.com/album/([a-zA-Z0-9]+)"]
|
||||
URL_PATTERNS = [r"\w+://open\.spotify\.com/album/([a-zA-Z0-9]+).*"]
|
||||
WIKI_PROPERTY_ID = "?"
|
||||
DEFAULT_MODEL = Album
|
||||
|
||||
|
|
57
catalog/static/podcast.js
Normal file
57
catalog/static/podcast.js
Normal file
|
@ -0,0 +1,57 @@
|
|||
function create_player(audio) {
|
||||
window.player = new Shikwasa.Player({
|
||||
container: () => document.querySelector('.player'),
|
||||
preload: 'metadata',
|
||||
autoplay: true,
|
||||
themeColor: getComputedStyle(document.documentElement).getPropertyValue('--pico-primary'),
|
||||
fixed: {
|
||||
type: 'fixed',
|
||||
position: 'bottom'
|
||||
},
|
||||
audio: audio
|
||||
});
|
||||
// $('.shk-title').on('click', e=>{
|
||||
// window.location = "#";
|
||||
// });
|
||||
$('.footer').attr('style', 'margin-bottom: 120px !important');
|
||||
}
|
||||
function podcast_init(context) {
|
||||
$('.episode', context).on('click', e=>{
|
||||
e.preventDefault();
|
||||
var ele = e.currentTarget;
|
||||
var album = $(ele).data('album');
|
||||
var artist = $(ele).data('hosts');
|
||||
var title = $(ele).data('title');
|
||||
var cover_url = $(ele).data('cover');
|
||||
var media_url = $(ele).data('media');
|
||||
var position = $(ele).data('position');
|
||||
if (!media_url) return;
|
||||
window.current_item_uuid = $(ele).data('uuid');
|
||||
if (!window.player) {
|
||||
create_player({
|
||||
title: title,
|
||||
cover: cover_url,
|
||||
src: media_url,
|
||||
album: album,
|
||||
artist: artist
|
||||
})
|
||||
} else {
|
||||
window.player.update({
|
||||
title: title,
|
||||
cover: cover_url,
|
||||
src: media_url,
|
||||
album: album,
|
||||
artist: artist
|
||||
})
|
||||
}
|
||||
if (position) window.player._initSeek = position;
|
||||
window.player.play()
|
||||
});
|
||||
}
|
||||
|
||||
$(function() {
|
||||
document.body.addEventListener('htmx:load', function(evt) {
|
||||
podcast_init(evt.detail.elt);
|
||||
});
|
||||
podcast_init(document.body);
|
||||
});
|
121
catalog/templates/_item_card.html
Normal file
121
catalog/templates/_item_card.html
Normal file
|
@ -0,0 +1,121 @@
|
|||
{% load humanize %}
|
||||
{% load i18n %}
|
||||
{% load highlight %}
|
||||
{% if item.get_embed_link %}
|
||||
<div class="item player">
|
||||
<h5>
|
||||
<a href="{{ item.url }}">{{ item.title }}</a>
|
||||
<small>
|
||||
{% if not hide_category %}<span class="category">[{{ item.category.label }}]</span>{% endif %}
|
||||
<span class="site-list">
|
||||
{% for res in item.external_resources.all %}
|
||||
<a href="{{ res.url }}" class="{{ res.site_name }}">{{ res.site_name.label }}</a>
|
||||
{% endfor %}
|
||||
</span>
|
||||
</small>
|
||||
</h5>
|
||||
<iframe src="{{ item.get_embed_link }}"
|
||||
frameborder="0"
|
||||
allowtransparency="true"
|
||||
allow="encrypted-media"
|
||||
style="width: 100%;
|
||||
height: 120px"></iframe>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="item">
|
||||
<div class="cover">
|
||||
<a href="{{ item.url }}">
|
||||
<img src="{{ item.cover_image_url }}" alt="cover" />
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<hgroup>
|
||||
<h5>
|
||||
<a href="{{ item.url }}">
|
||||
{% if request.GET.q %}
|
||||
{{ item.title | strip_season | highlight:request.GET.q }}
|
||||
{% else %}
|
||||
{{ item.title | strip_season }}
|
||||
{% endif %}
|
||||
</a>
|
||||
<small>
|
||||
{% if item.season_number %}第{{ item.season_number|apnumber }}季{% endif %}
|
||||
{% if item.year %}({{ item.year }}){% endif %}
|
||||
{% if not hide_category %}<span class="category">[{{ item.category.label }}]</span>{% endif %}
|
||||
<span class="site-list">
|
||||
{% for res in item.external_resources.all %}
|
||||
<a href="{{ res.url }}" class="{{ res.site_name }}">{{ res.site_name.label }}</a>
|
||||
{% endfor %}
|
||||
</span>
|
||||
</small>
|
||||
</h5>
|
||||
{% comment %}
|
||||
<span class="site-list">
|
||||
{% for res in item.external_resources.all %}
|
||||
<a href="{{ res.url }}" class="{{ res.site_name }}">{{ res.site_name.label }}</a>
|
||||
{% endfor %}
|
||||
</span>
|
||||
{% endcomment %}
|
||||
<div>
|
||||
<small>
|
||||
{% if item.subtitle %}{{ item.subtitle }}{% endif %}
|
||||
{% if item.orig_title %}
|
||||
{{ item.orig_title }}
|
||||
{% if item.season_number %}Season {{ item.season_number }}{% endif %}
|
||||
{% endif %}
|
||||
</small>
|
||||
</div>
|
||||
</hgroup>
|
||||
<div>
|
||||
<div class="metadata">
|
||||
{% if item.rating %}
|
||||
{{ item.rating | floatformat:1 }}分
|
||||
{% else %}
|
||||
{% endif %}
|
||||
{% include '_people.html' with people=item.author role='' max=2 %}
|
||||
{% include '_people.html' with people=item.translator role='' max=2 %}
|
||||
{% include '_people.html' with people=item.director role='' max=2 %}
|
||||
{% include '_people.html' with people=item.hosts role='' max=2 %}
|
||||
{% include '_people.html' with people=item.artist role='' max=2 %}
|
||||
{% include '_people.html' with people=item.developer role='' max=2 %}
|
||||
{% if item.pub_house %}/ {{ item.pub_house }}{% endif %}
|
||||
{% if item.pub_year %}
|
||||
/ {{ item.pub_year }}{% trans '年' %}
|
||||
{% if item.pub_month %}
|
||||
{{ item.pub_month }}{% trans '月' %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if item.release_date %}/ {{ item.release_date }}{% endif %}
|
||||
{% include '_people.html' with people=item.genre role='' max=10 %}
|
||||
{% include '_people.html' with people=item.platform role='' max=10 %}
|
||||
</div>
|
||||
<div class="brief">
|
||||
{% if item.actor %}
|
||||
{% include '_people.html' with people=item.actor role='主演' max=2 %}
|
||||
<br>
|
||||
{% endif %}
|
||||
{% if item.other_title %}
|
||||
{% include '_people.html' with people=item.other_title role='又名' max=2 %}
|
||||
<br>
|
||||
{% endif %}
|
||||
{% if request.GET.q %}
|
||||
{{ item.brief | linebreaksbr | highlight:request.GET.q }}
|
||||
{% else %}
|
||||
{{ item.brief | linebreaksbr }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if show_tags %}
|
||||
<div class="tag-list">
|
||||
{% for tag in item.tags %}
|
||||
{% if forloop.counter <= 5 %}
|
||||
<span>
|
||||
<a href="{% url 'catalog:search' %}?tag={{ tag }}">{{ tag }}</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
11
catalog/templates/_people.html
Normal file
11
catalog/templates/_people.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
{% if people %}
|
||||
{% if role %}{{ role }}:{% endif %}
|
||||
{% for p in people %}
|
||||
{% if forloop.counter <= max %}
|
||||
{% if not forloop.first %}、{% endif %}
|
||||
<span>{{ p }}</span>
|
||||
{% elif forloop.last %}
|
||||
等
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
|
@ -10,20 +10,11 @@
|
|||
{% load strip_scheme %}
|
||||
{% load thumb %}
|
||||
{% load duration %}
|
||||
|
||||
<!-- class specific details -->
|
||||
{% block details %}
|
||||
<div class="entity-detail__fields">
|
||||
<div class="entity-detail__rating">
|
||||
{% if item.rating and item.rating_count >= 5 %}
|
||||
<span class="entity-detail__rating-star rating-star" data-rating-score="{{ item.rating | floatformat:"0" }}"></span>
|
||||
<span class="entity-detail__rating-score"> {{ item.rating | floatformat:1 }} </span>
|
||||
<small>({{ item.rating_count }}人评分)</small>
|
||||
{% else %}
|
||||
<span> {% trans '评分:评分人数不足' %}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>{% if item.artist %}{% trans '艺术家:' %}
|
||||
<div>
|
||||
{% if item.artist %}
|
||||
{% trans '艺术家:' %}
|
||||
{% for artist in item.artist %}
|
||||
<span {% if forloop.counter > 5 %}style="display: none;"{% endif %}>
|
||||
<span class="artist">{{ artist }}</span>
|
||||
|
@ -39,10 +30,14 @@
|
|||
});
|
||||
$(this).remove();
|
||||
})
|
||||
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endif %}</div>
|
||||
<div>{% if item.company %}{% trans '发行方:' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.company %}
|
||||
{% trans '发行方:' %}
|
||||
{% for company in item.company %}
|
||||
<span {% if forloop.counter > 5 %}style="display: none;"{% endif %}>
|
||||
<span class="company">{{ company }}</span>
|
||||
|
@ -58,66 +53,77 @@
|
|||
});
|
||||
$(this).remove();
|
||||
})
|
||||
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endif %}</div>
|
||||
<div>{% if item.release_date %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.release_date %}
|
||||
{% trans '发行日期:' %}{{ item.release_date }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>{% if item.duration %}
|
||||
<div>
|
||||
{% if item.duration %}
|
||||
{% trans '时长:' %}{{ item.duration|duration_format:1000 }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>{% if item.genre %}
|
||||
<div>
|
||||
{% if item.genre %}
|
||||
{% trans '流派:' %}
|
||||
{% for genre in item.genre %}
|
||||
<span>{{ genre }}</span>{% if not forloop.last %} / {% endif %}
|
||||
<span>{{ genre }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>{% if item.barcode %}
|
||||
<div>
|
||||
{% if item.barcode %}
|
||||
{% trans '条形码:' %}{{ item.barcode }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="entity-detail__fields">
|
||||
<div>{% if item.other_title %}
|
||||
<div>
|
||||
{% if item.other_title %}
|
||||
{% trans '又名:' %}
|
||||
{% for t in item.other_title %}
|
||||
<span>{{ t }}</span>{% if not forloop.last %} / {% endif %}
|
||||
<span>{{ t }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>{% if item.album_type %}
|
||||
<div>
|
||||
{% if item.album_type %}
|
||||
{% trans '专辑类型:' %}{{ item.album_type }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>{% if item.media %}
|
||||
<div>
|
||||
{% if item.media %}
|
||||
{% trans '介质:' %}{{ item.media }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>{% if item.disc_count %}
|
||||
<div>
|
||||
{% if item.disc_count %}
|
||||
{% trans '碟片数:' %}{{ item.disc_count }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if item.last_editor and item.last_editor.preference.show_last_edit %}
|
||||
<div>{% trans '最近编辑者:' %}<a href="{% url 'journal:user_profile' item.last_editor.mastodon_username %}">{{ item.last_editor | default:"" }}</a></div>
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
{% if user.is_authenticated %}
|
||||
<a href="{% url 'catalog:edit' item.url_path item.uuid %}">{% trans '编辑' %}{{ item.demonstrative }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
<!-- class specific sidebar -->
|
||||
{% block sidebar %}
|
||||
{% block content %}
|
||||
{% if item.track_list %}
|
||||
<section>
|
||||
<h5>曲目</h5>
|
||||
<p class="tldr" _="on click toggle .tldr on me">{{ item.track_list | linebreaksbr }}</p>
|
||||
</section>
|
||||
{% endif %}
|
||||
{% if item.get_embed_link %}
|
||||
<iframe src="{{ item.get_embed_link }}" height="320" frameborder="0" allowtransparency="true" allow="encrypted-media"></iframe>
|
||||
<section>
|
||||
<h5>播放</h5>
|
||||
<iframe src="{{ item.get_embed_link }}"
|
||||
frameborder="0"
|
||||
allowtransparency="true"
|
||||
allow="encrypted-media"
|
||||
style="width: 100%;
|
||||
height: 50vh"></iframe>
|
||||
</section>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -4,87 +4,110 @@
|
|||
{% load mastodon %}
|
||||
{% load oauth_token %}
|
||||
{% load truncate %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<html lang="en" class="content-page">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ site_name }} - {% if form.instance.id %}{% trans '编辑' %} {{ form.instance.title }} {% else %}{% trans '添加' %}{% endif %}</title>
|
||||
{% include "common_libs.html" with jquery=0 %}
|
||||
<title>{{ site_name }} -
|
||||
{% if form.instance.id %}
|
||||
{% trans '编辑' %} {{ form.instance.title }}
|
||||
{% else %}
|
||||
{% trans '添加' %}
|
||||
{% endif %}
|
||||
</title>
|
||||
{% include "common_libs.html" with jquery=0 v2=1 %}
|
||||
<style>
|
||||
aside details {
|
||||
margin-bottom: 1rem;
|
||||
padding: 1rem;
|
||||
border: var(--pico-muted-color) solid 1px;
|
||||
}
|
||||
aside summary {
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
}
|
||||
main>div {
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="page-wrapper">
|
||||
<div id="content-wrapper">
|
||||
{% include "partial/_navbar.html" %}
|
||||
|
||||
<section id="content" class="container">
|
||||
{% include "_header.html" %}
|
||||
<main>
|
||||
<div class="grid__main">
|
||||
<form action="{{ submit_url }}" method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form.media }}
|
||||
{{ form }}
|
||||
<div class="grid">
|
||||
<div style="float:right;padding-left:16px">
|
||||
<input type="submit" value="{% trans '保存' %}">
|
||||
<input type="reset" value="{% trans '返回' %}" onclick="history.go(-1);">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<aside class="grid__aside">
|
||||
<h5>进阶编辑选项</h5>
|
||||
{% if item %}
|
||||
<div class="aside-section-wrapper">
|
||||
{% for res in form.instance.external_resources.all %}
|
||||
<div class="action-panel">
|
||||
<div class="action-panel__label">{% trans '源网站' %}: <a href="{{ res.url }}">{{ res.site_name.label }}</a></div>
|
||||
<div class="action-panel__button-group">
|
||||
<details>
|
||||
<summary>
|
||||
{% trans '源网站' %}: <a href="{{ res.url }}">{{ res.site_name.label }}</a>
|
||||
</summary>
|
||||
<div class="grid">
|
||||
<form method="post" action="{% url 'catalog:refetch' %}">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="id" value="{{ res.id }}">
|
||||
<input type="hidden" name="url" value="{{ res.url }}">
|
||||
<input class="button" type="submit" value="{% trans '重新抓取' %}">
|
||||
<input class="secondary" type="submit" value="{% trans '重新抓取' %}">
|
||||
</form>
|
||||
</div>
|
||||
{% if request.user.is_staff %}
|
||||
<div class="action-panel__button-group">
|
||||
<form method="post" action="{% url 'catalog:unlink' %}">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="id" value="{{ res.id }}">
|
||||
<input class="button" type="submit" value="{% trans '取消关联' %}">
|
||||
<input class="contrast" type="submit" value="{% trans '取消关联' %}">
|
||||
</form>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</details>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% if item.class_name == "movie" or item.class_name == "tvshow" %}
|
||||
<div class="aside-section-wrapper">
|
||||
<div class="action-panel">
|
||||
<div class="action-panel__label">{% trans '切换分类' %} </div>
|
||||
<div class="action-panel__button-group">
|
||||
<form method="post" action="{% url 'catalog:recast' item.url_path item.uuid %}" onsubmit="return confirm('确认切换吗?');">
|
||||
<details>
|
||||
<summary>{% trans '切换分类' %}</summary>
|
||||
<form method="post"
|
||||
action="{% url 'catalog:recast' item.url_path item.uuid %}"
|
||||
onsubmit="return confirm('确认切换吗?');">
|
||||
{% csrf_token %}
|
||||
{% if item.class_name == "movie" %}
|
||||
<input type="hidden" value="tvshow" name="class">
|
||||
<input class="button" type="submit" value="{% trans '更改为剧集' %}">
|
||||
<input class="contrast" type="submit" value="{% trans '更改为剧集' %}">
|
||||
{% endif %}
|
||||
{% if item.class_name == "tvshow" %}
|
||||
<input type="hidden" value="movie" name="class">
|
||||
<input class="button" type="submit" value="{% trans '更改为电影' %}">
|
||||
<input class="contrast" type="submit" value="{% trans '更改为电影' %}">
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
{% endif %}
|
||||
|
||||
<div class="aside-section-wrapper">
|
||||
<div class="action-panel">
|
||||
{% if item.class_name == "tvseason" %}
|
||||
{% if not item.show or request.user.is_superuser %}
|
||||
<div class="action-panel__label">{% trans '将本季关联到电视剧' %} </div>
|
||||
<div class="action-panel__button-group">
|
||||
<form method="post" action="{% url 'catalog:assign_parent' item.url_path item.uuid %}" onsubmit="return confirm('本操作不可撤销。确认关联吗?');">
|
||||
<details>
|
||||
<summary>{% trans '将本季关联到电视剧' %}</summary>
|
||||
<form method="post"
|
||||
action="{% url 'catalog:assign_parent' item.url_path item.uuid %}"
|
||||
onsubmit="return confirm('本操作不可撤销。确认关联吗?');">
|
||||
{% csrf_token %}
|
||||
<input type="url" name="parent_item_url" placeholder="目标条目URL" value="{{ item.show.absolute_url }}" required><br>
|
||||
<input class="button" type="submit" value="{% trans '提交' %}">
|
||||
<input type="url"
|
||||
name="parent_item_url"
|
||||
placeholder="目标条目URL"
|
||||
value="{{ item.show.absolute_url }}"
|
||||
required>
|
||||
<br>
|
||||
<input class="contrast" type="submit" value="{% trans '提交' %}">
|
||||
</form>
|
||||
</div>
|
||||
</details>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if item.is_deleted and not request.user.is_superuser %}
|
||||
<i>条目已被删除</i>
|
||||
{% elif item.merged_to_item and not request.user.is_superuser %}
|
||||
|
@ -92,45 +115,37 @@
|
|||
{% elif not item.deletable and not request.user.is_superuser %}
|
||||
<i>条目已被用户标记过</i>
|
||||
{% else %}
|
||||
<div class="action-panel__label">{% trans '合并到另一条目' %} </div>
|
||||
<div class="action-panel__button-group">
|
||||
<form method="post" action="{% url 'catalog:merge' item.url_path item.uuid %}" onsubmit="return confirm('本操作不可撤销。确认合并吗?');">
|
||||
<details>
|
||||
<summary>{% trans '合并到另一条目' %}</summary>
|
||||
<form method="post"
|
||||
action="{% url 'catalog:merge' item.url_path item.uuid %}"
|
||||
onsubmit="return confirm('本操作不可撤销。确认合并吗?');">
|
||||
{% csrf_token %}
|
||||
<input type="url" name="new_item_url" placeholder="目标条目URL" value="{{ item.merged_to_item.absolute_url }}" required><br>
|
||||
<input class="button" type="submit" value="{% trans '提交' %}">
|
||||
<input type="url"
|
||||
name="new_item_url"
|
||||
placeholder="目标条目URL"
|
||||
value="{{ item.merged_to_item.absolute_url }}"
|
||||
required>
|
||||
<br>
|
||||
<input class="contrast" type="submit" value="{% trans '提交' %}">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="action-panel__label">{% trans '删除' %} </div>
|
||||
<div class="action-panel__button-group">
|
||||
<form method="post" action="{% url 'catalog:delete' item.url_path item.uuid %}" onsubmit="return confirm('本操作不可撤销。确认删除吗?');">
|
||||
</details>
|
||||
<details>
|
||||
<summary>{% trans '删除' %}</summary>
|
||||
<form method="post"
|
||||
action="{% url 'catalog:delete' item.url_path item.uuid %}"
|
||||
onsubmit="return confirm('本操作不可撤销。确认删除吗?');">
|
||||
{% csrf_token %}
|
||||
<input class="button" type="submit"
|
||||
{% if item.is_deleted or item.merged_to_item %} disabled {% endif %} value="{% trans '提交' %}">
|
||||
<input class="contrast"
|
||||
type="submit"
|
||||
{% if item.is_deleted or item.merged_to_item %}disabled{% endif %}
|
||||
value="{% trans '提交' %}">
|
||||
</form>
|
||||
</div>
|
||||
</details>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="single-section-wrapper" id="main">
|
||||
<form class="entity-form" action="{{ submit_url }}" method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form.media }}
|
||||
{{ form }}
|
||||
<hr/>
|
||||
<input class="button" type="submit" value="{% trans '提交' %}">
|
||||
<a href="{{ item.url | default:'javascript:history.go(-1)' }}" style="float:right;">返回</a>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
</aside>
|
||||
</main>
|
||||
{% include "partial/_footer.html" %}
|
||||
</div>
|
||||
</body>
|
||||
|
||||
|
||||
</html>
|
||||
|
|
|
@ -1,21 +1,13 @@
|
|||
{% load static %}
|
||||
{% load sass_tags %}
|
||||
{% load tz_detect %}
|
||||
{% if request.user.is_authenticated %}
|
||||
{% tz_detect %}
|
||||
{% if sentry_dsn %}
|
||||
<script src="https://browser.sentry-cdn.com/7.7.0/bundle.min.js"></script>
|
||||
<script>
|
||||
if (window.Sentry) Sentry.init({
|
||||
dsn: "{{ sentry_dsn }}",
|
||||
release: "{{ version_hash }}",
|
||||
environment: "{{ settings_module }}",
|
||||
tracesSampleRate: 1.0,
|
||||
});
|
||||
</script>
|
||||
{% endif %}
|
||||
{% if jquery %}
|
||||
<script src="https://cdn.staticfile.org/jquery/3.6.3/jquery.min.js"></script>
|
||||
{% else %}
|
||||
<script src="https://cdn.staticfile.org/cash/8.1.3/cash.min.js"></script>
|
||||
<script src="https://cdn.staticfile.org/cash/8.1.5/cash.min.js"></script>
|
||||
{% endif %}
|
||||
<script type="text/javascript">
|
||||
if (!$.fn.is_visible) $.fn.is_visible = function () {
|
||||
|
@ -29,14 +21,18 @@
|
|||
return this;
|
||||
};
|
||||
</script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/htmx/1.8.5/htmx.min.js"></script>
|
||||
<script src="https://cdn.staticfile.org/htmx/1.9.2/htmx.min.js"></script>
|
||||
<script src="{% static 'lib/js/hyperscript-0.9.7.min.js' %}"></script>
|
||||
<script src="{% static 'lib/js/rating-star.js' %}"></script>
|
||||
<link rel="stylesheet" href="{% static 'css/boofilsic.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'lib/css/rating-star.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'lib/css/collection.css' %}">
|
||||
<link rel="search" type="application/opensearchdescription+xml" title="{{ site_name }}" href="{% static 'opensearch.xml' %}">
|
||||
<script src="{% static 'catalog.js' %}"></script>
|
||||
<script src="{% static 'lib/js/tag-input.js' %}"></script>
|
||||
<link href="{% static 'lib/css/tag-input.css' %}" type="text/css" media="all" rel="stylesheet">
|
||||
<link href="{% static 'fontawesomefree/css/all.min.css' %}" rel="stylesheet" type="text/css">
|
||||
<link rel="stylesheet"
|
||||
href="https://unpkg.com/@picocss/pico@next/css/pico.min.css" />
|
||||
<link href="{% sass_src 'scss/neodb.scss' %}"
|
||||
rel="stylesheet"
|
||||
type="text/css" />
|
||||
<link href="{% static 'fontawesomefree/css/all.min.css' %}"
|
||||
rel="stylesheet"
|
||||
type="text/css">
|
||||
<link rel="search"
|
||||
type="application/opensearchdescription+xml"
|
||||
title="{{ site_name }}"
|
||||
href="{% static 'opensearch.xml' %}">
|
||||
|
|
|
@ -6,62 +6,62 @@
|
|||
{% load truncate %}
|
||||
{% load thumb %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<html lang="en" class="classic-page">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta property="og:title" content="{{ site_name }} - 联邦宇宙书影音游戏标注平台">
|
||||
<meta name="description"
|
||||
property="og:description"
|
||||
content="{{ site_name }}致力于为联邦宇宙居民提供一个自由、开放、互联的书籍、电影、音乐和游戏收藏评论空间">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="{{ site_url }}">
|
||||
<meta property="og:image"
|
||||
content="{{ request.scheme }}://{{ request.get_host }}{% static 'img/logo_square.jpg' %}">
|
||||
<meta property="og:site_name" content="{{ site_name }}">
|
||||
<title>{{ site_name }} - {% trans '发现' %}</title>
|
||||
<link rel="alternate" type="application/rss+xml" title="{{ site_name }} - {{ user.mastodon_username }}的评论" href="{{ request.build_absolute_uri }}feed/reviews/">
|
||||
|
||||
{% include "common_libs.html" with jquery=0 %}
|
||||
<script src="{% static 'js/mastodon.js' %}" defer></script>
|
||||
<script src="{% static 'js/home.js' %}" defer></script>
|
||||
<link rel="alternate"
|
||||
type="application/rss+xml"
|
||||
title="{{ site_name }} - {{ user.mastodon_username }}的评论"
|
||||
href="{{ request.build_absolute_uri }}feed/reviews/">
|
||||
{% include "common_libs.html" with jquery=0 v2=1 %}
|
||||
<script src="https://cdn.jsdelivr.net/npm/shikwasa@2.2.1/dist/shikwasa.min.js"></script>
|
||||
<link href="https://cdn.jsdelivr.net/npm/shikwasa@2.2.1/dist/style.min.css"
|
||||
rel="stylesheet"></link>
|
||||
<script src="{% static 'podcast.js' %}"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="page-wrapper">
|
||||
<div id="content-wrapper">
|
||||
{% include "partial/_navbar.html" with current="discover" %}
|
||||
|
||||
<section id="content">
|
||||
<div class="grid grid--reverse-order">
|
||||
<div class="grid__main grid__main--reverse-order">
|
||||
|
||||
<div class="main-section-wrapper sortable">
|
||||
|
||||
{% include "_header.html" with current="discover" %}
|
||||
<main>
|
||||
<div class="grid__main">
|
||||
<div class="sortable">
|
||||
{% for gallery in gallery_list %}
|
||||
<div class="entity-sort" id="{{ gallery.name }}" {% if not gallery.items %}style="display:none;"{% endif %}>
|
||||
<h5 class="entity-sort__label">
|
||||
{{ gallery.title }}
|
||||
</h5>
|
||||
<ul class="entity-sort__entity-list">
|
||||
<section class="entity-sort shelf"
|
||||
id="{{ gallery.name }}"
|
||||
{% if not gallery.items %}style="display:none;"{% endif %}>
|
||||
<h5>{{ gallery.title }}</h5>
|
||||
<ul class="cards">
|
||||
{% for item in gallery.items %}
|
||||
<li class="entity-sort__entity">
|
||||
<a href="{{ item.url }}">
|
||||
<img src="{{ item.cover_image_url | default:item.cover.url }}" alt="{{ item.title }}" class="entity-sort__entity-img">
|
||||
<div class="entity-sort__entity-name" title="{{ item.title }}"> {{ item.title }}</div>
|
||||
<li class="card">
|
||||
<a href="{{ item.url }}" title="{{ item.title }}">
|
||||
<img src="{{ item.cover|thumb:'normal' }}"
|
||||
alt="{{ item.title }}"
|
||||
loading="lazy">
|
||||
<div class="card-title">{{ item.title }}</div>
|
||||
</a>
|
||||
</li>
|
||||
{% empty %}
|
||||
<div>暂无记录</div>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
|
||||
{% if user == request.user %}
|
||||
|
||||
{% if request.user.is_authenticated %}
|
||||
<div class="entity-sort-control">
|
||||
<div class="entity-sort-control__button" id="sortEditButton">
|
||||
<span class="entity-sort-control__text" id="sortEditText">
|
||||
{% trans '编辑布局' %}
|
||||
</span>
|
||||
<span class="entity-sort-control__text" id="sortSaveText" style="display: none;">
|
||||
{% trans '保存' %}
|
||||
</span>
|
||||
<span class="entity-sort-control__text" id="sortEditText">{% trans '编辑布局' %}</span>
|
||||
<span class="entity-sort-control__text"
|
||||
id="sortSaveText"
|
||||
style="display: none">{% trans '保存' %}</span>
|
||||
<span class="icon-edit" id="sortEditIcon">
|
||||
<i class="fa-solid fa-pencil"></i>
|
||||
</span>
|
||||
|
@ -69,29 +69,26 @@
|
|||
<i class="fa-regular fa-floppy-disk"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="entity-sort-control__button" id="sortExitButton" style="display: none;">
|
||||
<span class="entity-sort-control__text">
|
||||
{% trans '取消' %}
|
||||
</span>
|
||||
<div class="entity-sort-control__button"
|
||||
id="sortExitButton"
|
||||
style="display: none">
|
||||
<span class="entity-sort-control__text">{% trans '取消' %}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="entity-sort-control__button entity-sort-control__button--float-right" id="toggleDisplayButtonTemplate" style="display: none;">
|
||||
<span class="showText" style="display: none;">
|
||||
{% trans '显示' %}
|
||||
</span>
|
||||
<span class="hideText" style="display: none;">
|
||||
{% trans '隐藏' %}
|
||||
</span>
|
||||
<div class="entity-sort-control__button entity-sort-control__button--float-right"
|
||||
id="toggleDisplayButtonTemplate"
|
||||
style="display: none">
|
||||
<span class="showText" style="display: none;">{% trans '显示' %}</span>
|
||||
<span class="hideText" style="display: none;">{% trans '隐藏' %}</span>
|
||||
</div>
|
||||
<form action="{% url 'users:set_layout' %}" method="post" id="sortForm">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="name" value="discover">
|
||||
<input type="hidden" name="layout">
|
||||
</form>
|
||||
<script src="https://cdn.staticfile.org/html5sortable/0.13.3/html5sortable.min.js" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.staticfile.org/html5sortable/0.13.3/html5sortable.min.js"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="{% static 'js/sort_layout.js' %}"></script>
|
||||
{% endif %}
|
||||
|
||||
{{ layout|json_script:"layout-data" }}
|
||||
<script>
|
||||
const initialLayoutData = JSON.parse(document.getElementById('layout-data').textContent);
|
||||
|
@ -103,21 +100,17 @@
|
|||
$('#' + elem.id).hide();
|
||||
}
|
||||
// order
|
||||
$('#' + elem.id).appendTo('.main-section-wrapper');
|
||||
$('#' + elem.id).appendTo('.sortable');
|
||||
});
|
||||
</script>
|
||||
|
||||
</div>
|
||||
|
||||
{% include "partial/_sidebar.html" %}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
{% include "partial/_footer.html" %}
|
||||
</div>
|
||||
|
||||
{% if request.user.unread_announcements %}
|
||||
{% include "partial/_announcement.html" %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if request.user.is_authenticated %}
|
||||
{% include "_sidebar.html" with show_progress=1 %}
|
||||
{% else %}
|
||||
{% include "partial/_sidebar_anonymous.html" %}
|
||||
{% endif %}
|
||||
</main>
|
||||
{% include "partial/_footer.html" %}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -9,105 +9,153 @@
|
|||
{% load truncate %}
|
||||
{% load strip_scheme %}
|
||||
{% load thumb %}
|
||||
|
||||
{% block head %}
|
||||
{% if item.author %}
|
||||
<meta property="og:book:author" content="{% for author in item.author %}{{ author }}{% if not forloop.last %},{% endif %}{% endfor %}">
|
||||
{% endif %}
|
||||
{% if item.isbn %}
|
||||
<meta property="og:book:isbn" content="{{ item.isbn }}">
|
||||
<meta property="og:book:author"
|
||||
content="{% for author in item.author %}{{ author }}{% if not forloop.last %},{% endif %}{% endfor %}">
|
||||
{% endif %}
|
||||
{% if item.isbn %}<meta property="og:book:isbn" content="{{ item.isbn }}">{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block details %}
|
||||
<div class="entity-detail__fields">
|
||||
<div class="entity-detail__rating">
|
||||
{% if item.rating %}
|
||||
<span class="entity-detail__rating-star rating-star" data-rating-score="{{ item.rating | floatformat:0 }}"></span>
|
||||
<span class="entity-detail__rating-score"> {{ item.rating | floatformat:1 }} </span>
|
||||
<small>({{ item.rating_count }}人评分)</small>
|
||||
{% else %}
|
||||
<span> {% trans '评分:评分人数不足' %}</span>
|
||||
<!-- <div>{% if item.subtitle %}{% trans '副标题:' %}{{ item.subtitle }}{% endif %}</div>
|
||||
<div>{% if item.orig_title %}{% trans '原作名:' %}{{ item.orig_title }}{% endif %}</div> -->
|
||||
<div>
|
||||
{% if item.isbn %}
|
||||
{% trans 'ISBN:' %}{{ item.isbn }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>{% if item.subtitle %}{% trans '副标题:' %}{{ item.subtitle }}{% endif %}</div>
|
||||
<div>{% if item.isbn %}{% trans 'ISBN:' %}{{ item.isbn }}{% endif %}</div>
|
||||
<div>{% if item.author %}{% trans '作者:' %}
|
||||
<div>
|
||||
{% if item.author %}
|
||||
{% trans '作者:' %}
|
||||
{% for author in item.author %}
|
||||
<span>{{ author }}</span>{% if not forloop.last %} / {% endif %}
|
||||
<span>{{ author }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if item.pub_house %}{% trans '出版社:' %}{{ item.pub_house }}{% endif %}</div>
|
||||
<div>{% if item.orig_title %}{% trans '原作名:' %}{{ item.orig_title }}{% endif %}</div>
|
||||
<div>{% if item.translator %}{% trans '译者:' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.translator %}
|
||||
{% trans '译者:' %}
|
||||
{% for translator in item.translator %}
|
||||
<span>{{ translator }}</span>{% if not forloop.last %} / {% endif %}
|
||||
<span>{{ translator }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{%if item.pub_year %}{% trans '出版时间:' %}{{ item.pub_year }}{% trans '年' %}{% if item.pub_month %}{{ item.pub_month }}{% trans '月' %}{% endif %}{% endif %}</div>
|
||||
<div>{% if item.series %}{% trans '丛书系列:' %}{{ item.series }}{% endif %}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.pub_house %}
|
||||
{% trans '出版社:' %}{{ item.pub_house }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.imprint %}
|
||||
{% trans '出品方:' %}{{ item.imprint }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.pub_year %}
|
||||
{% trans '出版时间:' %}{{ item.pub_year }}{% trans '年' %}
|
||||
{% if item.pub_month %}
|
||||
{{ item.pub_month }}{% trans '月' %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.series %}
|
||||
{% trans '丛书系列:' %}{{ item.series }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.language %}
|
||||
{% trans '语言:' %}{{ item.language }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.binding %}
|
||||
{% trans '装帧:' %}{{ item.binding }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.price %}
|
||||
{% trans '定价:' %}{{ item.price }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.pages %}
|
||||
{% trans '页数:' %}{{ item.pages }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="entity-detail__fields">
|
||||
<div>{% if item.language %}{% trans '语言:' %}{{ item.language }}{% endif %}</div>
|
||||
<div>{% if item.binding %}{% trans '装帧:' %}{{ item.binding }}{% endif %}</div>
|
||||
<div>{% if item.price %}{% trans '定价:' %}{{ item.price }}{% endif %}</div>
|
||||
<div>{% if item.pages %}{% trans '页数:' %}{{ item.pages }}{% endif %}</div>
|
||||
<div>{% if item.imprint %}{% trans '出品方:' %}{{ item.imprint }}{% endif %}</div>
|
||||
{% if item.other_info %}
|
||||
{% for k, v in item.other_info.items %}
|
||||
<div>
|
||||
{{ k }}:{{ v | urlize }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% for k, v in item.other_info.items %}<div>{{ k }}:{{ v|urlizetrunc:24 }}</div>{% endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
{% if item.contents %}
|
||||
<section>
|
||||
<h5>目录</h5>
|
||||
<p class="tldr" _="on click toggle .tldr on me">{{ item.contents | linebreaksbr }}</p>
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if item.last_editor and item.last_editor.preference.show_last_edit %}
|
||||
<div>{% trans '最近编辑者:' %}<a href="{% url 'journal:user_profile' item.last_editor.mastodon_username %}">{{ item.last_editor | default:"" }}</a></div>
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
{% if user.is_authenticated %}
|
||||
<a href="{% url 'catalog:edit' item.url_path item.uuid %}">{% trans '编辑' %}{{ item.demonstrative }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block sidebar %}
|
||||
{% with related_books=item.get_related_books %}
|
||||
{% if related_books.count > 0 %}
|
||||
<div class="aside-section-wrapper">
|
||||
<div class="action-panel">
|
||||
<div class="action-panel__label">{% trans '其它版本' %}</div>
|
||||
<div >
|
||||
<section>
|
||||
<h5>{% trans '其它版本' %}</h5>
|
||||
{% for b in related_books %}
|
||||
<p>
|
||||
<a href="{{ b.url }}">{{ b.title }}</a>
|
||||
<small>({{ b.pub_house | default:'' }} {{ b.pub_year | default:'' }})</small>
|
||||
{% for res in b.external_resources.all %}
|
||||
{% comment %} {% for res in b.external_resources.all %}
|
||||
<a href="{{ res.url }}">
|
||||
<span class="source-label source-label__{{ res.site_name }}">{{ res.site_name.label }}</span>
|
||||
</a>
|
||||
{% endfor %}
|
||||
{% endfor %} {% endcomment %}
|
||||
</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
{% if item.isbn %}
|
||||
<div class="aside-section-wrapper">
|
||||
<section>
|
||||
<div class="action-panel">
|
||||
<div class="action-panel__label">{% trans '借阅或购买' %}</div>
|
||||
<div class="action-panel__button-group">
|
||||
<a class="action-panel__button" target="_blank" rel="noopener" href="https://www.worldcat.org/isbn/{{ item.isbn }}">{% trans 'WorldCat' %}</a>
|
||||
<a class="action-panel__button" target="_blank" rel="noopener" href="https://openlibrary.org/search?isbn={{ item.isbn }}">{% trans 'Open Library' %}</a>
|
||||
</div>
|
||||
<h5>{% trans '借阅或购买' %}</h5>
|
||||
<div>
|
||||
<ul>
|
||||
<li>
|
||||
<a target="_blank"
|
||||
rel="noopener"
|
||||
href="https://www.worldcat.org/isbn/{{ item.isbn }}">WorldCat</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank"
|
||||
rel="noopener"
|
||||
href="https://openlibrary.org/search?isbn={{ item.isbn }}">Open Library</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank"
|
||||
rel="noopener"
|
||||
href="https://library.oapen.org/discover?filtertype_1=isbn&filter_relational_operator_1=equals&filter_1={{ item.isbn }}">
|
||||
OAPEN</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank"
|
||||
rel="noopener"
|
||||
href="https://bookshop.org/search?keywords={{ item.isbn }}">Bookshop.org</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank"
|
||||
rel="noopener"
|
||||
href="https://www.amazon.com/s?k={{ item.isbn }}">Amazon</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank"
|
||||
rel="noopener"
|
||||
href="https://www.duozhuayu.com/search/book/{{ item.isbn }}">多抓鱼</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -8,17 +8,14 @@
|
|||
{% load truncate %}
|
||||
{% load strip_scheme %}
|
||||
{% load thumb %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<script src="https://cdn.staticfile.org/cash/8.1.3/cash.min.js"></script>
|
||||
{% block head %}
|
||||
{% endblock %}
|
||||
{% block head %}{% endblock %}
|
||||
<title>{{ site_name }} - {% trans item.category.label %} | {{ item.title }}</title>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
<body></body>
|
||||
</html>
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
{% load truncate %}
|
||||
{% load strip_scheme %}
|
||||
{% load thumb %}
|
||||
|
||||
{% block head %}
|
||||
<script src="https://cdn.jsdelivr.net/npm/shikwasa@2.2.0/dist/shikwasa.min.js"></script>
|
||||
<link href="https://cdn.jsdelivr.net/npm/shikwasa@2.2.0/dist/style.min.css" rel="stylesheet"></link>
|
||||
<script src="https://cdn.jsdelivr.net/npm/shikwasa@2.2.1/dist/shikwasa.min.js"></script>
|
||||
<link href="https://cdn.jsdelivr.net/npm/shikwasa@2.2.1/dist/style.min.css"
|
||||
rel="stylesheet"></link>
|
||||
<style>
|
||||
.shk-player {
|
||||
font-family: sans-serif;
|
||||
|
|
|
@ -8,43 +8,6 @@
|
|||
{% load truncate %}
|
||||
{% load highlight %}
|
||||
{% load thumb %}
|
||||
|
||||
{% for item in external_items %}
|
||||
<li class="entity-list__entity">
|
||||
<div class="entity-list__entity-img-wrapper">
|
||||
<a href="{{ item.link }}">
|
||||
{% if item.cover_url %}
|
||||
<img src="{{ item.cover_url }}" alt="" class="entity-list__entity-img">
|
||||
{% endif %}
|
||||
</a>
|
||||
</div>
|
||||
<div class="entity-list__entity-text">
|
||||
<div class="entity-list__entity-title" style="font-style:italic;">
|
||||
<a href="{{ item.link }}" class="entity-list__entity-link">
|
||||
{% if request.GET.q %}
|
||||
{{ item.title | highlight:request.GET.q }}
|
||||
{% else %}
|
||||
{{ item.title }}
|
||||
{% endif %}
|
||||
</a>
|
||||
|
||||
{% if not request.GET.c or not request.GET.c in categories %}
|
||||
<span class="entity-list__entity-category">[{{item.verbose_category_name}}]</span>
|
||||
{% endif %}
|
||||
<a href="{{ item.source_url }}">
|
||||
<span class="source-label source-label__{{ item.source_site }}">{{ item.source_site.label }}</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<span class="entity-list__entity-info entity-list__entity-info--full-length">
|
||||
{{item.subtitle}}
|
||||
</span>
|
||||
<p class="entity-list__entity-brief">
|
||||
{{ item.brief }}
|
||||
</p>
|
||||
<div class="tag-collection">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
<article class="item-card external">{% include "_item_card.html" with item=item %}</article>
|
||||
{% endfor %}
|
|
@ -1,3 +1,5 @@
|
|||
<p>
|
||||
无法加载条目。部分网站可能删除条目或隐藏条目为仅登录可见,欢迎在本站手工添加这些条目。
|
||||
<i class="fa-solid fa-triangle-exclamation"></i>
|
||||
无法加载条目,请确认链接正确。
|
||||
部分网站可能删除条目或隐藏条目为仅登录可见,欢迎在本站手工添加这些条目。
|
||||
</p>
|
|
@ -9,51 +9,28 @@
|
|||
{% load highlight %}
|
||||
{% load thumb %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<html lang="en" class="classic-page">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ site_name }} - {% trans '搜索结果' %}</title>
|
||||
{% include "common_libs.html" with jquery=0 %}
|
||||
{% include "common_libs.html" with jquery=0 v2=1 %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="page-wrapper">
|
||||
<div id="content-wrapper">
|
||||
{% include 'partial/_navbar.html' %}
|
||||
|
||||
<section id="content">
|
||||
<div class="grid">
|
||||
{% include '_header.html' %}
|
||||
<main>
|
||||
<div class="grid__main">
|
||||
<div class="main-section-wrapper">
|
||||
<div>
|
||||
{% trans '正在连线' %}{{ site.SITE_NAME.label }}
|
||||
<div hx-get="{% url 'catalog:fetch_refresh' job_id %}" hx-trigger="load delay:2s" hx-swap="outerHTML"></div>
|
||||
<i class="fas fa-fan fa-spin"></i>
|
||||
<article>
|
||||
<h5>{% trans '正在连线' %}{{ site.SITE_NAME.label }}</h5>
|
||||
<div hx-get="{% url 'catalog:fetch_refresh' job_id %}"
|
||||
hx-trigger="load delay:2s"
|
||||
hx-swap="outerHTML">
|
||||
<i class="fa-solid fa-compact-disc fa-spin loading"></i>
|
||||
</div>
|
||||
|
||||
</article>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
{% include "search_sidebar.html" %}
|
||||
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
{% include 'partial/_footer.html' %}
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
document.body.addEventListener('htmx:configRequest', (event) => {
|
||||
event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
</html>
|
||||
|
|
|
@ -1 +1,5 @@
|
|||
<div hx-get="{% url 'catalog:fetch_refresh' job_id %}?retry={{ retry }}" hx-trigger="load delay:{{ delay }}s" hx-swap="outerHTML"></div>
|
||||
<div hx-get="{% url 'catalog:fetch_refresh' job_id %}?retry={{ retry }}"
|
||||
hx-trigger="load delay:{{ delay }}s"
|
||||
hx-swap="outerHTML">
|
||||
<i class="fa-solid fa-compact-disc fa-spin loading"></i>
|
||||
</div>
|
||||
|
|
|
@ -9,21 +9,11 @@
|
|||
{% load truncate %}
|
||||
{% load strip_scheme %}
|
||||
{% load thumb %}
|
||||
|
||||
<!-- class specific details -->
|
||||
{% block details %}
|
||||
<div class="entity-detail__fields">
|
||||
<div class="entity-detail__rating">
|
||||
{% if item.rating and item.rating_count >= 5 %}
|
||||
<span class="entity-detail__rating-star rating-star" data-rating-score="{{ item.rating | floatformat:0 }}"></span>
|
||||
<span class="entity-detail__rating-score"> {{ item.rating | floatformat:1 }} </span>
|
||||
<small>({{ item.rating_count }}人评分)</small>
|
||||
{% else %}
|
||||
<span> {% trans '评分:评分人数不足' %}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div>{% if item.other_title %}{% trans '别名:' %}
|
||||
<div>
|
||||
{% if item.other_title %}
|
||||
{% trans '别名:' %}
|
||||
{% for other_title in item.other_title %}
|
||||
<span {% if forloop.counter > 5 %}style="display: none;"{% endif %}>
|
||||
<span class="other_title">{{ other_title }}</span>
|
||||
|
@ -39,70 +29,55 @@
|
|||
});
|
||||
$(this).remove();
|
||||
})
|
||||
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% if item.genre %}{% trans '类型:' %}
|
||||
{% if item.genre %}
|
||||
{% trans '类型:' %}
|
||||
{% for genre in item.genre %}
|
||||
<span>{{ genre }}</span>{% if not forloop.last %} / {% endif %}
|
||||
<span>{{ genre }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% if item.developer %}{% trans '开发商:' %}
|
||||
{% if item.developer %}
|
||||
{% trans '开发商:' %}
|
||||
{% for developer in item.developer %}
|
||||
<span>{{ developer }}</span>{% if not forloop.last %} / {% endif %}
|
||||
<span>{{ developer }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% if item.publisher %}{% trans '发行商:' %}
|
||||
{% if item.publisher %}
|
||||
{% trans '发行商:' %}
|
||||
{% for publisher in item.publisher %}
|
||||
<span>{{ publisher }}</span>{% if not forloop.last %} / {% endif %}
|
||||
<span>{{ publisher }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div>{% if item.release_date %}
|
||||
<div>
|
||||
{% if item.release_date %}
|
||||
{% trans '发行日期:' %}{{ item.release_date }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div>{% if item.official_site %}
|
||||
{% trans '官方网站:' %}{{ item.official_site|urlizetrunc:42 }}
|
||||
<div>
|
||||
{% if item.official_site %}
|
||||
{% trans '官方网站:' %}{{ item.official_site|urlizetrunc:24 }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="entity-detail__fields">
|
||||
|
||||
<div>
|
||||
{% if item.platform %}{% trans '平台:' %}
|
||||
{% if item.platform %}
|
||||
{% trans '平台:' %}
|
||||
{% for platform in item.platform %}
|
||||
<span>{{ platform }}</span>{% if not forloop.last %} / {% endif %}
|
||||
<span>{{ platform }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{% if item.last_editor and item.last_editor.preference.show_last_edit %}
|
||||
<div>{% trans '最近编辑者:' %}<a href="{% url 'journal:user_profile' item.last_editor.mastodon_username %}">{{ item.last_editor | default:"" }}</a></div>
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
{% if user.is_authenticated %}
|
||||
<a href="{% url 'catalog:edit' item.url_path item.uuid %}">{% trans '编辑' %}{{ item.demonstrative }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
<!-- class specific sidebar -->
|
||||
{% block sidebar %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -9,11 +9,7 @@
|
|||
{% load truncate %}
|
||||
{% load strip_scheme %}
|
||||
{% load thumb %}
|
||||
|
||||
<!-- class specific details -->
|
||||
{% block details %}
|
||||
{% endblock %}
|
||||
|
||||
{% block details %}{% endblock %}
|
||||
<!-- class specific sidebar -->
|
||||
{% block sidebar %}
|
||||
{% endblock %}
|
||||
{% block sidebar %}{% endblock %}
|
||||
|
|
|
@ -9,325 +9,389 @@
|
|||
{% load strip_scheme %}
|
||||
{% load thumb %}
|
||||
{% load user_actions %}
|
||||
|
||||
{% load duration %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<html lang="en" id="item-page">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta property="og:title" content="{{ site_name }}{% trans item.category.label %} - {{ item.title }}">
|
||||
<meta property="og:title"
|
||||
content="{{ site_name }}{% trans item.category.label %} - {{ item.title }}">
|
||||
<meta property="og:type" content="{{ item.category }}">
|
||||
<meta property="og:url" content="{{ request.build_absolute_uri }}">
|
||||
{% if item.has_cover %}
|
||||
<meta property="og:image" content="{{ item.cover_image_url }}">
|
||||
{% endif %}
|
||||
{% if item.has_cover %}<meta property="og:image" content="{{ item.cover_image_url }}">{% endif %}
|
||||
<meta property="og:site_name" content="{{ site_name }}">
|
||||
<meta property="og:description" content="{{ item.brief }}">
|
||||
{% block head %}
|
||||
{% endblock %}
|
||||
{% if item.is_deleted or item.merged_to_item %}<meta name="robots" content="noindex">{% endif %}
|
||||
<title>{{ site_name }} - {% trans item.category.label %} | {{ item.title }}</title>
|
||||
{% include "common_libs.html" with jquery=0 %}
|
||||
{% include "common_libs.html" with jquery=0 v2=1 %}
|
||||
{% block head %}{% endblock %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="page-wrapper">
|
||||
<div id="content-wrapper">
|
||||
{% include "partial/_navbar.html" %}
|
||||
|
||||
<section id="content">
|
||||
<div class="grid">
|
||||
<div class="grid__main" id="main">
|
||||
<div class="main-section-wrapper">
|
||||
<div class="entity-detail">
|
||||
|
||||
<a href="{{ item.cover.url }}" class="entity-detail__img-origin" target="_blank" rel="noopener" title="{% trans '查看原图' %}">
|
||||
<img src="{{ item.cover|thumb:'normal' }}" class="entity-detail__img" alt="{{ item.title }}">
|
||||
</a>
|
||||
|
||||
<div class="entity-detail__info">
|
||||
{% if item.is_deleted %}
|
||||
[DELETED]
|
||||
{% endif %}
|
||||
{% include "_header.html" %}
|
||||
<main class="container-fluid">
|
||||
<div id="item-title" class="middle">
|
||||
{% if item.is_deleted %}[DELETED]{% endif %}
|
||||
{% if item.merged_to_item %}
|
||||
[MERGED <a href="{{ item.merged_to_item.url }}">{{ item.merged_to_item.title }}</a>]
|
||||
[MERGED TO <a href="{{ item.merged_to_item.url }}">{{ item.merged_to_item.title }}</a>]
|
||||
{% endif %}
|
||||
{% block title %}
|
||||
<h5 class="entity-detail__title">
|
||||
<h1>
|
||||
{{ item.title }}
|
||||
|
||||
<small>
|
||||
{% if item.season_number %}
|
||||
{% trans '第' %}{{ item.season_number|apnumber }}{% trans '季' %}
|
||||
{% endif %}
|
||||
{% if item.year %}({{ item.year }}){% endif %}
|
||||
</small>
|
||||
</h1>
|
||||
<span class="site-list">
|
||||
{% for res in item.external_resources.all %}
|
||||
<a href="{{ res.url }}">
|
||||
<span class="source-label source-label__{{ res.site_name }}">{{ res.site_name.label }}</span>
|
||||
</a>
|
||||
<a href="{{ res.url }}" class="{{ res.site_name }}">{{ res.site_name.label }}</a>
|
||||
{% endfor %}
|
||||
</h5>
|
||||
{% endblock %}
|
||||
|
||||
{% block details %}
|
||||
<div class="entity-detail__fields">
|
||||
<div class="entity-detail__rating">
|
||||
{% if item.rating %}
|
||||
<span class="entity-detail__rating-star rating-star" data-rating-score="{{ item.rating | floatformat:0 }}"></span>
|
||||
<span class="entity-detail__rating-score"> {{ item.rating | floatformat:1 }} </span>
|
||||
<small>({{ item.rating_count }}人评分)</small>
|
||||
</span>
|
||||
</div>
|
||||
<div id="item-cover" class="left">
|
||||
<img src="{{ item.cover|thumb:'normal' }}" alt="{{ item.title }}">
|
||||
</div>
|
||||
{% if request.user.is_authenticated and not mark.shelf_type %}
|
||||
<div id="item-primary-action" class="right mark">
|
||||
<div class="item-action">
|
||||
{% for k, v in shelf_types %}
|
||||
{% if v %}
|
||||
<button class="primary"
|
||||
data-status="{{ k }}"
|
||||
hx-get="{% url 'journal:mark' item.uuid %}?shelf_type={{ k }}&new=1"
|
||||
hx-target="body"
|
||||
hx-swap="beforeend">{% trans v %}</button>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if request.user.is_authenticated and mark.shelf_type %}
|
||||
<div id="item-primary-mark" class="right mark">
|
||||
<div class="item-action">
|
||||
<button class="outline edit"
|
||||
hx-get="{% url 'journal:mark' item.uuid %}?new=1"
|
||||
hx-target="body"
|
||||
hx-swap="beforeend">
|
||||
{{ mark.created_time | date }} {% trans mark.action_label %}
|
||||
{% if mark.rating %}
|
||||
<br>
|
||||
{{ mark.rating | rating_star }}
|
||||
<!-- <span style="white-space: nowrap;">
|
||||
<i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star-half-stroke"></i><i class="fa-regular fa-star"></i>
|
||||
</span> -->
|
||||
{% endif %}
|
||||
</button>
|
||||
</div>
|
||||
<div class="small-only" style="margin-top:2vh;">
|
||||
<a href="#item-sidebar">标签 · 短评 · 评论 · 收藏</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div id="item-sidebar" class="right">
|
||||
{% if request.user.is_authenticated %}
|
||||
<section>
|
||||
<h5>
|
||||
我的标签
|
||||
<small>
|
||||
<a href="#"
|
||||
hx-get="{% url 'journal:mark' item.uuid %}?new=1"
|
||||
class="edit"
|
||||
hx-target="body"
|
||||
hx-swap="beforeend">
|
||||
{% if mark.tags %}
|
||||
<i class="fa-solid fa-pen-to-square"></i>
|
||||
{% else %}
|
||||
<span> {% trans '评分:评分人数不足' %}</span>
|
||||
<i class="fa-regular fa-square-plus"></i>
|
||||
{% endif %}
|
||||
</a>
|
||||
</small>
|
||||
</h5>
|
||||
<div class="tag-list">
|
||||
{% for tag in mark.tags %}
|
||||
<span>
|
||||
<a href="{% url 'journal:user_tag_member_list' request.user.mastodon_username tag %}">{{ tag }}</a>
|
||||
</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
<h5>
|
||||
我的短评
|
||||
<small>
|
||||
<a href="#"
|
||||
hx-get="{% url 'journal:mark' item.uuid %}?new=1"
|
||||
class="edit"
|
||||
hx-target="body"
|
||||
hx-swap="beforeend">
|
||||
{% if mark.text %}
|
||||
<i class="fa-solid fa-pen-to-square"></i>
|
||||
{% else %}
|
||||
<i class="fa-regular fa-square-plus"></i>
|
||||
{% endif %}
|
||||
</a>
|
||||
</small>
|
||||
</h5>
|
||||
{% if mark.comment %}
|
||||
<span class="action">
|
||||
<span>
|
||||
{% liked_piece mark.comment as liked %}
|
||||
{% include 'like_stats.html' with liked=liked piece=mark.comment %}
|
||||
</span>
|
||||
<span>
|
||||
<a target="_blank"
|
||||
rel="noopener"
|
||||
{% if mark.comment.metadata.shared_link %} href="{{ mark.comment.metadata.shared_link }}" title="打开联邦网络分享链接" {% else %} class="disabled" {% endif %}><i class="fa-solid {% if mark.comment.visibility > 0 %} fa-lock {% else %} fa-globe {% endif %}"></i></a>
|
||||
</span>
|
||||
<span class="timestamp">{{ mark.comment.created_time|date }}</span>
|
||||
</span>
|
||||
<p>{{ mark.comment.html|safe }}</p>
|
||||
{% else %}
|
||||
<!-- <span class="empty">暂无</span> -->
|
||||
{% endif %}
|
||||
</section>
|
||||
<section>
|
||||
<h5>
|
||||
我的评论
|
||||
<small>
|
||||
{% if review %}
|
||||
<a href="{% url 'journal:review_edit' item.uuid review.uuid %}">
|
||||
<i class="fa-solid fa-pen-to-square"></i>
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="{% url 'journal:review_create' item.uuid %}">
|
||||
<i class="fa-regular fa-square-plus"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
</small>
|
||||
</h5>
|
||||
{% if review %}
|
||||
<span class="action">
|
||||
<span>
|
||||
{% liked_piece mark.review as liked %}
|
||||
{% include 'like_stats.html' with liked=liked piece=mark.review %}
|
||||
</span>
|
||||
<span>
|
||||
<a target="_blank"
|
||||
rel="noopener"
|
||||
{% if mark.review.metadata.shared_link %} href="{{ mark.review.metadata.shared_link }}" title="打开联邦网络分享链接" {% else %} class="disabled" {% endif %}><i class="fa-solid {% if mark.review.visibility > 0 %} fa-lock {% else %} fa-globe {% endif %}"></i></a>
|
||||
</span>
|
||||
<span class="timestamp">{{ mark.review.created_time|date }}</span>
|
||||
</span>
|
||||
<p>
|
||||
<a href="{% url 'journal:review_retrieve' review.uuid %}">{{ review.title }}</a>
|
||||
</p>
|
||||
{% else %}
|
||||
<!-- <span class="empty">暂无</span> -->
|
||||
{% endif %}
|
||||
</section>
|
||||
<section>
|
||||
<h5>
|
||||
我的收藏单
|
||||
<small>
|
||||
<a href="#"
|
||||
hx-get="{% url 'journal:add_to_collection' item.uuid %}?new=1"
|
||||
class="edit"
|
||||
hx-target="body"
|
||||
hx-swap="beforeend">
|
||||
<i class="fa-regular fa-square-plus"></i>
|
||||
</a>
|
||||
</small>
|
||||
</h5>
|
||||
<div>
|
||||
{% for c in my_collections %}
|
||||
<p>
|
||||
<a href="{{ c.url }}">{{ c.title }}</a>
|
||||
{% if c.visibility > 0 %}<i class="fa-solid fa-lock"></i>{% endif %}
|
||||
</p>
|
||||
{% empty %}
|
||||
<!-- <span class="empty">暂无</span> -->
|
||||
{% endfor %}
|
||||
</div>
|
||||
</section>
|
||||
<!--
|
||||
<section>
|
||||
<h5>标记历史</h5>
|
||||
<div>
|
||||
{% for log in mark.logs %}{{ log.timestamp|date }} {{ log.action_label }}<br>{% endfor %}
|
||||
</div>
|
||||
</section>
|
||||
-->
|
||||
{% else %}
|
||||
<section>
|
||||
<p class="empty">
|
||||
<span><a href="{% url 'users:login' %}">登录</a>后可管理标记收藏</span>
|
||||
</p>
|
||||
</section>
|
||||
{% endif %}
|
||||
{% block sidebar %}{% endblock %}
|
||||
{% if collection_list %}
|
||||
<section>
|
||||
<h5>相关收藏单</h5>
|
||||
<div>
|
||||
{% for c in collection_list %}
|
||||
<p>
|
||||
<a href="{{ c.url }}">{{ c.title }}</a>
|
||||
{% if c.visibility > 0 %}<i class="fa-solid fa-lock"></i>{% endif %}
|
||||
</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div id="item-metadata" class="left">
|
||||
{% block details %}
|
||||
<div>此类数据尚未支持</div>
|
||||
<div>uuid: {{ item.uuid }}</div>
|
||||
<div>class: {{ item.class_name }}</div>
|
||||
<div>category: {{ item.category }}</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
<div class="tag-collection">
|
||||
{% if request.user.is_authenticated %}
|
||||
<div class="item-edit">
|
||||
<span class="action inline">
|
||||
<a href="{% url 'catalog:edit' item.url_path item.uuid %}"
|
||||
title="{% trans '编辑' %}{{ item.demonstrative }}"><i class="fa-solid fa-pen-to-square"></i></a>
|
||||
</span>
|
||||
{% if item.last_editor and item.last_editor.preference.show_last_edit %}
|
||||
<span>
|
||||
{% trans '最近编辑:' %}
|
||||
<a href="{% url 'journal:user_profile' item.last_editor.mastodon_username %}">{{ item.last_editor | default:"" }}</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="rating{% if not item.rating %} unavailable{% endif %}">
|
||||
<div class="display">
|
||||
<div>
|
||||
<hgroup>
|
||||
<h3>
|
||||
{{ item.rating | floatformat:1 }} <small>/ 10</small>
|
||||
</h3>
|
||||
<p>{{ item.rating_count }}人评分</p>
|
||||
</hgroup>
|
||||
</div>
|
||||
<div data-placement="top">
|
||||
<ul class="chart">
|
||||
<li data-tooltip="{{ item.rating_dist.0 }}%" data-placement="left">
|
||||
<span style="height:{{ item.rating_dist.0 }}%"></span>
|
||||
</li>
|
||||
<li data-tooltip="{{ item.rating_dist.1 }}%" data-placement="left">
|
||||
<span style="height:{{ item.rating_dist.1 }}%"></span>
|
||||
</li>
|
||||
<li data-tooltip="{{ item.rating_dist.2 }}%" data-placement="left">
|
||||
<span style="height:{{ item.rating_dist.2 }}%"></span>
|
||||
</li>
|
||||
<li data-tooltip="{{ item.rating_dist.3 }}%" data-placement="left">
|
||||
<span style="height:{{ item.rating_dist.3 }}%"></span>
|
||||
</li>
|
||||
<li data-tooltip="{{ item.rating_dist.4 }}%" data-placement="left">
|
||||
<span style="height:{{ item.rating_dist.4 }}%"></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="undisplay">
|
||||
<span>评分人数不足</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tag-list">
|
||||
{% for tag in item.tags %}
|
||||
<span class="tag-collection__tag">
|
||||
<span>
|
||||
<a href="{% url 'catalog:search' %}?tag={{ tag }}">{{ tag }}</a>
|
||||
</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% block left_sidebar %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="dividing-line"></div>
|
||||
{% if item.brief %}
|
||||
<div class="entity-desc" id="description">
|
||||
<h5 class="entity-desc__title">{% trans '简介' %}</h5>
|
||||
|
||||
<p class="entity-desc__content">{{ item.brief | linebreaksbr }}</p>
|
||||
<div class="entity-desc__unfold-button entity-desc__unfold-button--hidden">
|
||||
<a href="javascript:void(0);">展开全部</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% block content %}
|
||||
{% if item.contents %}
|
||||
<div class="entity-desc" id="contents">
|
||||
<h5 class="entity-desc__title">{% trans '目录' %}</h5>
|
||||
<p class="entity-desc__content">{{ item.contents | linebreaksbr }}</p>
|
||||
<div class="entity-desc__unfold-button entity-desc__unfold-button--hidden">
|
||||
<a href="javascript:void(0);">展开全部</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if item.track_list %}
|
||||
<div class="entity-desc" id="description">
|
||||
<h5 class="entity-desc__title">{% trans '曲目' %}</h5>
|
||||
<p class="entity-desc__content">{{ item.track_list | linebreaksbr }}</p>
|
||||
<div class="entity-desc__unfold-button entity-desc__unfold-button--hidden">
|
||||
<a href="javascript:void(0);">展开全部</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
<div class="entity-marks">
|
||||
<h5 class="entity-marks__title">{% trans '标记' %}</h5>
|
||||
{% if mark_list %}
|
||||
<a href="{% url 'catalog:mark_list' item.url_path item.uuid %}" class="entity-marks__more-link">{% trans '全部标记' %}</a>
|
||||
<a href="{% url 'catalog:mark_list' item.url_path item.uuid 'following' %}" class="entity-marks__more-link">关注的人的标记</a>
|
||||
{% endif %}
|
||||
|
||||
<ul class="entity-marks__mark-list">
|
||||
{% for others_mark in mark_list %}
|
||||
<li class="entity-marks__mark">
|
||||
<a href="{% url 'journal:user_profile' others_mark.owner.mastodon_username %}" class="entity-marks__owner-link">{{ others_mark.owner.username }}</a>
|
||||
|
||||
<span>{{ others_mark.action_label }}</span>
|
||||
|
||||
{% if others_mark.rating %}
|
||||
<span class="entity-marks__rating-star rating-star" data-rating-score="{{ others_mark.rating }}"></span>
|
||||
{% endif %}
|
||||
|
||||
{% if others_mark.visibility > 0 %}
|
||||
<i class="fa-solid fa-lock"></i>
|
||||
{% endif %}
|
||||
|
||||
{% if others_mark.shelfmember.metadata.shared_link %}
|
||||
<a href="{{ others_mark.shelfmember.metadata.shared_link }}" target="_blank" rel="noopener"><span class="entity-marks__mark-time">{{ others_mark.created_time | date }}</span></a>
|
||||
{% else %}
|
||||
<span class="entity-marks__mark-time">{{ others_mark.created_time | date }}</span>
|
||||
{% endif %}
|
||||
|
||||
{% if others_mark.text %}
|
||||
<p class="entity-marks__mark-content">{{ others_mark.comment_html|safe }}
|
||||
<span class="action-bar inline">
|
||||
<span>
|
||||
{% liked_piece others_mark.shelfmember as liked %}
|
||||
{% include 'like_stats.html' with liked=liked piece=others_mark.shelfmember %}
|
||||
</span>
|
||||
</span>
|
||||
</p>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% empty %}
|
||||
|
||||
<div> {% trans '暂无标记' %} </div>
|
||||
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="entity-reviews">
|
||||
<h5 class="entity-reviews__title">{% trans '评论' %}</h5>
|
||||
{% if review_list %}
|
||||
<a href="{% url 'catalog:review_list' item.url_path item.uuid %}" class="entity-reviews__more-link">{% trans '全部评论' %}</a>
|
||||
{% endif %}
|
||||
{% if review_list %}
|
||||
<ul class="entity-reviews__review-list">
|
||||
{% for others_review in review_list %}
|
||||
<li class="entity-reviews__review">
|
||||
<a href="{% url 'journal:user_profile' others_review.owner.mastodon_username %}" class="entity-reviews__owner-link">{{ others_review.owner.username }}</a>
|
||||
{% if others_review.visibility > 0 %}
|
||||
<i class="fa-solid fa-lock"></i>
|
||||
{% endif %}
|
||||
<span class="entity-reviews__review-time">{{ others_review.created_time | date }}</span>
|
||||
<span class="entity-reviews__review-title"> <a href="{% url 'journal:review_retrieve' others_review.uuid %}">{{ others_review.title }}</a></span>
|
||||
<span class="action-bar inline">
|
||||
<span>
|
||||
{% liked_piece others_review as liked %}
|
||||
{% include 'like_stats.html' with liked=liked piece=others_review %}
|
||||
</span>
|
||||
</span>
|
||||
<span>{{ others_review.get_plain_content | truncate:100 }}</span>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<div>{% trans '暂无评论' %}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid__aside" id="aside">
|
||||
{% block sidebar_review %}
|
||||
{% if user.is_authenticated %}
|
||||
<div class="aside-section-wrapper">
|
||||
{% if mark.shelf_type %}
|
||||
<div class="mark-panel">
|
||||
<span class="mark-panel__status">{% trans '我' %}{% trans mark.shelf_label %}</span>
|
||||
{% if mark.rating %}
|
||||
<span class="mark-panel__rating-star rating-star" data-rating-score="{{ mark.rating | floatformat:'0' }}"></span>
|
||||
{% endif %}
|
||||
{% if mark.visibility > 0 %}
|
||||
<i class="fa-solid fa-lock"></i>
|
||||
{% endif %}
|
||||
<span class="mark-panel__actions">
|
||||
<a href="#" hx-get="{% url 'journal:mark' item.uuid %}" class="edit" hx-target="body" hx-swap="beforeend">{% trans '修改' %}</a>
|
||||
<form id="mark_delete" action="{% url 'journal:mark' item.uuid %}" method="post">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="delete" value="1">
|
||||
<a href="javascript:$('#mark_delete').submit()" class="delete">{% trans '删除' %}</a>
|
||||
</form>
|
||||
</span>
|
||||
<div class="mark-panel__clear"></div>
|
||||
|
||||
<div class="mark-panel__time">
|
||||
<!-- <div>
|
||||
{% for log in mark.logs %}
|
||||
{{ log.timestamp|date }} {{ log.action_label }}<br>
|
||||
{% endfor %}
|
||||
</div> -->
|
||||
{% if mark.metadata.shared_link %}
|
||||
<a href="{{ mark.metadata.shared_link }}">{{ mark.created_time|date }}</a>
|
||||
{% else %}
|
||||
{{ mark.created_time|date }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if mark.text %}
|
||||
<p class="mark-panel__text">{{ mark.comment_html|safe }}</p>
|
||||
{% endif %}
|
||||
<div class="tag-collection">
|
||||
|
||||
{% for tag in mark.tags %}
|
||||
<span class="tag-collection__tag"><a href="{% url 'journal:user_tag_member_list' user.mastodon_username tag %}">{{ tag }}</a></span>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="action-panel" id="addMarkPanel">
|
||||
<div class="action-panel__label">{% trans '标记' %}{% trans item.demonstrative %}</div>
|
||||
<div class="action-panel__button-group">
|
||||
{% for k, v in shelf_types %}
|
||||
{% if v %}
|
||||
<button class="action-panel__button" data-status="{{ k }}" hx-get="{% url 'journal:mark' item.uuid %}?shelf_type={{ k }}" class="edit" hx-target="body" hx-swap="beforeend">{% trans v %}</button>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="aside-section-wrapper">
|
||||
<div class="review-panel action-panel">
|
||||
{% if review %}
|
||||
<span class="review-panel__label">{% trans '我的评论' %}</span>
|
||||
{% if review.visibility > 0 %}
|
||||
<i class="fa-solid fa-lock"></i>
|
||||
{% endif %}
|
||||
<span class="review-panel__actions">
|
||||
<a href="{% url 'journal:review_edit' item.uuid review.uuid %}">{% trans '编辑' %}</a>
|
||||
<a href="{% url 'journal:review_delete' review.uuid %}?return_url={{ item.url }}">{% trans '删除' %}</a>
|
||||
</span>
|
||||
|
||||
<div class="review-panel__time">{{ review.edited_time }}</div>
|
||||
|
||||
<a href="{% url 'journal:review_retrieve' review.uuid %}" class="review-panel__review-title">
|
||||
{{ review.title }}
|
||||
</a>
|
||||
{% else %}
|
||||
<div class="action-panel__button-group action-panel__button-group--center">
|
||||
<a href="{% url 'journal:review_create' item.uuid %}">
|
||||
<button class="action-panel__button">{% trans '撰写评论' %}</button>
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="aside-section-wrapper">
|
||||
<div class="mark-panel">
|
||||
<span>{% trans '登录后可管理标记和评论' %}</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block sidebar %}
|
||||
{% endblock %}
|
||||
|
||||
{% block sidebar_collection %}
|
||||
<div class="aside-section-wrapper">
|
||||
<div class="action-panel">
|
||||
<div class="action-panel__label">{% trans '相关收藏单' %}</div>
|
||||
<div >
|
||||
{% if collection_list %}
|
||||
{% for c in collection_list %}
|
||||
<div id="item-title-more" class="middle">
|
||||
<hgroup>
|
||||
{% if item.subtitle %}<p>{{ item.subtitle }}</p>{% endif %}
|
||||
{% if item.orig_title %}
|
||||
<p>
|
||||
<a href="{{ c.url }}">{{ c.title }}</a>
|
||||
{{ item.orig_title }}
|
||||
<small>
|
||||
{% if item.season_number %}Season {{ item.season_number }}{% endif %}
|
||||
</small>
|
||||
</p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if item.author or item.translator %}
|
||||
<p>
|
||||
<i>
|
||||
{% include '_people.html' with people=item.author _role='作者' max=2 %}
|
||||
</i>
|
||||
|
||||
<i>
|
||||
{% include '_people.html' with people=item.translator role='译者' max=2 %}
|
||||
</i>
|
||||
</p>
|
||||
{% endif %}
|
||||
</hgroup>
|
||||
</div>
|
||||
<div id="item-detail" class="middle">
|
||||
<section>
|
||||
<h5>简介</h5>
|
||||
{% if item.brief %}
|
||||
<p class="tldr" _="on click toggle .tldr on me">{{ item.brief | linebreaksbr }}</p>
|
||||
{% else %}
|
||||
<p class="empty">暂缺</p>
|
||||
{% endif %}
|
||||
</section>
|
||||
{% block content %}{% endblock %}
|
||||
<section>
|
||||
<h5>
|
||||
短评
|
||||
{% if request.user.is_authenticated %}
|
||||
<div class="action-panel__button-group action-panel__button-group--center">
|
||||
<button class="action-panel__button add-to-list" hx-get="{% url 'journal:add_to_collection' item.uuid %}" hx-target="body" hx-swap="beforeend">{% trans '添加到收藏单' %}</button>
|
||||
</div>
|
||||
<small>
|
||||
| <a href="{% url 'catalog:mark_list' item.url_path item.uuid %}"
|
||||
class="entity-marks__more-link">{% trans '全部标记' %}</a>
|
||||
| <a href="{% url 'catalog:mark_list' item.url_path item.uuid 'following' %}"
|
||||
class="entity-marks__more-link">关注的人的标记</a>
|
||||
</small>
|
||||
{% endif %}
|
||||
</h5>
|
||||
{% if request.user.is_authenticated %}
|
||||
<div>
|
||||
<div hx-get="{% url 'catalog:comments' item.url_path item.uuid %}"
|
||||
hx-trigger="intersect once"
|
||||
hx-swap="outerHTML">
|
||||
<i class="fa-solid fa-compact-disc fa-spin loading"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% else %}
|
||||
<p class="empty">登录后可见</p>
|
||||
{% endif %}
|
||||
</section>
|
||||
<section class="entity-reviews">
|
||||
<h5>
|
||||
{% trans '评论' %}
|
||||
{% comment %}
|
||||
{% if request.user.is_authenticated %}
|
||||
<small>
|
||||
| <a href="{% url 'catalog:review_list' item.url_path item.uuid %}" class="entity-marks__more-link">{% trans '全部评论' %}</a>
|
||||
</small>
|
||||
{% endif %}
|
||||
{% endcomment %}
|
||||
</h5>
|
||||
{% if request.user.is_authenticated %}
|
||||
<div>
|
||||
<div hx-get="{% url 'catalog:reviews' item.url_path item.uuid %}"
|
||||
hx-trigger="intersect once"
|
||||
hx-swap="outerHTML">
|
||||
<i class="fa-solid fa-compact-disc fa-spin loading"></i>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<p class="empty">登录后可见</p>
|
||||
{% endif %}
|
||||
</section>
|
||||
</div>
|
||||
{% include "partial/_footer.html" %}
|
||||
<div id="item-more" class="middle">
|
||||
<!-- test more content -->
|
||||
</div>
|
||||
<div style="clear: both;display: table;"></div>
|
||||
</main>
|
||||
{% include "partial/_footer.html" %}
|
||||
</body>
|
||||
</html>
|
||||
|
|
44
catalog/templates/item_comments.html
Normal file
44
catalog/templates/item_comments.html
Normal file
|
@ -0,0 +1,44 @@
|
|||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load l10n %}
|
||||
{% load admin_url %}
|
||||
{% load mastodon %}
|
||||
{% load oauth_token %}
|
||||
{% load truncate %}
|
||||
{% load duration %}
|
||||
{% load user_actions %}
|
||||
{% for comment in comments %}
|
||||
{% if forloop.counter <= 10 %}
|
||||
<section>
|
||||
<span class="action">
|
||||
<span>
|
||||
{% liked_piece comment as liked %}
|
||||
{% include 'like_stats.html' with liked=liked piece=comment %}
|
||||
</span>
|
||||
<span>
|
||||
<a target="_blank"
|
||||
rel="noopener"
|
||||
{% if comment.metadata.shared_link %} href="{{ comment.metadata.shared_link }}" title="打开联邦网络分享链接" {% else %} class="disabled" {% endif %}><i class="fa-solid {% if comment.visibility > 0 %} fa-lock {% else %} fa-globe {% endif %}"></i></a>
|
||||
</span>
|
||||
<span class="timestamp">{{ comment.created_time|date }}</span>
|
||||
</span>
|
||||
<span>
|
||||
{% if comment.rating_grade %}{{ comment.rating_grade|rating_star }}{% endif %}
|
||||
<a href="{% url 'journal:user_profile' comment.owner.mastodon_username %}"
|
||||
class="nickname"
|
||||
title="@{{ comment.owner.mastodon_username }}">{{ comment.owner.display_name }}</a>
|
||||
{{ comment.mark.action_label }}
|
||||
{% if comment.focus_item %}<a href="{{ comment.focus_item.url }}">{{ comment.focus_item.title }}</a>{% endif %}
|
||||
</span>
|
||||
<div>{{ comment.html|safe }}</div>
|
||||
</section>
|
||||
{% else %}
|
||||
<a hx-get="{% url 'catalog:comments' comment.item.url_path comment.item.uuid %}?last={{ comment.created_time|date:'Y-m-d H:i:s.uO'|urlencode }}"
|
||||
hx-trigger="click"
|
||||
hx-swap="outerHTML">
|
||||
<button class="outline">显示更多</button>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% empty %}
|
||||
<div class="empty">{% trans '暂无' %}</div>
|
||||
{% endfor %}
|
|
@ -7,108 +7,78 @@
|
|||
{% load highlight %}
|
||||
{% load thumb %}
|
||||
{% load user_actions %}
|
||||
|
||||
{% load duration %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<html lang="en" class="classic-page">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ site_name }} - {{ item.title }}{% trans '的标记' %}</title>
|
||||
{% include "common_libs.html" with jquery=0 %}
|
||||
{% include "common_libs.html" with jquery=0 v2=1 %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="page-wrapper">
|
||||
<div id="content-wrapper">
|
||||
{% include "partial/_navbar.html" %}
|
||||
|
||||
<section id="content">
|
||||
<div class="grid">
|
||||
<div class="grid__main" id="main">
|
||||
<div class="main-section-wrapper">
|
||||
<div class="entity-marks">
|
||||
<h5 class="entity-marks__title entity-marks__title--stand-alone">
|
||||
{% include '_header.html' %}
|
||||
<main>
|
||||
<div class="grid__main">
|
||||
<h5>
|
||||
<a href="{% url 'catalog:retrieve' item.url_path item.uuid %}">{{ item.title }}</a>{% trans ' 的标记' %}
|
||||
</h5>
|
||||
<ul class="entity-marks__mark-list">
|
||||
{% for others_mark in marks %}
|
||||
<li class="entity-marks__mark">
|
||||
<a href="{% url 'journal:user_profile' others_mark.owner.mastodon_username %}" class="entity-marks__owner-link">{{ others_mark.owner.username }}</a>
|
||||
|
||||
<span>{{ others_mark.mark.action_label }}</span>
|
||||
|
||||
{% if others_mark.mark.rating %}
|
||||
<span class="entity-marks__rating-star rating-star" data-rating-score="{{ others_mark.mark.rating }}"></span>
|
||||
{% endif %}
|
||||
|
||||
{% if others_mark.mark.visibility > 0 %}
|
||||
<i class="fa-solid fa-lock"></i>
|
||||
{% endif %}
|
||||
|
||||
{% if others_mark.metadata.shared_link %}
|
||||
<a href="{{ others_mark.metadata.shared_link }}" target="_blank" rel="noopener"><span class="entity-marks__mark-time">{{ others_mark.mark.created_time|date }}</span></a>
|
||||
{% else %}
|
||||
<span class="entity-marks__mark-time">{{ others_mark.mark.created_time|date }}</span>
|
||||
{% endif %}
|
||||
|
||||
{% if others_mark.mark.text %}
|
||||
<p class="entity-marks__mark-content">{{ others_mark.mark.comment_html|safe }}
|
||||
<span class="action-bar inline">
|
||||
{% for member in marks %}
|
||||
{% with member.mark as mark %}
|
||||
<section>
|
||||
<div class="action">
|
||||
{% if mark.comment %}
|
||||
<span>
|
||||
{% liked_piece others_mark as liked %}
|
||||
{% include 'like_stats.html' with liked=liked piece=others_mark %}
|
||||
{% liked_piece mark.comment as liked %}
|
||||
{% include 'like_stats.html' with liked=liked piece=mark.comment %}
|
||||
</span>
|
||||
</span>
|
||||
</p>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% empty %}
|
||||
|
||||
<div> {% trans '暂无标记' %} </div>
|
||||
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<span>
|
||||
<a target="_blank"
|
||||
rel="noopener"
|
||||
{% if mark.metadata.shared_link %} href="{{ mark.metadata.shared_link }}" title="打开联邦网络分享链接" {% else %} class="disabled" {% endif %}><i class="fa-solid {% if mark.visibility > 0 %} fa-lock {% else %} fa-globe {% endif %}"></i></a>
|
||||
</span>
|
||||
<span class="timestamp">{{ mark.created_time|date }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<a href="{% url 'journal:user_profile' mark.owner.mastodon_username %}"
|
||||
title="@{{ mark.owner.mastodon_username }}">{{ mark.owner.display_name }}</a>
|
||||
<span>{{ mark.action_label }}</span>
|
||||
{% if mark.rating_grade %}{{ mark.rating_grade|rating_star }}{% endif %}
|
||||
{% if mark.comment.focus_item %}
|
||||
<a href="{{ mark.comment.focus_item.url }}">{{ mark.comment.focus_item.title }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>{{ mark.comment.html|safe }}</div>
|
||||
</section>
|
||||
{% endwith %}
|
||||
{% empty %}
|
||||
<div>{% trans '暂无标记' %}</div>
|
||||
{% endfor %}
|
||||
<div class="pagination">
|
||||
|
||||
{% if marks.pagination.has_prev %}
|
||||
<a href="?page=1"
|
||||
class="pagination__nav-link pagination__nav-link">«</a>
|
||||
<a href="?page=1" class="pagination__nav-link pagination__nav-link">«</a>
|
||||
<a href="?page={{ marks.previous_page_number }}"
|
||||
class="pagination__nav-link pagination__nav-link--right-margin pagination__nav-link">‹</a>
|
||||
{% endif %}
|
||||
|
||||
{% for page in marks.pagination.page_range %}
|
||||
|
||||
{% if page == marks.pagination.current_page %}
|
||||
<a href="?page={{ page }}"
|
||||
class="pagination__page-link pagination__page-link--current">{{ page }}</a>
|
||||
{% else %}
|
||||
<a href="?page={{ page }}"
|
||||
class="pagination__page-link">{{ page }}</a>
|
||||
<a href="?page={{ page }}" class="pagination__page-link">{{ page }}</a>
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{% if marks.pagination.has_next %}
|
||||
<a href="?page={{ marks.next_page_number }}"
|
||||
class="pagination__nav-link pagination__nav-link--left-margin">›</a>
|
||||
<a href="?page={{ marks.pagination.last_page }}"
|
||||
class="pagination__nav-link">»</a>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid__aside" id="aside">
|
||||
{% include "sidebar_item.html" %}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="grid__aside" id="aside">{% include "sidebar_item.html" %}</div>
|
||||
</main>
|
||||
{% include "partial/_footer.html" %}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -7,94 +7,77 @@
|
|||
{% load highlight %}
|
||||
{% load thumb %}
|
||||
{% load user_actions %}
|
||||
|
||||
{% load duration %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<html lang="en" class="classic-page">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ site_name }} - {{ item.title }}{% trans '的评论' %}</title>
|
||||
{% include "common_libs.html" with jquery=0 %}
|
||||
{% include "common_libs.html" with jquery=0 v2=1 %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="page-wrapper">
|
||||
<div id="content-wrapper">
|
||||
{% include "partial/_navbar.html" %}
|
||||
<section id="content">
|
||||
<div class="grid">
|
||||
<div class="grid__main" id="main">
|
||||
<div class="main-section-wrapper">
|
||||
<div class="entity-reviews">
|
||||
<h5 class="entity-reviews__title entity-reviews__title--stand-alone">
|
||||
<a href="{{ item.url }}">{{ item.title }}</a>{% trans ' 的评论' %}
|
||||
{% include '_header.html' %}
|
||||
<main>
|
||||
<div class="grid__main">
|
||||
<h5>
|
||||
<a href="{% url 'catalog:retrieve' item.url_path item.uuid %}">{{ item.title }}</a>{% trans ' 的评论' %}
|
||||
</h5>
|
||||
<ul class="entity-reviews__review-list">
|
||||
|
||||
{% for review in reviews %}
|
||||
<li class="entity-reviews__review entity-reviews__review--wider">
|
||||
<a href="{% url 'journal:user_profile' review.owner.mastodon_username %}" class="entity-reviews__owner-link">{{ review.owner.username }}</a>
|
||||
{% if review.visibility > 0 %}
|
||||
<i class="fa-solid fa-lock"></i>
|
||||
{% endif %}
|
||||
<span class="entity-reviews__review-time">{{ review.created_time | date }}</span>
|
||||
<span class="entity-reviews__review-title"><a href="{% url 'journal:review_retrieve' review.uuid %}">{{ review.title }}</a></span>
|
||||
<span class="action-bar inline">
|
||||
<section>
|
||||
<div class="action">
|
||||
<span>
|
||||
<a target="_blank"
|
||||
rel="noopener"
|
||||
{% if review.metadata.shared_link %} href="{{ review.metadata.shared_link }}" title="打开联邦网络分享链接" {% else %} class="disabled" {% endif %}><i class="fa-solid {% if review.visibility > 0 %} fa-lock {% else %} fa-globe {% endif %}"></i></a>
|
||||
</span>
|
||||
<span>
|
||||
{% liked_piece review as liked %}
|
||||
{% include 'like_stats.html' with liked=liked piece=review %}
|
||||
</span>
|
||||
<span class="timestamp">{{ review.created_time|date }}</span>
|
||||
</div>
|
||||
<div>
|
||||
{% if review.rating_grade %}{{ review.rating_grade|rating_star }}{% endif %}
|
||||
<span>
|
||||
<a href="{% url 'journal:review_retrieve' review.uuid %}">{{ review.title }}</a>
|
||||
</span>
|
||||
</li>
|
||||
-
|
||||
<span>
|
||||
<a href="{% url 'journal:user_profile' review.owner.mastodon_username %}"
|
||||
class="nickname"
|
||||
title="@{{ review.owner.mastodon_username }}">{{ review.owner.display_name }}</a>
|
||||
</span>
|
||||
</div>
|
||||
<div>{{ review.plain_content | truncate:200 }}</div>
|
||||
</section>
|
||||
{% empty %}
|
||||
<div>{% trans '暂无评论' %}</div>
|
||||
{% endfor %}
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<div class="pagination">
|
||||
|
||||
{% if reviews.pagination.has_prev %}
|
||||
<a href="?page=1" class="pagination__nav-link pagination__nav-link">«</a>
|
||||
<a href="?page={{ reviews.previous_page_number }}"
|
||||
class="pagination__nav-link pagination__nav-link--right-margin pagination__nav-link">‹</a>
|
||||
{% endif %}
|
||||
|
||||
{% for page in reviews.pagination.page_range %}
|
||||
|
||||
{% if page == reviews.pagination.current_page %}
|
||||
<a href="?page={{ page }}" class="pagination__page-link pagination__page-link--current">{{ page }}</a>
|
||||
<a href="?page={{ page }}"
|
||||
class="pagination__page-link pagination__page-link--current">{{ page }}</a>
|
||||
{% else %}
|
||||
<a href="?page={{ page }}" class="pagination__page-link">{{ page }}</a>
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{% if reviews.pagination.has_next %}
|
||||
<a href="?page={{ reviews.next_page_number }}"
|
||||
class="pagination__nav-link pagination__nav-link--left-margin">›</a>
|
||||
<a href="?page={{ reviews.pagination.last_page }}" class="pagination__nav-link">»</a>
|
||||
<a href="?page={{ reviews.pagination.last_page }}"
|
||||
class="pagination__nav-link">»</a>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid__aside" id="aside">
|
||||
{% include "sidebar_item.html" %}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="grid__aside" id="aside">{% include "sidebar_item.html" %}</div>
|
||||
</main>
|
||||
{% include "partial/_footer.html" %}
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
</html>
|
||||
|
|
49
catalog/templates/item_reviews.html
Normal file
49
catalog/templates/item_reviews.html
Normal file
|
@ -0,0 +1,49 @@
|
|||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load l10n %}
|
||||
{% load admin_url %}
|
||||
{% load mastodon %}
|
||||
{% load oauth_token %}
|
||||
{% load truncate %}
|
||||
{% load duration %}
|
||||
{% load user_actions %}
|
||||
{% for review in reviews %}
|
||||
{% if forloop.counter <= 10 %}
|
||||
<section>
|
||||
<span class="action">
|
||||
<span>
|
||||
{% liked_piece review as liked %}
|
||||
{% include 'like_stats.html' with liked=liked piece=review %}
|
||||
</span>
|
||||
<span>
|
||||
<a target="_blank"
|
||||
rel="noopener"
|
||||
{% if review.metadata.shared_link %} href="{{ review.metadata.shared_link }}" title="打开联邦网络分享链接" {% else %} class="disabled" {% endif %}><i class="fa-solid {% if review.visibility > 0 %} fa-lock {% else %} fa-globe {% endif %}"></i></a>
|
||||
</span>
|
||||
<span class="timestamp">{{ review.created_time|date }}</span>
|
||||
</span>
|
||||
<span>
|
||||
{% if review.rating_grade %}{{ review.rating_grade|rating_star }}{% endif %}
|
||||
<a href="{% url 'journal:user_profile' review.owner.mastodon_username %}"
|
||||
class="nickname"
|
||||
title="@{{ review.owner.mastodon_username }}">{{ review.owner.display_name }}</a>
|
||||
{{ review.mark.action_label | default:"" }}
|
||||
</span>
|
||||
<div>
|
||||
<span>
|
||||
<a href="{% url 'journal:review_retrieve' review.uuid %}">{{ review.title }}</a>
|
||||
</span>
|
||||
-
|
||||
{{ review.plain_content | truncate:200 }}
|
||||
</div>
|
||||
</section>
|
||||
{% else %}
|
||||
<a hx-get="{% url 'catalog:reviews' review.item.url_path review.item.uuid %}?last={{ review.created_time|date:'Y-m-d H:i:s.uO'|urlencode }}"
|
||||
hx-trigger="click"
|
||||
hx-swap="outerHTML">
|
||||
<button class="outline">显示更多</button>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% empty %}
|
||||
<div class="empty">{% trans '暂无' %}</div>
|
||||
{% endfor %}
|
|
@ -9,46 +9,18 @@
|
|||
{% load truncate %}
|
||||
{% load strip_scheme %}
|
||||
{% load thumb %}
|
||||
|
||||
{% block title %}
|
||||
<h5 class="entity-detail__title">
|
||||
{% if item.season_number %}
|
||||
{{ item.title }} {% trans '第' %}{{ item.season_number|apnumber }}{% trans '季' %} {{ item.orig_title }} Season {{ item.season_number }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
{% if item.year %}({{ item.year }}){% endif %}
|
||||
</span>
|
||||
{% else %}
|
||||
{{ item.title }} {{ item.orig_title }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
{% if item.year %}({{ item.year }}){% endif %}
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
{% for res in item.external_resources.all %}
|
||||
<a href="{{ res.url }}">
|
||||
<span class="source-label source-label__{{ res.site_name }}">{{ res.site_name.label }}</span>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</h5>
|
||||
{% endblock %}
|
||||
|
||||
<!-- class specific details -->
|
||||
{% block details %}
|
||||
<div class="entity-detail__fields">
|
||||
<div class="entity-detail__rating">
|
||||
{% if item.rating %}
|
||||
<span class="entity-detail__rating-star rating-star" data-rating-score="{{ item.rating | floatformat:'0' }}"></span>
|
||||
<span class="entity-detail__rating-score"> {{ item.rating|floatformat:1 }} </span>
|
||||
<small>({{ item.rating_count }}人评分)</small>
|
||||
{% else %}
|
||||
<span> {% trans '评分:评分人数不足' %}</span>
|
||||
<div>
|
||||
{% if item.imdb %}
|
||||
{% trans 'IMDb:' %}<a href="https://www.imdb.com/title/{{ item.imdb }}/"
|
||||
target="_blank"
|
||||
rel="noopener">{{ item.imdb }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>{% if item.imdb %}
|
||||
{% trans 'IMDb:' %}<a href="https://www.imdb.com/title/{{ item.imdb }}/" target="_blank" rel="noopener">{{ item.imdb }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>{% if item.director %}{% trans '导演:' %}
|
||||
<div>
|
||||
{% if item.director %}
|
||||
{% trans '导演:' %}
|
||||
{% for director in item.director %}
|
||||
<span {% if forloop.counter > 5 %}style="display: none;"{% endif %}>
|
||||
<span class="director">{{ director }}</span>
|
||||
|
@ -64,10 +36,14 @@
|
|||
});
|
||||
$(this).remove();
|
||||
})
|
||||
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endif %}</div>
|
||||
<div>{% if item.playwright %}{% trans '编剧:' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.playwright %}
|
||||
{% trans '编剧:' %}
|
||||
{% for playwright in item.playwright %}
|
||||
<span {% if forloop.counter > 5 %}style="display: none;"{% endif %}>
|
||||
<span class="playwright">{{ playwright }}</span>
|
||||
|
@ -83,17 +59,20 @@
|
|||
});
|
||||
$(this).remove();
|
||||
})
|
||||
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endif %}</div>
|
||||
<div>{% if item.actor %}{% trans '主演:' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.actor %}
|
||||
{% trans '主演:' %}
|
||||
{% for actor in item.actor %}
|
||||
<span {% if forloop.counter > 5 %}style="display: none;"{% endif %}>
|
||||
<span class="actor">{{ actor }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
</span>
|
||||
{% endfor %}
|
||||
|
||||
{% if item.actor|length > 5 %}
|
||||
<a href="javascript:void(0);" id="actorMore">{% trans '更多' %}</a>
|
||||
<script>
|
||||
|
@ -103,70 +82,87 @@
|
|||
});
|
||||
$(this).remove();
|
||||
})
|
||||
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}</div>
|
||||
<div>{% if item.genre %}{% trans '类型:' %}
|
||||
{% for genre in item.genre %}
|
||||
<span>{{ genre }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if item.area %}{% trans '制片国家/地区:' %}
|
||||
{% for area in item.area %}
|
||||
<span>{{ area }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if item.language %}{% trans '语言:' %}
|
||||
{% for language in item.language %}
|
||||
<span>{{ language }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="entity-detail__fields">
|
||||
<div>{% if item.duration %}{% trans '片长:' %}{{ item.duration }}{% endif %}</div>
|
||||
<div>{% if item.season_count %}{% trans '季数:' %}{{ item.season_count }}{% endif %}</div>
|
||||
<div>{% if item.episode_count %}{% trans '集数:' %}{{ item.episode_count }}{% endif %}</div>
|
||||
<div>{% if item.single_episode_length %}{% trans '单集长度:' %}{{ item.single_episode_length }}{% endif %}</div>
|
||||
|
||||
<div>{% if item.showtime %}{% trans '上映时间:' %}
|
||||
<div>
|
||||
{% if item.genre %}
|
||||
{% trans '类型:' %}
|
||||
{% for genre in item.genre %}
|
||||
<span>{{ genre }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.area %}
|
||||
{% trans '制片国家/地区:' %}
|
||||
{% for area in item.area %}
|
||||
<span>{{ area }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.language %}
|
||||
{% trans '语言:' %}
|
||||
{% for language in item.language %}
|
||||
<span>{{ language }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.duration %}
|
||||
{% trans '片长:' %}{{ item.duration }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.season_count %}
|
||||
{% trans '季数:' %}{{ item.season_count }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.episode_count %}
|
||||
{% trans '集数:' %}{{ item.episode_count }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.single_episode_length %}
|
||||
{% trans '单集长度:' %}{{ item.single_episode_length }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.showtime %}
|
||||
{% trans '上映时间:' %}
|
||||
{% for showtime in item.showtime %}
|
||||
{% for time, region in showtime.items %}
|
||||
<span>{{ time }}{% if region != '' %}({{ region }}){% endif %}</span>
|
||||
<span>{{ time }}
|
||||
{% if region != '' %}({{ region }}){% endif %}
|
||||
</span>
|
||||
{% endfor %}
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if item.other_title %}{% trans '又名:' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.other_title %}
|
||||
{% trans '又名:' %}
|
||||
{% for t in item.other_title %}
|
||||
<span>{{ t }}</span>{% if not forloop.last %} / {% endif %}
|
||||
<span>{{ t }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if item.site %}{% trans '网站:' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.site %}
|
||||
{% trans '网站:' %}
|
||||
<a href="{{ item.site }}" target="_blank" rel="noopener">{{ item.site|strip_scheme }}</a>
|
||||
{% endif %}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if item.other_info %}
|
||||
{% for k, v in item.other_info.items %}
|
||||
<div>
|
||||
{{ k }}:{{ v | urlize }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% for k, v in item.other_info.items %}<div>{{ k }}:{{ v|urlizetrunc:24 }}</div>{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if item.last_editor and item.last_editor.preference.show_last_edit %}
|
||||
<div>{% trans '最近编辑者:' %}<a href="{% url 'journal:user_profile' item.last_editor.mastodon_username %}">{{ item.last_editor | default:"" }}</a></div>
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
{% if user.is_authenticated %}
|
||||
<a href="{% url 'catalog:edit' item.url_path item.uuid %}">{% trans '编辑' %}{{ item.demonstrative }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
<!-- class specific sidebar -->
|
||||
{% block sidebar %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -9,21 +9,11 @@
|
|||
{% load truncate %}
|
||||
{% load strip_scheme %}
|
||||
{% load thumb %}
|
||||
|
||||
<!-- class specific details -->
|
||||
{% block details %}
|
||||
<div class="entity-detail__fields">
|
||||
<div class="entity-detail__rating">
|
||||
{% if item.rating and item.rating_count >= 5 %}
|
||||
<span class="entity-detail__rating-star rating-star" data-rating-score="{{ item.rating | floatformat:0 }}"></span>
|
||||
<span class="entity-detail__rating-score"> {{ item.rating | floatformat:1 }} </span>
|
||||
<small>({{ item.rating_count }}人评分)</small>
|
||||
{% else %}
|
||||
<span> {% trans '评分:评分人数不足' %}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div>{% if item.other_title %}{% trans '别名:' %}
|
||||
<div>
|
||||
{% if item.other_title %}
|
||||
{% trans '别名:' %}
|
||||
{% for other_title in item.other_title %}
|
||||
<span {% if forloop.counter > 5 %}style="display: none;"{% endif %}>
|
||||
<span class="other_title">{{ other_title }}</span>
|
||||
|
@ -39,108 +29,101 @@
|
|||
});
|
||||
$(this).remove();
|
||||
})
|
||||
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% if item.genre %}{% trans '类型:' %}
|
||||
{% if item.genre %}
|
||||
{% trans '类型:' %}
|
||||
{% for genre in item.genre %}
|
||||
<span>{{ genre }}</span>{% if not forloop.last %} / {% endif %}
|
||||
<span>{{ genre }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% if item.director %}{% trans '导演:' %}
|
||||
{% if item.director %}
|
||||
{% trans '导演:' %}
|
||||
{% for director in item.director %}
|
||||
<span>{{ director }}</span>{% if not forloop.last %} / {% endif %}
|
||||
<span>{{ director }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% if item.playwright %}{% trans '编剧:' %}
|
||||
{% if item.playwright %}
|
||||
{% trans '编剧:' %}
|
||||
{% for playwright in item.playwright %}
|
||||
<span>{{ playwright }}</span>{% if not forloop.last %} / {% endif %}
|
||||
<span>{{ playwright }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% if item.actor %}{% trans '主演:' %}
|
||||
{% if item.actor %}
|
||||
{% trans '主演:' %}
|
||||
{% for actor in item.actor %}
|
||||
<span>{{ actor }}</span>{% if not forloop.last %} / {% endif %}
|
||||
<span>{{ actor }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% if item.choreographer %}{% trans '编舞:' %}
|
||||
{% if item.choreographer %}
|
||||
{% trans '编舞:' %}
|
||||
{% for choreographer in item.choreographer %}
|
||||
<span>{{ choreographer }}</span>{% if not forloop.last %} / {% endif %}
|
||||
<span>{{ choreographer }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% if item.composer %}{% trans '作曲:' %}
|
||||
{% if item.composer %}
|
||||
{% trans '作曲:' %}
|
||||
{% for composer in item.composer %}
|
||||
<span>{{ composer }}</span>{% if not forloop.last %} / {% endif %}
|
||||
<span>{{ composer }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="entity-detail__fields">
|
||||
|
||||
<div>
|
||||
{% if item.troupe %}{% trans '剧团:' %}
|
||||
{% if item.troupe %}
|
||||
{% trans '剧团:' %}
|
||||
{% for troupe in item.troupe %}
|
||||
<span>{{ troupe }}</span>{% if not forloop.last %} / {% endif %}
|
||||
<span>{{ troupe }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% if item.theatre %}{% trans '剧场:' %}
|
||||
{% if item.theatre %}
|
||||
{% trans '剧场:' %}
|
||||
{% for theatre in item.theatre %}
|
||||
<span>{{ theatre }}</span>{% if not forloop.last %} / {% endif %}
|
||||
<span>{{ theatre }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% if item.opening_date %}{% trans '演出日期:' %}
|
||||
{% if item.opening_date %}
|
||||
{% trans '演出日期:' %}
|
||||
<span>{{ item.opening_date }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% if item.version %}{% trans '版本:' %}
|
||||
{% if item.version %}
|
||||
{% trans '版本:' %}
|
||||
{% for version in item.version %}
|
||||
<span>{{ version }}</span>{% if not forloop.last %} / {% endif %}
|
||||
<span>{{ version }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div>{% if item.official_site %}
|
||||
{% trans '官方网站:' %}{{ item.official_site|urlizetrunc:42 }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if item.last_editor and item.last_editor.preference.show_last_edit %}
|
||||
<div>{% trans '最近编辑者:' %}<a href="{% url 'journal:user_profile' item.last_editor.mastodon_username %}">{{ item.last_editor | default:"" }}</a></div>
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
{% if user.is_authenticated %}
|
||||
<a href="{% url 'catalog:edit' item.url_path item.uuid %}">{% trans '编辑' %}{{ item.demonstrative }}</a>
|
||||
{% if item.official_site %}
|
||||
{% trans '官方网站:' %}{{ item.official_site|urlizetrunc:24 }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
<!-- class specific sidebar -->
|
||||
{% block sidebar %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -9,47 +9,30 @@
|
|||
{% load truncate %}
|
||||
{% load strip_scheme %}
|
||||
{% load thumb %}
|
||||
|
||||
{% block head %}
|
||||
<script src=" https://cdn.jsdelivr.net/npm/shikwasa@2.2.0/dist/shikwasa.min.js "></script>
|
||||
<link href=" https://cdn.jsdelivr.net/npm/shikwasa@2.2.0/dist/style.min.css " rel="stylesheet"></link>
|
||||
<script src="https://cdn.jsdelivr.net/npm/shikwasa@2.2.1/dist/shikwasa.min.js"></script>
|
||||
<link href="https://cdn.jsdelivr.net/npm/shikwasa@2.2.1/dist/style.min.css"
|
||||
rel="stylesheet"></link>
|
||||
<script src="{% static 'podcast.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
<!-- class specific details -->
|
||||
{% block details %}
|
||||
<style type="text/css">
|
||||
.entity-detail .entity-detail__img {
|
||||
height: unset !important;
|
||||
}
|
||||
</style>
|
||||
<div class="entity-detail__fields">
|
||||
<div class="entity-detail__rating">
|
||||
{% if item.rating and item.rating_count >= 5 %}
|
||||
<span class="entity-detail__rating-star rating-star" data-rating-score="{{ item.rating | floatformat:0 }}"></span>
|
||||
<span class="entity-detail__rating-score"> {{ item.rating | floatformat:1 }} </span>
|
||||
<small>({{ item.rating_count }}人评分)</small>
|
||||
{% else %}
|
||||
<span> {% trans '评分:评分人数不足' %}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% if item.genre %}{% trans '类型:' %}
|
||||
{% if item.genre %}
|
||||
{% trans '类型:' %}
|
||||
{% for genre in item.genre %}
|
||||
<span>{{ genre }}</span>{% if not forloop.last %} / {% endif %}
|
||||
<span>{{ genre }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div>{% if item.official_site %}
|
||||
{% trans '网站:' %}{{ item.official_site|urlizetrunc:42 }}
|
||||
<div>
|
||||
{% if item.official_site %}
|
||||
{% trans '网站:' %}{{ item.official_site|urlizetrunc:24 }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="entity-detail__fields">
|
||||
|
||||
<div>{% if item.hosts %}{% trans '主播:' %}
|
||||
<div>
|
||||
{% if item.hosts %}
|
||||
{% trans '主播:' %}
|
||||
{% for host in item.hosts %}
|
||||
<span {% if forloop.counter > 5 %}style="display: none;"{% endif %}>
|
||||
<span class="other_title">{{ host }}</span>
|
||||
|
@ -65,42 +48,27 @@
|
|||
});
|
||||
$(this).remove();
|
||||
})
|
||||
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if item.last_editor and item.last_editor.preference.show_last_edit %}
|
||||
<div>{% trans '最近编辑者:' %}<a href="{% url 'journal:user_profile' item.last_editor.mastodon_username %}">{{ item.last_editor | default:"" }}</a></div>
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
{% if user.is_authenticated %}
|
||||
<a href="{% url 'catalog:edit' item.url_path item.uuid %}">{% trans '编辑' %}{{ item.demonstrative }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<div class="entity-desc" id="episodes">
|
||||
<section class="entity-desc" id="episodes">
|
||||
<h5 class="entity-desc__title">{% trans '近期节目' %}</h5>
|
||||
<br>
|
||||
<div hx-get="{% url 'catalog:episode_data' item.uuid %}" hx-trigger="load" hx-swap="outerHTML"></div>
|
||||
</div>
|
||||
<div hx-get="{% url 'catalog:episode_data' item.uuid %}"
|
||||
hx-trigger="load"
|
||||
hx-swap="outerHTML"></div>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
||||
<!-- class specific sidebar -->
|
||||
{% block sidebar %}
|
||||
<div class="aside-section-wrapper">
|
||||
<div class="action-panel" id="episodes">
|
||||
<div class="action-panel__button-group action-panel__button-group--center">
|
||||
<button href="#" class="podlove-subscribe-button-primary action-panel__button">{% trans '用播客应用订阅' %}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% block left_sidebar %}
|
||||
<section>
|
||||
<center>
|
||||
<button href="#" class="podlove-subscribe-button-primary outline">{% trans '用播客应用订阅' %}</button>
|
||||
</center>
|
||||
</section>
|
||||
<script>
|
||||
window.podcastData = {
|
||||
"title": "{{ item.title | escapejs }}",
|
||||
|
@ -124,5 +92,11 @@ $(()=>{
|
|||
{% endif %}
|
||||
});
|
||||
</script>
|
||||
<script class="podlove-subscribe-button" src="https://cdn.podlove.org/subscribe-button/javascripts/app.js" data-json-data="podcastData" data-buttonid="primary" data-language="en" data-hide="true" data-color="#1190C0"></script>
|
||||
<script class="podlove-subscribe-button"
|
||||
src="https://cdn.podlove.org/subscribe-button/javascripts/app.js"
|
||||
data-json-data="podcastData"
|
||||
data-buttonid="primary"
|
||||
data-language="en"
|
||||
data-hide="true"
|
||||
data-color="#1190C0"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -3,11 +3,9 @@
|
|||
{% load l10n %}
|
||||
{% load humanize %}
|
||||
{% for ep in episodes %}
|
||||
<details>
|
||||
<summary>
|
||||
<p>
|
||||
<h6 class="entity-desc__title">
|
||||
<a
|
||||
data-media="{{ ep.media_url }}"
|
||||
<a data-media="{{ ep.media_url }}"
|
||||
data-cover="{{ ep.cover_url|default:item.cover.url }}"
|
||||
class="episode gg-play-button-o"
|
||||
href="{{ ep.url }}"
|
||||
|
@ -15,32 +13,29 @@
|
|||
data-title="{{ ep.title }}"
|
||||
data-album="{{ item.title }}"
|
||||
data-hosts="{{ item.hosts|join:' / ' }}"
|
||||
style="top:4px;margin-right: 8px;">
|
||||
</a>
|
||||
style="top:4px;
|
||||
margin-right: 8px"></a>
|
||||
|
||||
{% if request.user.is_authenticated %}
|
||||
<a style="margin-right: 10px"
|
||||
title="评论单集"
|
||||
href="#"
|
||||
hx-get="{% url 'journal:comment' item.uuid ep.uuid %}"
|
||||
hx-target="body"
|
||||
hx-swap="beforeend"><i class="fa-regular fa-comment-dots"></i></a>
|
||||
{% endif %}
|
||||
<a title="打开源网站" target="_blank" rel="noopener" href="{{ ep.link }}"><i class="fa-solid fa-link"></i></a>
|
||||
{{ ep.title }}
|
||||
<small style="color:lightgrey;">{{ ep.pub_date|date }}</small>
|
||||
</h6>
|
||||
</summary>
|
||||
<p> {{ ep.brief | linebreaksbr }} </p>
|
||||
</details>
|
||||
<div style="margin-bottom: 8px;margin-left: 32px;">
|
||||
{% if request.user.is_authenticated %}
|
||||
<a class="icon" style="margin-right: 10px;" title="评论单集" href="#" hx-get="{% url 'journal:comment' item.uuid ep.uuid %}" hx-target="body" hx-swap="beforeend">
|
||||
<i class="fa-regular fa-comment-dots"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
<!-- <a class="icon" title="详细介绍" href="{{ep.link}}">
|
||||
<i class="fa-solid fa-circle-info"></i>
|
||||
</a> -->
|
||||
<a class="icon" title="打开源网站" target="_blank" rel="noopener" href="{{ep.link}}">
|
||||
<i class="fa-solid fa-arrow-up-right-from-square"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<small class="tldr-2 muted" _="on click toggle .tldr-2">{{ ep.brief | linebreaksbr }}</small>
|
||||
</p>
|
||||
{% if forloop.last %}
|
||||
<button hx-get="{% url 'catalog:episode_data' item.uuid %}?last={{ ep.pub_date|date:'Y-m-d H:i:s.uO'|urlencode }}" hx-trigger="click" hx-swap="outerHTML">显示更多</button>
|
||||
<button class="outline"
|
||||
hx-get="{% url 'catalog:episode_data' item.uuid %}?last={{ ep.pub_date|date:'Y-m-d H:i:s.uO'|urlencode }}"
|
||||
hx-trigger="click"
|
||||
hx-swap="outerHTML">显示更多</button>
|
||||
{% endif %}
|
||||
|
||||
{% empty %}
|
||||
<div>{% trans '目前没有更多内容了' %}</div>
|
||||
{% endfor %}
|
||||
|
|
|
@ -9,14 +9,17 @@
|
|||
{% load truncate %}
|
||||
{% load strip_scheme %}
|
||||
{% load thumb %}
|
||||
|
||||
{% block head %}
|
||||
<meta http-equiv="refresh" content="0;url={{ item.program.absolute_url }}?focus={{ item.uuid }}{% if request.GET.position %}&position={{ request.GET.position }}{% endif %}" />
|
||||
<meta property="og:image" content="{{ item.cover_url | default:item.program.cover_image_url }}">
|
||||
<meta property="twitter:image" content="{{ item.cover_url | default:item.program.cover_image_url }}">
|
||||
<meta http-equiv="refresh"
|
||||
content="0;url={{ item.program.absolute_url }}?focus={{ item.uuid }}{% if request.GET.position %}&position={{ request.GET.position }}{% endif %}" />
|
||||
<meta property="og:image"
|
||||
content="{{ item.cover_url | default:item.program.cover_image_url }}">
|
||||
<meta property="twitter:image"
|
||||
content="{{ item.cover_url | default:item.program.cover_image_url }}">
|
||||
{% if item.media_url %}
|
||||
<meta property="twitter:card" content="player">
|
||||
<meta property="twitter:player" content="{{ item.program.absolute_url }}/embed?focus={{ item.uuid }}{% if request.GET.position %}&position={{ request.GET.position }}{% endif %}" />
|
||||
<meta property="twitter:player"
|
||||
content="{{ item.program.absolute_url }}/embed?focus={{ item.uuid }}{% if request.GET.position %}&position={{ request.GET.position }}{% endif %}" />
|
||||
<meta property="twitter:player:width" content="300">
|
||||
<meta property="twitter:player:height" content="120">
|
||||
{% endif %}
|
||||
|
|
|
@ -9,94 +9,70 @@
|
|||
{% load highlight %}
|
||||
{% load thumb %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<html lang="en" class="classic-page">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ site_name }} - {% trans '搜索结果' %}</title>
|
||||
{% include "common_libs.html" with jquery=0 %}
|
||||
{% include "common_libs.html" with jquery=0 v2=1 %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="page-wrapper">
|
||||
<div id="content-wrapper">
|
||||
{% include 'partial/_navbar.html' %}
|
||||
|
||||
<section id="content">
|
||||
<div class="grid">
|
||||
{% include '_header.html' %}
|
||||
<main>
|
||||
<div class="grid__main">
|
||||
<div class="main-section-wrapper">
|
||||
|
||||
<div class="entity-list">
|
||||
{% if request.GET.q %}
|
||||
<h5 class="entity-list__title">“{{ request.GET.q }}” {% trans '的搜索结果' %}</h5>
|
||||
<h5>“{{ request.GET.q }}” {% trans '的搜索结果' %}</h5>
|
||||
{% endif %}
|
||||
|
||||
{% if request.GET.tag %}
|
||||
<h5 class="entity-list__title">{% trans '含有标签' %} “{{ request.GET.tag }}” {% trans '的结果' %}</h5>
|
||||
<h5>{% trans '含有标签' %} “{{ request.GET.tag }}” {% trans '的结果' %}</h5>
|
||||
{% endif %}
|
||||
|
||||
<ul class="entity-list__entities">
|
||||
<ul class="item-card-list">
|
||||
{% for item in items %}
|
||||
{% with "list_item_"|add:item.class_name|add:".html" as template %}
|
||||
{% include template %}
|
||||
{% include template with show_tags=1 %}
|
||||
{% endwith %}
|
||||
{% empty %}
|
||||
<li class="entity-list__entity">
|
||||
{% trans '无站内条目匹配' %}
|
||||
</li>
|
||||
<li class="empty">{% trans '无站内条目匹配' %}</li>
|
||||
{% endfor %}
|
||||
{% if request.GET.q and user.is_authenticated %}
|
||||
<li class="entity-list__entity" hx-get="{% url 'catalog:external_search' %}?q={{ request.GET.q }}&c={{ request.GET.c }}&page={% if pagination.current_page %}{{ pagination.current_page }}{% else %}1{% endif %}" hx-trigger="load" hx-swap="outerHTML">
|
||||
<li hx-get="{% url 'catalog:external_search' %}?q={{ request.GET.q }}&c={{ request.GET.c }}&page={% if pagination.current_page %}{{ pagination.current_page }}{% else %}1{% endif %}"
|
||||
hx-trigger="load"
|
||||
hx-swap="outerHTML">
|
||||
{% trans '正在实时搜索站外条目' %}
|
||||
<span><i class="fas fa-fan fa-spin"></i></span>
|
||||
<span><i class="fa-solid fa-compact-disc fa-spin loading"></i></span>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="pagination">
|
||||
|
||||
{% if pagination.has_prev %}
|
||||
<a href="?page=1&{% if request.GET.q %}q={{ request.GET.q }}{% elif request.GET.tag %}tag={{ request.GET.tag }}{% endif %}{% if request.GET.c %}&c={{ request.GET.c }}{% endif %}" class="pagination__nav-link pagination__nav-link">«</a>
|
||||
<a href="?page={{ pagination.previous_page }}&{% if request.GET.q %}q={{ request.GET.q }}{% elif request.GET.tag %}tag={{ request.GET.tag }}{% endif %}{% if request.GET.c %}&c={{ request.GET.c }}{% endif %}" class="pagination__nav-link pagination__nav-link--right-margin pagination__nav-link">‹</a>
|
||||
<a href="?page=1&{% if request.GET.q %}q={{ request.GET.q }}{% elif request.GET.tag %}tag={{ request.GET.tag }}{% endif %}{% if request.GET.c %}&c={{ request.GET.c }}{% endif %}"
|
||||
class="pagination__nav-link pagination__nav-link">«</a>
|
||||
<a href="?page={{ pagination.previous_page }}&{% if request.GET.q %}q={{ request.GET.q }}{% elif request.GET.tag %}tag={{ request.GET.tag }}{% endif %}{% if request.GET.c %}&c={{ request.GET.c }}{% endif %}"
|
||||
class="pagination__nav-link pagination__nav-link--right-margin pagination__nav-link">‹</a>
|
||||
{% endif %}
|
||||
|
||||
{% for page in pagination.page_range %}
|
||||
|
||||
{% if page == pagination.current_page %}
|
||||
<a href="?page={{ page }}&{% if request.GET.q %}q={{ request.GET.q }}{% elif request.GET.tag %}tag={{ request.GET.tag }}{% endif %}{% if request.GET.c %}&c={{ request.GET.c }}{% endif %}" class="pagination__page-link pagination__page-link--current">{{ page }}</a>
|
||||
<a href="?page={{ page }}&{% if request.GET.q %}q={{ request.GET.q }}{% elif request.GET.tag %}tag={{ request.GET.tag }}{% endif %}{% if request.GET.c %}&c={{ request.GET.c }}{% endif %}"
|
||||
class="pagination__page-link pagination__page-link--current">{{ page }}</a>
|
||||
{% else %}
|
||||
<a href="?page={{ page }}&{% if request.GET.q %}q={{ request.GET.q }}{% elif request.GET.tag %}tag={{ request.GET.tag }}{% endif %}{% if request.GET.c %}&c={{ request.GET.c }}{% endif %}" class="pagination__page-link">{{ page }}</a>
|
||||
<a href="?page={{ page }}&{% if request.GET.q %}q={{ request.GET.q }}{% elif request.GET.tag %}tag={{ request.GET.tag }}{% endif %}{% if request.GET.c %}&c={{ request.GET.c }}{% endif %}"
|
||||
class="pagination__page-link">{{ page }}</a>
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{% if pagination.has_next %}
|
||||
<a href="?page={{ pagination.next_page }}&{% if request.GET.q %}q={{ request.GET.q }}{% elif request.GET.tag %}tag={{ request.GET.tag }}{% endif %}{% if request.GET.c %}&c={{ request.GET.c }}{% endif %}" class="pagination__nav-link pagination__nav-link--left-margin">›</a>
|
||||
<a href="?page={{ pagination.last_page }}&{% if request.GET.q %}q={{ request.GET.q }}{% elif request.GET.tag %}tag={{ request.GET.tag }}{% endif %}{% if request.GET.c %}&c={{ request.GET.c }}{% endif %}" class="pagination__nav-link">»</a>
|
||||
<a href="?page={{ pagination.next_page }}&{% if request.GET.q %}q={{ request.GET.q }}{% elif request.GET.tag %}tag={{ request.GET.tag }}{% endif %}{% if request.GET.c %}&c={{ request.GET.c }}{% endif %}"
|
||||
class="pagination__nav-link pagination__nav-link--left-margin">›</a>
|
||||
<a href="?page={{ pagination.last_page }}&{% if request.GET.q %}q={{ request.GET.q }}{% elif request.GET.tag %}tag={{ request.GET.tag }}{% endif %}{% if request.GET.c %}&c={{ request.GET.c }}{% endif %}"
|
||||
class="pagination__nav-link">»</a>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{% include "search_sidebar.html" %}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
{% include 'partial/_footer.html' %}
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
document.body.addEventListener('htmx:configRequest', (event) => {
|
||||
event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
</html>
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load l10n %}
|
||||
|
||||
<div class="grid__aside">
|
||||
<div class="aside-section-wrapper">
|
||||
|
||||
<div class="add-entity-entries">
|
||||
<div class="add-entity-entries__entry">
|
||||
<div class="add-entity-entries__label">
|
||||
{% trans '没有想要的结果?' %}
|
||||
</div>
|
||||
<style>
|
||||
.add-entity-entries__button {
|
||||
margin: 4px;
|
||||
}
|
||||
</style>
|
||||
<aside class="grid__aside bottom">
|
||||
<article>
|
||||
<div class="add-entity-entries__label">{% trans '没有想要的结果?' %}</div>
|
||||
<p>
|
||||
如果在
|
||||
{% for site in sites %}
|
||||
|
@ -18,29 +17,26 @@
|
|||
{% endfor %}
|
||||
找到了条目,可以在搜索栏中输入完整链接提交。
|
||||
</p>
|
||||
<p>
|
||||
当然也可以手工创建条目。
|
||||
</p>
|
||||
<a href="{% url 'catalog:create' 'Edition' %}">
|
||||
<button class="add-entity-entries__button">{% trans '添加书' %}</button>
|
||||
</a>
|
||||
<a href="{% url 'catalog:create' 'Movie' %}">
|
||||
<button class="add-entity-entries__button">{% trans '添加电影' %}</button>
|
||||
</a>
|
||||
<a href="{% url 'catalog:create' 'TVShow' %}">
|
||||
<button class="add-entity-entries__button">{% trans '添加剧集' %}</button>
|
||||
</a>
|
||||
<a href="{% url 'catalog:create' 'Podcast' %}">
|
||||
<button class="add-entity-entries__button">{% trans '添加播客' %}</button>
|
||||
</a>
|
||||
<a href="{% url 'catalog:create' 'Album' %}">
|
||||
<button class="add-entity-entries__button">{% trans '添加专辑' %}</button>
|
||||
</a>
|
||||
<a href="{% url 'catalog:create' 'Game' %}">
|
||||
<button class="add-entity-entries__button">{% trans '添加游戏' %}</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<p>当然也可以手工创建条目:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{% url 'catalog:create' 'Edition' %}">{% trans '添加书' %}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'catalog:create' 'Movie' %}">{% trans '添加电影' %}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'catalog:create' 'TVShow' %}">{% trans '添加剧集' %}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'catalog:create' 'Podcast' %}">{% trans '添加播客' %}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'catalog:create' 'Album' %}">{% trans '添加专辑' %}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'catalog:create' 'Game' %}">{% trans '添加游戏' %}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</article>
|
||||
</aside>
|
||||
|
|
|
@ -2,30 +2,26 @@
|
|||
{% load i18n %}
|
||||
{% load truncate %}
|
||||
{% load thumb %}
|
||||
<div class="aside-section-wrapper">
|
||||
<div class="entity-card">
|
||||
<div class="entity-card__img-wrapper">
|
||||
<a href="{% url 'catalog:retrieve' item.url_path item.uuid %}"><img src="{{ item.cover|thumb:'normal' }}" alt="" class="entity-card__img"></a>
|
||||
<article class="item">
|
||||
<div>
|
||||
<a href="{% url 'catalog:retrieve' item.url_path item.uuid %}">
|
||||
<img src="{{ item.cover|thumb:'normal' }}" alt="" class="entity-card__img">
|
||||
</a>
|
||||
</div>
|
||||
<div class="entity-card__info-wrapper">
|
||||
<h5 class="entity-card__title"><a href="{% url 'catalog:retrieve' item.url_path item.uuid %}">{{ item.title }}</a>
|
||||
<footer>
|
||||
<h4>
|
||||
<a href="{% url 'catalog:retrieve' item.url_path item.uuid %}">{{ item.title }}</a>
|
||||
{% for res in item.external_resources.all %}
|
||||
<a href="{{ res.url }}">
|
||||
<span class="source-label source-label__{{ res.site_name }}">{{ res.site_name.label }}</span>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</h5>
|
||||
|
||||
{% if item.isbn %}
|
||||
<div>ISBN: {{ item.isbn }}</div>
|
||||
{% endif %}
|
||||
|
||||
<div>{% if item.pub_house %}{% trans '出版社:' %}{{ item.pub_house }}{% endif %}</div>
|
||||
{% if item.rating %}
|
||||
{% trans '评分: ' %}<span class="entity-card__rating-star rating-star" data-rating-score="{{ item.rating | floatformat:0 }}"></span>
|
||||
<span class="entity-card__rating-score rating-score">{{ item.rating | floatformat:1 }}</span>
|
||||
</h4>
|
||||
{% if item.isbn %}<div>ISBN: {{ item.isbn }}</div>{% endif %}
|
||||
<div>
|
||||
{% if item.pub_house %}
|
||||
{% trans '出版社:' %}{{ item.pub_house }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</article>
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
{% load truncate %}
|
||||
{% load strip_scheme %}
|
||||
{% load thumb %}
|
||||
|
||||
{% block title %}
|
||||
<h5 class="entity-detail__title">
|
||||
{% if item.season_number %}
|
||||
|
@ -23,7 +22,6 @@
|
|||
{% if item.year %}({{ item.year }}){% endif %}
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
{% for res in item.external_resources.all %}
|
||||
<a href="{{ res.url }}">
|
||||
<span class="source-label source-label__{{ res.site_name }}">{{ res.site_name.label }}</span>
|
||||
|
@ -31,24 +29,18 @@
|
|||
{% endfor %}
|
||||
</h5>
|
||||
{% endblock %}
|
||||
|
||||
<!-- class specific details -->
|
||||
{% block details %}
|
||||
<div class="entity-detail__fields">
|
||||
<div class="entity-detail__rating">
|
||||
{% if item.rating and item.rating_count >= 5 %}
|
||||
<span class="entity-detail__rating-star rating-star" data-rating-score="{{ item.rating | floatformat:"0" }}"></span>
|
||||
<span class="entity-detail__rating-score"> {{ item.rating | floatformat:1 }} </span>
|
||||
<small>({{ item.rating_count }}人评分)</small>
|
||||
{% else %}
|
||||
<span> {% trans '评分:评分人数不足' %}</span>
|
||||
<div>
|
||||
{% if item.imdb %}
|
||||
{% trans 'IMDb:' %}<a href="https://www.imdb.com/title/{{ item.imdb }}/"
|
||||
target="_blank"
|
||||
rel="noopener">{{ item.imdb }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>{% if item.imdb %}
|
||||
{% trans 'IMDb:' %}<a href="https://www.imdb.com/title/{{ item.imdb }}/" target="_blank" rel="noopener">{{ item.imdb }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>{% if item.director %}{% trans '导演:' %}
|
||||
<div>
|
||||
{% if item.director %}
|
||||
{% trans '导演:' %}
|
||||
{% for director in item.director %}
|
||||
<span {% if forloop.counter > 5 %}style="display: none;"{% endif %}>
|
||||
<span class="director">{{ director }}</span>
|
||||
|
@ -64,10 +56,14 @@
|
|||
});
|
||||
$(this).remove();
|
||||
})
|
||||
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endif %}</div>
|
||||
<div>{% if item.playwright %}{% trans '编剧:' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.playwright %}
|
||||
{% trans '编剧:' %}
|
||||
{% for playwright in item.playwright %}
|
||||
<span {% if forloop.counter > 5 %}style="display: none;"{% endif %}>
|
||||
<span class="playwright">{{ playwright }}</span>
|
||||
|
@ -83,17 +79,20 @@
|
|||
});
|
||||
$(this).remove();
|
||||
})
|
||||
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endif %}</div>
|
||||
<div>{% if item.actor %}{% trans '主演:' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.actor %}
|
||||
{% trans '主演:' %}
|
||||
{% for actor in item.actor %}
|
||||
<span {% if forloop.counter > 5 %}style="display: none;"{% endif %}>
|
||||
<span class="actor">{{ actor }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
</span>
|
||||
{% endfor %}
|
||||
|
||||
{% if item.actor|length > 5 %}
|
||||
<a href="javascript:void(0);" id="actorMore">{% trans '更多' %}</a>
|
||||
<script>
|
||||
|
@ -103,34 +102,65 @@
|
|||
});
|
||||
$(this).remove();
|
||||
})
|
||||
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}</div>
|
||||
<div>{% if item.genre %}{% trans '类型:' %}
|
||||
{% for genre in item.genre %}
|
||||
<span>{{ genre }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if item.area %}{% trans '制片国家/地区:' %}
|
||||
{% for area in item.area %}
|
||||
<span>{{ area }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if item.language %}{% trans '语言:' %}
|
||||
{% for language in item.language %}
|
||||
<span>{{ language }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.genre %}
|
||||
{% trans '类型:' %}
|
||||
{% for genre in item.genre %}
|
||||
<span>{{ genre }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.area %}
|
||||
{% trans '制片国家/地区:' %}
|
||||
{% for area in item.area %}
|
||||
<span>{{ area }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.language %}
|
||||
{% trans '语言:' %}
|
||||
{% for language in item.language %}
|
||||
<span>{{ language }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.season_number %}
|
||||
{% trans '本季序号:' %}{{ item.season_number }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.episode_count %}
|
||||
{% trans '本季集数:' %}{{ item.episode_count }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="entity-detail__fields">
|
||||
<div>{% if item.season_number %}{% trans '本季序号:' %}{{ item.season_number }}{% endif %}</div>
|
||||
<div>{% if item.episode_count %}{% trans '本季集数:' %}{{ item.episode_count }}{% endif %}</div>
|
||||
<div></div>
|
||||
<div>{% if item.show %}{% trans '所属剧集:' %}<a href="{{ item.show.url }}">{{ item.show.title }}{% endif %}</a></div>
|
||||
<div>{% if item.season_count %}{% trans '总季数:' %}{{ item.season_count }}{% endif %}</div>
|
||||
<div>{% if item.single_episode_length %}{% trans '单集长度:' %}{{ item.single_episode_length }}{% endif %}</div>
|
||||
<div>
|
||||
{% if item.show %}
|
||||
{% trans '所属剧集:' %}<a href="{{ item.show.url }}">{{ item.show.title }}
|
||||
{% endif %}
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
{% if item.season_count %}
|
||||
{% trans '总季数:' %}{{ item.season_count }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.single_episode_length %}
|
||||
{% trans '单集长度:' %}{{ item.single_episode_length }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% with item.all_seasons as seasons %}
|
||||
{% if seasons %}
|
||||
<div>
|
||||
|
@ -143,44 +173,37 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
<div>{% if item.showtime %}{% trans '上映时间:' %}
|
||||
<div>
|
||||
{% if item.showtime %}
|
||||
{% trans '上映时间:' %}
|
||||
{% for showtime in item.showtime %}
|
||||
{% for time, region in showtime.items %}
|
||||
<span>{{ time }}{% if region != '' %}({{ region }}){% endif %}</span>
|
||||
<span>{{ time }}
|
||||
{% if region != '' %}({{ region }}){% endif %}
|
||||
</span>
|
||||
{% endfor %}
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if item.other_title %}{% trans '又名:' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.other_title %}
|
||||
{% trans '又名:' %}
|
||||
{% for t in item.other_title %}
|
||||
<span>{{ t }}</span>{% if not forloop.last %} / {% endif %}
|
||||
<span>{{ t }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if item.site %}{% trans '网站:' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.site %}
|
||||
{% trans '网站:' %}
|
||||
<a href="{{ item.site }}" target="_blank" rel="noopener">{{ item.site|strip_scheme }}</a>
|
||||
{% endif %}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if item.other_info %}
|
||||
{% for k, v in item.other_info.items %}
|
||||
<div>
|
||||
{{ k }}:{{ v | urlize }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% for k, v in item.other_info.items %}<div>{{ k }}:{{ v|urlizetrunc:24 }}</div>{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if item.last_editor and item.last_editor.preference.show_last_edit %}
|
||||
<div>{% trans '最近编辑者:' %}<a href="{% url 'journal:user_profile' item.last_editor.mastodon_username %}">{{ item.last_editor | default:"" }}</a></div>
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
{% if user.is_authenticated %}
|
||||
<a href="{% url 'catalog:edit' item.url_path item.uuid %}">{% trans '编辑' %}{{ item.demonstrative }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
<!-- class specific sidebar -->
|
||||
{% block sidebar %}
|
||||
{% endblock %}
|
||||
{% block sidebar %}{% endblock %}
|
||||
|
|
|
@ -9,46 +9,18 @@
|
|||
{% load truncate %}
|
||||
{% load strip_scheme %}
|
||||
{% load thumb %}
|
||||
|
||||
{% block title %}
|
||||
<h5 class="entity-detail__title">
|
||||
{% if item.season_number %}
|
||||
{{ item.title }} {% trans '第' %}{{ item.season_number|apnumber }}{% trans '季' %} {{ item.orig_title }} Season {{ item.season_number }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
{% if item.year %}({{ item.year }}){% endif %}
|
||||
</span>
|
||||
{% else %}
|
||||
{{ item.title }} {{ item.orig_title }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
{% if item.year %}({{ item.year }}){% endif %}
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
{% for res in item.external_resources.all %}
|
||||
<a href="{{ res.url }}">
|
||||
<span class="source-label source-label__{{ res.site_name }}">{{ res.site_name.label }}</span>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</h5>
|
||||
{% endblock %}
|
||||
|
||||
<!-- class specific details -->
|
||||
{% block details %}
|
||||
<div class="entity-detail__fields">
|
||||
<div class="entity-detail__rating">
|
||||
{% if item.rating and item.rating_count >= 5 %}
|
||||
<span class="entity-detail__rating-star rating-star" data-rating-score="{{ item.rating | floatformat:0 }}"></span>
|
||||
<span class="entity-detail__rating-score"> {{ item.rating | floatformat:1 }} </span>
|
||||
<small>({{ item.rating_count }}人评分)</small>
|
||||
{% else %}
|
||||
<span> {% trans '评分:评分人数不足' %}</span>
|
||||
<div>
|
||||
{% if item.imdb %}
|
||||
{% trans 'IMDb:' %}<a href="https://www.imdb.com/title/{{ item.imdb }}/"
|
||||
target="_blank"
|
||||
rel="noopener">{{ item.imdb }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>{% if item.imdb %}
|
||||
{% trans 'IMDb:' %}<a href="https://www.imdb.com/title/{{ item.imdb }}/" target="_blank" rel="noopener">{{ item.imdb }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>{% if item.director %}{% trans '导演:' %}
|
||||
<div>
|
||||
{% if item.director %}
|
||||
{% trans '导演:' %}
|
||||
{% for director in item.director %}
|
||||
<span {% if forloop.counter > 5 %}style="display: none;"{% endif %}>
|
||||
<span class="director">{{ director }}</span>
|
||||
|
@ -64,10 +36,14 @@
|
|||
});
|
||||
$(this).remove();
|
||||
})
|
||||
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endif %}</div>
|
||||
<div>{% if item.playwright %}{% trans '编剧:' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.playwright %}
|
||||
{% trans '编剧:' %}
|
||||
{% for playwright in item.playwright %}
|
||||
<span {% if forloop.counter > 5 %}style="display: none;"{% endif %}>
|
||||
<span class="playwright">{{ playwright }}</span>
|
||||
|
@ -83,17 +59,20 @@
|
|||
});
|
||||
$(this).remove();
|
||||
})
|
||||
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endif %}</div>
|
||||
<div>{% if item.actor %}{% trans '主演:' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.actor %}
|
||||
{% trans '主演:' %}
|
||||
{% for actor in item.actor %}
|
||||
<span {% if forloop.counter > 5 %}style="display: none;"{% endif %}>
|
||||
<span class="actor">{{ actor }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
</span>
|
||||
{% endfor %}
|
||||
|
||||
{% if item.actor|length > 5 %}
|
||||
<a href="javascript:void(0);" id="actorMore">{% trans '更多' %}</a>
|
||||
<script>
|
||||
|
@ -103,32 +82,53 @@
|
|||
});
|
||||
$(this).remove();
|
||||
})
|
||||
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}</div>
|
||||
<div>{% if item.genre %}{% trans '类型:' %}
|
||||
{% for genre in item.genre %}
|
||||
<span>{{ genre }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if item.area %}{% trans '制片国家/地区:' %}
|
||||
{% for area in item.area %}
|
||||
<span>{{ area }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if item.language %}{% trans '语言:' %}
|
||||
{% for language in item.language %}
|
||||
<span>{{ language }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.genre %}
|
||||
{% trans '类型:' %}
|
||||
{% for genre in item.genre %}
|
||||
<span>{{ genre }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.area %}
|
||||
{% trans '制片国家/地区:' %}
|
||||
{% for area in item.area %}
|
||||
<span>{{ area }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.language %}
|
||||
{% trans '语言:' %}
|
||||
{% for language in item.language %}
|
||||
<span>{{ language }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.season_count %}
|
||||
{% trans '季数:' %}{{ item.season_count }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.episode_count %}
|
||||
{% trans '集数:' %}{{ item.episode_count }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.single_episode_length %}
|
||||
{% trans '单集长度:' %}{{ item.single_episode_length }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="entity-detail__fields">
|
||||
<div>{% if item.season_count %}{% trans '季数:' %}{{ item.season_count }}{% endif %}</div>
|
||||
<div>{% if item.episode_count %}{% trans '集数:' %}{{ item.episode_count }}{% endif %}</div>
|
||||
<div>{% if item.single_episode_length %}{% trans '单集长度:' %}{{ item.single_episode_length }}{% endif %}</div>
|
||||
|
||||
{% with item.all_seasons as seasons %}
|
||||
{% if seasons %}
|
||||
<div>
|
||||
|
@ -141,47 +141,35 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
<div>{% if item.showtime %}{% trans '播出时间:' %}
|
||||
<div>
|
||||
{% if item.showtime %}
|
||||
{% trans '播出时间:' %}
|
||||
{% for showtime in item.showtime %}
|
||||
{% for time, region in showtime.items %}
|
||||
<span>{{ time }}{% if region != '' %}({{ region }}){% endif %}</span>
|
||||
<span>{{ time }}
|
||||
{% if region != '' %}({{ region }}){% endif %}
|
||||
</span>
|
||||
{% endfor %}
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if item.other_title %}{% trans '又名:' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.other_title %}
|
||||
{% trans '又名:' %}
|
||||
{% for t in item.other_title %}
|
||||
<span>{{ t }}</span>{% if not forloop.last %} / {% endif %}
|
||||
<span>{{ t }}</span>
|
||||
{% if not forloop.last %}/{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if item.site %}{% trans '网站:' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% if item.site %}
|
||||
{% trans '网站:' %}
|
||||
<a href="{{ item.site }}" target="_blank" rel="noopener">{{ item.site|strip_scheme }}</a>
|
||||
{% endif %}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if item.other_info %}
|
||||
{% for k, v in item.other_info.items %}
|
||||
<div>
|
||||
{{ k }}:{{ v | urlize }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% for k, v in item.other_info.items %}<div>{{ k }}:{{ v|urlizetrunc:24 }}</div>{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if item.last_editor and item.last_editor.preference.show_last_edit %}
|
||||
<div>{% trans '最近编辑者:' %}<a href="{% url 'journal:user_profile' item.last_editor.mastodon_username %}">{{ item.last_editor | default:"" }}</a></div>
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
{% if user.is_authenticated %}
|
||||
<a href="{% url 'catalog:edit' item.url_path item.uuid %}">{% trans '编辑' %}{{ item.demonstrative }}</a>
|
||||
{% endif %}
|
||||
{% if user.is_staff %}
|
||||
/<a href="{% url 'catalog:delete' item.url_path item.uuid %}"> {% trans '删除' %}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
<!-- class specific sidebar -->
|
||||
{% block sidebar %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -9,11 +9,7 @@
|
|||
{% load truncate %}
|
||||
{% load strip_scheme %}
|
||||
{% load thumb %}
|
||||
|
||||
<!-- class specific details -->
|
||||
{% block details %}
|
||||
{% endblock %}
|
||||
|
||||
{% block details %}{% endblock %}
|
||||
<!-- class specific sidebar -->
|
||||
{% block sidebar %}
|
||||
{% endblock %}
|
||||
{% block sidebar %}{% endblock %}
|
||||
|
|
|
@ -72,10 +72,24 @@ urlpatterns = [
|
|||
recast,
|
||||
name="recast",
|
||||
),
|
||||
re_path(
|
||||
r"^(?P<item_path>"
|
||||
+ _get_all_url_paths()
|
||||
+ ")/(?P<item_uuid>[A-Za-z0-9]{21,22})/comments",
|
||||
comments,
|
||||
name="comments",
|
||||
),
|
||||
re_path(
|
||||
r"^(?P<item_path>"
|
||||
+ _get_all_url_paths()
|
||||
+ ")/(?P<item_uuid>[A-Za-z0-9]{21,22})/reviews",
|
||||
reviews,
|
||||
name="reviews",
|
||||
),
|
||||
re_path(
|
||||
r"^(?P<item_path>"
|
||||
+ _get_all_url_paths()
|
||||
+ ")/(?P<item_uuid>[A-Za-z0-9]{21,22})/review_list",
|
||||
review_list,
|
||||
name="review_list",
|
||||
),
|
||||
|
|
136
catalog/views.py
136
catalog/views.py
|
@ -11,7 +11,7 @@ from django.core.paginator import Paginator
|
|||
from catalog.common.models import ExternalResource, IdealIdTypes
|
||||
from .models import *
|
||||
from django.views.decorators.clickjacking import xframe_options_exempt
|
||||
from journal.models import Mark, ShelfMember, Review, query_item_category
|
||||
from journal.models import Mark, ShelfMember, Review, Comment, query_item_category
|
||||
from journal.models import (
|
||||
query_visible,
|
||||
query_following,
|
||||
|
@ -85,32 +85,28 @@ def retrieve(request, item_path, item_uuid):
|
|||
)
|
||||
mark = None
|
||||
review = None
|
||||
mark_list = None
|
||||
review_list = None
|
||||
my_collections = []
|
||||
collection_list = []
|
||||
shelf_types = [(n[1], n[2]) for n in iter(ShelfTypeNames) if n[0] == item.category]
|
||||
if request.user.is_authenticated:
|
||||
visible = query_visible(request.user)
|
||||
mark = Mark(request.user, item)
|
||||
review = mark.review
|
||||
my_collections = item.collections.all().filter(owner=request.user)
|
||||
collection_list = (
|
||||
item.collections.all()
|
||||
.exclude(owner=request.user)
|
||||
.filter(visible)
|
||||
.annotate(like_counts=Count("likes"))
|
||||
.order_by("-like_counts")
|
||||
)
|
||||
mark_query = (
|
||||
ShelfMember.objects.filter(item=item)
|
||||
.filter(visible)
|
||||
.order_by("-created_time")
|
||||
else:
|
||||
collection_list = (
|
||||
item.collections.all()
|
||||
.filter(visibility=0)
|
||||
.annotate(like_counts=Count("likes"))
|
||||
.order_by("-like_counts")
|
||||
)
|
||||
mark_list = [member.mark for member in mark_query[:NUM_REVIEWS_ON_ITEM_PAGE]]
|
||||
review_list = (
|
||||
Review.objects.filter(item=item)
|
||||
.filter(visible)
|
||||
.order_by("-created_time")[:NUM_REVIEWS_ON_ITEM_PAGE]
|
||||
)
|
||||
|
||||
return render(
|
||||
request,
|
||||
item.class_name + ".html",
|
||||
|
@ -119,8 +115,7 @@ def retrieve(request, item_path, item_uuid):
|
|||
"focus_item": focus_item,
|
||||
"mark": mark,
|
||||
"review": review,
|
||||
"mark_list": mark_list,
|
||||
"review_list": review_list,
|
||||
"my_collections": my_collections,
|
||||
"collection_list": collection_list,
|
||||
"shelf_types": shelf_types,
|
||||
},
|
||||
|
@ -273,7 +268,7 @@ def episode_data(request, item_uuid):
|
|||
if request.GET.get("last"):
|
||||
qs = qs.filter(pub_date__lt=request.GET.get("last"))
|
||||
return render(
|
||||
request, "podcast_episode_data.html", {"item": item, "episodes": qs[:10]}
|
||||
request, "podcast_episode_data.html", {"item": item, "episodes": qs[:5]}
|
||||
)
|
||||
|
||||
|
||||
|
@ -326,27 +321,62 @@ def review_list(request, item_path, item_uuid):
|
|||
|
||||
|
||||
@login_required
|
||||
def comments(request, item_path, item_uuid):
|
||||
item = get_object_or_404(Item, uid=get_uuid_or_404(item_uuid))
|
||||
if not item:
|
||||
raise Http404()
|
||||
queryset = Comment.objects.filter(item=item).order_by("-created_time")
|
||||
queryset = queryset.filter(query_visible(request.user))
|
||||
before_time = request.GET.get("last")
|
||||
if before_time:
|
||||
queryset = queryset.filter(created_time__lte=before_time)
|
||||
return render(
|
||||
request,
|
||||
"item_comments.html",
|
||||
{
|
||||
"comments": queryset[:11],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@login_required
|
||||
def reviews(request, item_path, item_uuid):
|
||||
item = get_object_or_404(Item, uid=get_uuid_or_404(item_uuid))
|
||||
if not item:
|
||||
raise Http404()
|
||||
queryset = Review.objects.filter(item=item).order_by("-created_time")
|
||||
queryset = queryset.filter(query_visible(request.user))
|
||||
before_time = request.GET.get("last")
|
||||
if before_time:
|
||||
queryset = queryset.filter(created_time__lte=before_time)
|
||||
return render(
|
||||
request,
|
||||
"item_reviews.html",
|
||||
{
|
||||
"reviews": queryset[:11],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def discover(request):
|
||||
if request.method != "GET":
|
||||
raise BadRequest()
|
||||
user = request.user
|
||||
if user.is_authenticated:
|
||||
layout = user.get_preference().discover_layout
|
||||
top_tags = user.tag_manager.all_tags[:10]
|
||||
else:
|
||||
layout = []
|
||||
top_tags = []
|
||||
|
||||
cache_key = "public_gallery_list"
|
||||
cache_key = "public_gallery"
|
||||
gallery_list = cache.get(cache_key, [])
|
||||
|
||||
for gallery in gallery_list:
|
||||
ids = (
|
||||
random.sample(gallery["item_ids"], 10)
|
||||
if len(gallery["item_ids"]) > 10
|
||||
else gallery["item_ids"]
|
||||
)
|
||||
gallery["items"] = Item.objects.filter(id__in=ids)
|
||||
# for gallery in gallery_list:
|
||||
# ids = (
|
||||
# random.sample(gallery["item_ids"], 10)
|
||||
# if len(gallery["item_ids"]) > 10
|
||||
# else gallery["item_ids"]
|
||||
# )
|
||||
# gallery["items"] = Item.objects.filter(id__in=ids)
|
||||
|
||||
if user.is_authenticated:
|
||||
podcast_ids = [
|
||||
|
@ -355,41 +385,39 @@ def discover(request):
|
|||
ShelfType.PROGRESS, ItemCategory.Podcast
|
||||
)
|
||||
]
|
||||
episodes = PodcastEpisode.objects.filter(program_id__in=podcast_ids).order_by(
|
||||
"-pub_date"
|
||||
)[:5]
|
||||
gallery_list.insert(
|
||||
0,
|
||||
{
|
||||
"name": "my_recent_podcasts",
|
||||
"title": "在听播客的近期更新",
|
||||
"items": episodes,
|
||||
},
|
||||
recent_podcast_episodes = PodcastEpisode.objects.filter(
|
||||
program_id__in=podcast_ids
|
||||
).order_by("-pub_date")[:10]
|
||||
books_in_progress = Edition.objects.filter(
|
||||
id__in=[
|
||||
p.item_id
|
||||
for p in user.shelf_manager.get_members(
|
||||
ShelfType.PROGRESS, ItemCategory.Book
|
||||
).order_by("-created_time")[:10]
|
||||
]
|
||||
)
|
||||
# books = Edition.objects.filter(
|
||||
# id__in=[
|
||||
# p.item_id
|
||||
# for p in user.shelf_manager.get_members(
|
||||
# ShelfType.PROGRESS, ItemCategory.Book
|
||||
# ).order_by("-created_time")[:10]
|
||||
# ]
|
||||
# )
|
||||
# gallery_list.insert(
|
||||
# 0,
|
||||
# {
|
||||
# "name": "my_books_inprogress",
|
||||
# "title": "正在读的书",
|
||||
# "items": books,
|
||||
# },
|
||||
# )
|
||||
tvshows_in_progress = Item.objects.filter(
|
||||
id__in=[
|
||||
p.item_id
|
||||
for p in user.shelf_manager.get_members(
|
||||
ShelfType.PROGRESS, ItemCategory.TV
|
||||
).order_by("-created_time")[:10]
|
||||
]
|
||||
)
|
||||
else:
|
||||
recent_podcast_episodes = []
|
||||
books_in_progress = []
|
||||
tvshows_in_progress = []
|
||||
|
||||
return render(
|
||||
request,
|
||||
"discover.html",
|
||||
{
|
||||
"user": user,
|
||||
"top_tags": top_tags,
|
||||
"gallery_list": gallery_list,
|
||||
"recent_podcast_episodes": recent_podcast_episodes,
|
||||
"books_in_progress": books_in_progress,
|
||||
"tvshows_in_progress": tvshows_in_progress,
|
||||
"layout": layout,
|
||||
},
|
||||
)
|
||||
|
|
|
@ -26,6 +26,5 @@
|
|||
|
||||
.wday, .month {
|
||||
font-variant: small-caps;
|
||||
color: #222222;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
|
|
@ -180,8 +180,8 @@ div.jsoneditor-menu {
|
|||
}
|
||||
|
||||
.donut {
|
||||
margin-left: 20%;
|
||||
width: 60%;
|
||||
margin-left: 10%;
|
||||
width: 80%;
|
||||
aspect-ratio : 1 / 1;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
|
@ -198,7 +198,7 @@ div.jsoneditor-menu {
|
|||
justify-content: center;
|
||||
}
|
||||
|
||||
progress {
|
||||
/* progress {
|
||||
border-radius: 7px;
|
||||
width: 80%;
|
||||
height: 10px;
|
||||
|
@ -209,7 +209,7 @@ progress {
|
|||
}
|
||||
::-webkit-progress-value {
|
||||
background-color: #00a1cc;
|
||||
}
|
||||
} */
|
||||
|
||||
.markdownx-editor {
|
||||
font-family: monospace;
|
||||
|
@ -266,6 +266,6 @@ summary::-webkit-details-marker {
|
|||
transform: rotate(360deg);
|
||||
}
|
||||
|
||||
.fa-lock, .fa-spin {
|
||||
.action-bar .fa-lock, .fa-spin {
|
||||
color: lightgray;
|
||||
}
|
||||
|
|
|
@ -167,7 +167,7 @@
|
|||
|
||||
// Fixed size with width= 721 and height = 110
|
||||
var wire_html =
|
||||
'<svg width="721" height="110">' +
|
||||
'<svg width="700" height="100">' +
|
||||
'<g transform="translate(0, 20)">' +
|
||||
loop_html +
|
||||
'</g>' + '"Your browser does not support inline SVG."' +
|
||||
|
|
15
common/static/sass/_common.sass
Normal file
15
common/static/sass/_common.sass
Normal file
|
@ -0,0 +1,15 @@
|
|||
|
||||
@mixin clear
|
||||
content: ' '
|
||||
clear: both
|
||||
display: table
|
||||
|
||||
// Breakpoints
|
||||
// Small devices (landscape phones, 576px and up)
|
||||
$small-devices: 575.98px
|
||||
// Medium devices (tablets, 768px and up)
|
||||
$medium-devices: 767.98px
|
||||
// Large devices (desktops, 992px and up)
|
||||
$large-devices: 991.98px
|
||||
// Extra large devices (large desktops, 1200px and up)
|
||||
$x-large-devices: 1199.98px
|
48
common/static/scss/_card.scss
Normal file
48
common/static/scss/_card.scss
Normal file
|
@ -0,0 +1,48 @@
|
|||
div.item {
|
||||
display: grid;
|
||||
grid-template-columns:
|
||||
calc(4rem * var(--pico-line-height)) auto;
|
||||
column-gap: var(--pico-block-spacing-horizontal);
|
||||
align-items: top;
|
||||
justify-content: left;
|
||||
word-break: break-all;
|
||||
|
||||
&.player {
|
||||
display: block;
|
||||
}
|
||||
|
||||
hgroup {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h5 small,
|
||||
hgroup span {
|
||||
font-weight: 400;
|
||||
font-size: 80%;
|
||||
color: var(--pico-muted-color);
|
||||
|
||||
&.category {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.metadata {
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
.brief {
|
||||
text-overflow: ellipsis;
|
||||
word-wrap: break-word;
|
||||
overflow: hidden;
|
||||
-webkit-line-clamp: 4;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
}
|
25
common/static/scss/_collection.scss
Normal file
25
common/static/scss/_collection.scss
Normal file
|
@ -0,0 +1,25 @@
|
|||
#collection-page {
|
||||
@media (max-width: 768px) {
|
||||
main>article>header {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
|
||||
#collection-cover {
|
||||
img {
|
||||
height: 20vw;
|
||||
}
|
||||
|
||||
height: unset !important;
|
||||
order: -1;
|
||||
}
|
||||
|
||||
#collection-feature {
|
||||
order: 99;
|
||||
|
||||
.donut {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
95
common/static/scss/_common.scss
Normal file
95
common/static/scss/_common.scss
Normal file
|
@ -0,0 +1,95 @@
|
|||
body {
|
||||
--pico-block-spacing-vertical: var(--pico-block-spacing-horizontal);
|
||||
}
|
||||
|
||||
article.item-card {
|
||||
padding: calc(var(--pico-block-spacing-horizontal));
|
||||
margin-bottom: calc(var(--pico-block-spacing-vertical) / 2);
|
||||
|
||||
header,
|
||||
footer {
|
||||
padding: calc(var(--pico-block-spacing-horizontal) / 2);
|
||||
}
|
||||
|
||||
section {
|
||||
margin-bottom: calc(var(--pico-spacing) / 1);
|
||||
}
|
||||
}
|
||||
|
||||
article.item-card.external h5 {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
details {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
section section {
|
||||
margin-bottom: var(--pico-spacing) !important;
|
||||
}
|
||||
|
||||
.empty {
|
||||
font-style: italic;
|
||||
font-size: 80%;
|
||||
color: var(--pico-muted-color);
|
||||
}
|
||||
|
||||
.oneline {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.handler {
|
||||
color: var(--pico-muted-color);
|
||||
word-break: break-all;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.loading {
|
||||
color: var(--pico-muted-color);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.action {
|
||||
width: max-content;
|
||||
float: right;
|
||||
|
||||
&.inline {
|
||||
float: none;
|
||||
}
|
||||
|
||||
>span {
|
||||
padding-left: calc(var(--pico-spacing)/2);
|
||||
}
|
||||
|
||||
a {
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
a.disabled,
|
||||
.timestamp {
|
||||
cursor: unset;
|
||||
color: var(--pico-muted-color);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
a:not(:hover) {
|
||||
color: var(--pico-muted-color);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
a.activated:not(:hover) {
|
||||
color: var(--pico-primary);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
form img {
|
||||
max-height: 20vh;
|
||||
}
|
103
common/static/scss/_dialog.scss
Normal file
103
common/static/scss/_dialog.scss
Normal file
|
@ -0,0 +1,103 @@
|
|||
dialog {
|
||||
header {
|
||||
margin-bottom: 16px;
|
||||
padding: 8px !important;
|
||||
}
|
||||
|
||||
&>article {
|
||||
/* Animate when opening */
|
||||
animation-name: zoomIn;
|
||||
animation-duration: 150ms;
|
||||
animation-timing-function: ease;
|
||||
}
|
||||
|
||||
&.closing {
|
||||
/* Animate when closing */
|
||||
animation-name: fadeOut;
|
||||
animation-duration: 150ms;
|
||||
animation-timing-function: ease;
|
||||
}
|
||||
|
||||
&.closing>article {
|
||||
/* Aniate when closing */
|
||||
animation-name: zoomOut;
|
||||
animation-duration: 150ms;
|
||||
animation-timing-function: ease;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes zoomIn {
|
||||
0% {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes zoomOut {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
}
|
||||
|
||||
.grid>div {
|
||||
min-width: max-content;
|
||||
}
|
||||
|
||||
.grid>div:nth-child(2) fieldset {
|
||||
float: right;
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.grid>div:nth-child(2) fieldset {
|
||||
float: unset;
|
||||
}
|
||||
}
|
||||
|
||||
fieldset {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
article {
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
|
||||
input[type="date"] {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.tag-input {
|
||||
margin-bottom: var(--pico-spacing);
|
||||
}
|
||||
|
||||
.rating-editor {
|
||||
font-size: 120%;
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
}
|
63
common/static/scss/_feed.scss
Normal file
63
common/static/scss/_feed.scss
Normal file
|
@ -0,0 +1,63 @@
|
|||
.feed-page {
|
||||
.feed {
|
||||
.avatar {
|
||||
height: calc(1rem * var(--pico-line-height) + var(--pico-nav-link-spacing-vertical) * 4 - 8px);
|
||||
width: calc(1rem * var(--pico-line-height) + var(--pico-nav-link-spacing-vertical) * 4 - 8px);
|
||||
|
||||
img {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
section {
|
||||
margin-bottom: 2vh;
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
grid-template-rows: auto;
|
||||
grid-column-gap: 1em;
|
||||
grid-row-gap: 0px;
|
||||
// align-items: center;
|
||||
// justify-content: left;
|
||||
|
||||
.nickname a {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.time {
|
||||
width: max-content;
|
||||
float: right;
|
||||
color: var(--pico-muted-color);
|
||||
opacity: 0.5;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.rating-star {
|
||||
margin: 0 0.5em;
|
||||
}
|
||||
|
||||
.rating-star,
|
||||
.rating-star>* {
|
||||
color: var(--pico-primary);
|
||||
}
|
||||
|
||||
|
||||
article {
|
||||
padding: calc(var(--pico-block-spacing-horizontal) / 2);
|
||||
|
||||
footer {
|
||||
padding: calc(var(--pico-block-spacing-horizontal) / 2);
|
||||
margin-left: calc(var(--pico-block-spacing-horizontal) * -0.5);
|
||||
margin-right: calc(var(--pico-block-spacing-horizontal) * -0.5);
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.spacing {
|
||||
margin-bottom: var(--pico-block-spacing-horizontal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
120
common/static/scss/_gallery.scss
Normal file
120
common/static/scss/_gallery.scss
Normal file
|
@ -0,0 +1,120 @@
|
|||
.calendar_view {
|
||||
overflow-x: scroll;
|
||||
|
||||
svg {
|
||||
height: 108px;
|
||||
}
|
||||
}
|
||||
|
||||
.shelf {
|
||||
max-width: 1400px;
|
||||
padding: 0;
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.cards {
|
||||
display: grid;
|
||||
grid-auto-columns: 100%;
|
||||
grid-column-gap: var(--pico-block-spacing-horizontal);
|
||||
grid-auto-flow: column;
|
||||
padding: var(--pico-nav-link-spacing-vertical) 0px;
|
||||
list-style: none;
|
||||
overflow-x: scroll;
|
||||
scroll-snap-type: x mandatory;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
height: var(--pico-nav-link-spacing-vertical);
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb,
|
||||
&::-webkit-scrollbar-track {
|
||||
border-radius: 92px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: var(--pico-range-active-border-color);
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: var(--pico-range-border-color);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0px;
|
||||
// border-radius: 5px;
|
||||
scroll-snap-align: start;
|
||||
transition: all 0.2s;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
|
||||
a {
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
img {
|
||||
background: var(--pico-background-color);
|
||||
// border-radius: 5px;
|
||||
width: 100%;
|
||||
min-height: 3rem;
|
||||
vertical-align: middle;
|
||||
margin: auto;
|
||||
font-size: 80%;
|
||||
border: 2px solid transparent;
|
||||
}
|
||||
|
||||
a:hover img {
|
||||
border: 2px solid var(--pico-primary-hover);
|
||||
}
|
||||
|
||||
a>div {
|
||||
font-size: 80%;
|
||||
text-overflow: ellipsis;
|
||||
word-wrap: break-word;
|
||||
overflow: hidden;
|
||||
-webkit-line-clamp: 2;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
min-height: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 200px) {
|
||||
.cards {
|
||||
grid-auto-columns: calc(25% - var(--pico-block-spacing-horizontal));
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 500px) {
|
||||
.cards {
|
||||
grid-auto-columns: calc(20% - var(--pico-block-spacing-horizontal));
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 769px) {
|
||||
.cards {
|
||||
grid-auto-columns: calc(calc(100% / 6) - var(--pico-block-spacing-horizontal));
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1281px) {
|
||||
.cards {
|
||||
grid-auto-columns: calc(calc(100% / 8) - var(--pico-block-spacing-horizontal));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 769px) {
|
||||
.sidebar .shelf .cards {
|
||||
grid-auto-columns: calc(34% - var(--pico-spacing)) !important;
|
||||
gap: var(--pico-spacing) !important;
|
||||
}
|
||||
}
|
220
common/static/scss/_header.scss
Normal file
220
common/static/scss/_header.scss
Normal file
|
@ -0,0 +1,220 @@
|
|||
body>header {
|
||||
padding: 0px !important;
|
||||
}
|
||||
|
||||
.nav-logo {
|
||||
margin-left: 8px !important;
|
||||
}
|
||||
|
||||
.nav-dropdown {
|
||||
margin-right: 8px !important;
|
||||
}
|
||||
|
||||
.nav-dropdown ul li a {
|
||||
padding: var(--pico-form-element-spacing-vertical) var(--pico-form-element-spacing-horizontal) !important
|
||||
}
|
||||
|
||||
nav form {
|
||||
margin-bottom: 0px !important;
|
||||
}
|
||||
|
||||
nav summary {
|
||||
border: 0px !important;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
min-width: -webkit-max-content;
|
||||
min-width: -moz-max-content;
|
||||
}
|
||||
|
||||
nav ul li a.current {
|
||||
font-weight: bold;
|
||||
color: var(--pico-primary);
|
||||
}
|
||||
|
||||
.nav-search,
|
||||
.nav-search li {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.nav-search select {
|
||||
max-width: max-content;
|
||||
}
|
||||
|
||||
.nav-search input[type="submit"] {
|
||||
background-color: var(--pico-secondary-background);
|
||||
border-color: var(--pico-secondary-background);
|
||||
padding-left: calc(var(--pico-nav-link-spacing-horizontal)*2);
|
||||
padding-right: calc(var(--pico-nav-link-spacing-horizontal)*2);
|
||||
}
|
||||
|
||||
.nav-logo img {
|
||||
max-height: 56px;
|
||||
}
|
||||
|
||||
.unhide {
|
||||
display: unset !important;
|
||||
}
|
||||
|
||||
.nav-dropdown summary {
|
||||
padding-top: 0px !important;
|
||||
padding-bottom: 0px !important;
|
||||
}
|
||||
|
||||
.nav-dropdown summary::after {
|
||||
height: calc(1rem * var(--pico-line-height, 1.5) + 8px) !important;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
line-height: 0;
|
||||
/* remove line-height */
|
||||
display: inline-block;
|
||||
/* circle wraps image */
|
||||
border: 4px solid lightgray;
|
||||
border-radius: 50%;
|
||||
/* relative value */
|
||||
transition: linear 0.25s;
|
||||
}
|
||||
|
||||
.avatar img {
|
||||
border-radius: 50%;
|
||||
height: calc(1rem * var(--pico-line-height) + var(--pico-nav-link-spacing-vertical) * 2 - 8px);
|
||||
width: calc(1rem * var(--pico-line-height) + var(--pico-nav-link-spacing-vertical) * 2 - 8px);
|
||||
}
|
||||
|
||||
.avatar:hover {
|
||||
transition: ease-out 0.2s;
|
||||
border: 4px solid var(--pico-primary);
|
||||
-webkit-transition: ease-out 0.2s;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
:root {
|
||||
--pico-font-size: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 769px) {
|
||||
.small-only {
|
||||
display: none;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
:root {
|
||||
--pico-font-size: 100%;
|
||||
}
|
||||
|
||||
.large-only {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body>header {
|
||||
position: sticky;
|
||||
top: 0px;
|
||||
background: var(--pico-background-color);
|
||||
z-index: 999;
|
||||
box-shadow: var(--pico-box-shadow);
|
||||
}
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
}
|
||||
|
||||
.nav-logo img {
|
||||
max-height: 28px;
|
||||
}
|
||||
|
||||
.nav-search {
|
||||
order: 999;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nav-search li {
|
||||
padding: 0px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
.nav-search input[type="submit"] {
|
||||
padding-left: calc(var(--pico-nav-link-spacing-horizontal)*1);
|
||||
padding-right: calc(var(--pico-nav-link-spacing-horizontal)*1);
|
||||
}
|
||||
|
||||
.nav-dropdown::after {
|
||||
flex-basis: 100%;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.nav-dropdown {
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dark color scheme (Auto) */
|
||||
/* Automatically enabled if user has Dark mode enabled */
|
||||
@media only screen and (prefers-color-scheme: dark) {
|
||||
.nav-logo img {
|
||||
filter: brightness(100%) grayscale(100%) invert(40%);
|
||||
}
|
||||
}
|
||||
|
||||
/* Dark color scheme (Forced) */
|
||||
/* Enabled if forced with data-theme="dark" */
|
||||
.nav-logo img [data-theme="dark"] {
|
||||
filter: brightness(100%) grayscale(100%) invert(40%);
|
||||
}
|
||||
|
||||
.tldr {
|
||||
overflow: hidden;
|
||||
text-overflow: " ... [点击展开]";
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 10;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
.tldr-2 {
|
||||
overflow: hidden;
|
||||
text-overflow: " ... [点击展开]";
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
a:not(:hover) {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
body>footer {
|
||||
padding-top: 0.4em !important;
|
||||
text-align: center;
|
||||
margin-bottom: 4px !important;
|
||||
width: 100%;
|
||||
|
||||
.footer__border {
|
||||
width: 100%;
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.footer__link {
|
||||
margin: 0 12px;
|
||||
white-space: nowrap;
|
||||
min-width: 15vw;
|
||||
}
|
||||
|
||||
@media (min-width: 769px) {
|
||||
clear: both;
|
||||
position: absolute !important;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
165
common/static/scss/_item.scss
Normal file
165
common/static/scss/_item.scss
Normal file
|
@ -0,0 +1,165 @@
|
|||
#item-page {
|
||||
a:not(:hover) {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.muted {
|
||||
color: var(--pico-muted-color);
|
||||
}
|
||||
|
||||
.muted a:not(:hover) {
|
||||
color: var(--pico-muted-color);
|
||||
}
|
||||
|
||||
.muted .fa-lock {
|
||||
filter: brightness(50%) !important;
|
||||
}
|
||||
|
||||
a>button {
|
||||
padding: 2px 8px;
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
main>div {
|
||||
margin: 2vw;
|
||||
}
|
||||
|
||||
main>div>section {
|
||||
margin-bottom: 2vw;
|
||||
}
|
||||
|
||||
#item-title {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
#item-title-more {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
#item-title h1 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h1 small {
|
||||
font-size: 80%;
|
||||
margin-left: 0.5vw;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#item-cover {
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
#item-cover img {
|
||||
transition: transform 0.2s ease-in-out;
|
||||
filter: drop-shadow(0 0.2rem 0.8rem rgba(0, 0, 0, 0.2));
|
||||
max-width: 80%;
|
||||
max-height: 50vh;
|
||||
}
|
||||
|
||||
.item-edit,
|
||||
.item-edit a {
|
||||
color: var(--pico-muted-color);
|
||||
}
|
||||
|
||||
|
||||
|
||||
.item-action {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: 5%;
|
||||
}
|
||||
|
||||
.item-action button {
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.mark {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#item-cover {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
main {
|
||||
padding-top: 1vh !important;
|
||||
}
|
||||
|
||||
@media (min-width: 769px) {
|
||||
#item-title h1 {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.middle {
|
||||
margin: auto;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.left {
|
||||
float: left;
|
||||
clear: left;
|
||||
width: 22%;
|
||||
margin-left: 0;
|
||||
margin-right: 3%;
|
||||
}
|
||||
|
||||
.right {
|
||||
float: right;
|
||||
clear: right;
|
||||
width: 22%;
|
||||
margin-left: 3%;
|
||||
margin-right: 0%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
main {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
}
|
||||
|
||||
#item-title {
|
||||
order: -5;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
}
|
||||
|
||||
#item-title .site-list {
|
||||
order: -1;
|
||||
}
|
||||
|
||||
#item-title-more {
|
||||
order: -4;
|
||||
}
|
||||
|
||||
#item-cover {
|
||||
order: -3;
|
||||
}
|
||||
|
||||
#item-primary-action {
|
||||
order: -2;
|
||||
}
|
||||
|
||||
#item-primary-mark {
|
||||
order: -2;
|
||||
}
|
||||
|
||||
#item-metadata {
|
||||
order: -1;
|
||||
}
|
||||
|
||||
#item-sidebar {
|
||||
order: 99;
|
||||
}
|
||||
|
||||
#item-cover img {
|
||||
max-width: 60vw;
|
||||
}
|
||||
}
|
||||
}
|
144
common/static/scss/_layout.scss
Normal file
144
common/static/scss/_layout.scss
Normal file
|
@ -0,0 +1,144 @@
|
|||
.classic-page,
|
||||
.feed-page {
|
||||
main {
|
||||
width: 100vw;
|
||||
display: grid;
|
||||
grid-template-columns: 64% 32%;
|
||||
grid-template-areas: "main aside";
|
||||
gap: 4%;
|
||||
padding: calc(3*var(--pico-spacing));
|
||||
|
||||
.grid__main {
|
||||
grid-area: main;
|
||||
}
|
||||
|
||||
.grid__aside {
|
||||
grid-area: aside;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
main {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
padding: 0;
|
||||
gap: 0;
|
||||
|
||||
.grid__main {
|
||||
order: -1;
|
||||
margin: var(--pico-spacing);
|
||||
}
|
||||
|
||||
.grid__aside {
|
||||
order: -2;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
aside.bottom {
|
||||
order: 2 !important;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content-page {
|
||||
article {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
main {
|
||||
display: grid;
|
||||
grid-template-columns: auto 25%;
|
||||
grid-template-areas: "main aside";
|
||||
gap: calc(3*var(--pico-spacing));
|
||||
padding: calc(3*var(--pico-spacing));
|
||||
|
||||
&>div {
|
||||
grid-area: main;
|
||||
}
|
||||
|
||||
&>aside {
|
||||
grid-area: aside;
|
||||
|
||||
article>div {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.owner-info {
|
||||
height: max-content;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: var(--pico-spacing);
|
||||
|
||||
.owner {
|
||||
.avatar {
|
||||
width: calc(2rem * var(--pico-line-height));
|
||||
height: calc(2rem * var(--pico-line-height));
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.more {
|
||||
width: 20%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
main {
|
||||
display: flex;
|
||||
max-width: 100%;
|
||||
flex-flow: column nowrap;
|
||||
padding: 0;
|
||||
gap: 0;
|
||||
|
||||
>div {
|
||||
order: 1;
|
||||
// margin: var(--pico-spacing);
|
||||
}
|
||||
|
||||
>aside {
|
||||
order: 2;
|
||||
|
||||
article.item {
|
||||
display: grid;
|
||||
grid-template-columns: 25% auto;
|
||||
grid-template-areas: "main aside";
|
||||
margin: calc(var(--pico-spacing)/2);
|
||||
padding: 0;
|
||||
border: var(--pico-border-width) solid var(--pico-card-border-color);
|
||||
|
||||
>* {
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
>div {
|
||||
margin-left: var(--pico-spacing);
|
||||
background-color: var(--pico-card-sectioning-background-color);
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1028
common/static/scss/_legacy.sass
Normal file
1028
common/static/scss/_legacy.sass
Normal file
File diff suppressed because it is too large
Load diff
191
common/static/scss/_legacy2.scss
Normal file
191
common/static/scss/_legacy2.scss
Normal file
|
@ -0,0 +1,191 @@
|
|||
/*** django-jsoneditor ***/
|
||||
div.jsoneditor {
|
||||
border-color: #ccc !important;
|
||||
}
|
||||
|
||||
div.jsoneditor-menu {
|
||||
background-color: #606c76 !important;
|
||||
border-color: #606c76 !important;
|
||||
}
|
||||
|
||||
/***** MODAL DIALOG ****/
|
||||
#modal {
|
||||
/* Underlay covers entire screen. */
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
z-index: 1000;
|
||||
|
||||
/* Flexbox centers the .modal-content vertically and horizontally */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
/* Animate when opening */
|
||||
animation-name: fadeIn;
|
||||
animation-duration: 150ms;
|
||||
animation-timing-function: ease;
|
||||
}
|
||||
|
||||
#modal>.modal-underlay {
|
||||
/* underlay takes up the entire viewport. This is only
|
||||
required if you want to click to dismiss the popup */
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
#modal>.modal-content {
|
||||
/* Position visible dialog near the top of the window */
|
||||
margin-top: 10vh;
|
||||
|
||||
/* Sizing for visible dialog */
|
||||
width: 80%;
|
||||
max-width: 600px;
|
||||
|
||||
/* Display properties for visible dialog*/
|
||||
background-color: #f7f7f7;
|
||||
padding: 20px 20px 10px 20px;
|
||||
color: #606c76;
|
||||
|
||||
/* Animate when opening */
|
||||
animation-name: zoomIn;
|
||||
animation-duration: 150ms;
|
||||
animation-timing-function: ease;
|
||||
}
|
||||
|
||||
#modal.closing {
|
||||
/* Animate when closing */
|
||||
animation-name: fadeOut;
|
||||
animation-duration: 150ms;
|
||||
animation-timing-function: ease;
|
||||
}
|
||||
|
||||
#modal.closing>.modal-content {
|
||||
/* Aniate when closing */
|
||||
animation-name: zoomOut;
|
||||
animation-duration: 150ms;
|
||||
animation-timing-function: ease;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes zoomIn {
|
||||
0% {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes zoomOut {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
}
|
||||
|
||||
#modal .add-to-list-modal__head {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#modal .add-to-list-modal__head::after {
|
||||
content: ' ';
|
||||
clear: both;
|
||||
display: table;
|
||||
}
|
||||
|
||||
#modal .add-to-list-modal__title {
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#modal .add-to-list-modal__close-button {
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#modal .add-to-list-modal__confirm-button {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#modal li,
|
||||
#modal ul,
|
||||
#modal label {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.donut {
|
||||
margin-left: 10%;
|
||||
width: 80%;
|
||||
aspect-ratio: 1 / 1;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.donut .hole {
|
||||
width: 80%;
|
||||
aspect-ratio: 1 / 1;
|
||||
border-radius: 50%;
|
||||
background: #f7f7f7;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
input:invalid#position {
|
||||
border: red dashed 1px;
|
||||
}
|
||||
|
||||
.gg-play-button-o {
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
transform: scale(var(--ggs, 1));
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border: 2px solid;
|
||||
border-radius: 20px
|
||||
}
|
||||
|
||||
.gg-play-button-o::before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 10px;
|
||||
border-top: 5px solid transparent;
|
||||
border-bottom: 5px solid transparent;
|
||||
border-left: 6px solid;
|
||||
top: 4px;
|
||||
left: 7px
|
||||
}
|
72
common/static/scss/_login.scss
Normal file
72
common/static/scss/_login.scss
Normal file
|
@ -0,0 +1,72 @@
|
|||
.login-page {
|
||||
input:invalid {
|
||||
border: var(--pico-primary) dashed 2px;
|
||||
}
|
||||
|
||||
mark {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.autoComplete_wrapper>ul {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.autoComplete_wrapper>ul li {
|
||||
list-style: none;
|
||||
padding: 0 var(--pico-spacing);
|
||||
}
|
||||
|
||||
.autoComplete_wrapper>ul>li:hover {
|
||||
cursor: pointer;
|
||||
background-color: var(--pico-text-selection-color);
|
||||
}
|
||||
|
||||
.autoComplete_wrapper>ul>li[aria-selected="true"] {
|
||||
background-color: var(--pico-text-selection-color);
|
||||
}
|
||||
|
||||
article {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
min-width: max-content;
|
||||
width: 50%;
|
||||
height: max-content;
|
||||
|
||||
p {
|
||||
max-width: 50vw;
|
||||
}
|
||||
}
|
||||
|
||||
header img {
|
||||
padding: 10%;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
article {
|
||||
width: 96%;
|
||||
|
||||
p {
|
||||
max-width: 96vw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body>footer {
|
||||
color: lightgrey;
|
||||
text-align: center;
|
||||
bottom: 0px;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
68
common/static/scss/_mark.scss
Normal file
68
common/static/scss/_mark.scss
Normal file
|
@ -0,0 +1,68 @@
|
|||
#mark_date {
|
||||
width: unset !important;
|
||||
}
|
||||
|
||||
.tag-input {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-pack: start;
|
||||
-ms-flex-pack: start;
|
||||
justify-content: flex-start;
|
||||
-ms-flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
border-bottom: 0.1rem solid #ccc;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.tag-input__tag {
|
||||
position: relative;
|
||||
display: block;
|
||||
float: left;
|
||||
color: white;
|
||||
background: #d5d5d5;
|
||||
padding: 5px 20px 5px 6px;
|
||||
margin: 4px;
|
||||
border-radius: .4rem;
|
||||
line-height: 1em;
|
||||
-webkit-transition: all 0.2s ease-in-out;
|
||||
transition: all 0.2s ease-in-out;
|
||||
height: min-content;
|
||||
}
|
||||
|
||||
.tag-input__tag.tag-input__tag--highlight {
|
||||
color: white;
|
||||
background: #00a1cc;
|
||||
}
|
||||
|
||||
.tag-input__close {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 14px;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
border-radius: 0 2px 2px 0;
|
||||
-webkit-transition: background 0.2s;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.tag-input__close:after {
|
||||
position: absolute;
|
||||
content: "×";
|
||||
top: 5px;
|
||||
left: 2px;
|
||||
}
|
||||
|
||||
.tag-input__close:hover {
|
||||
color: #606c76;
|
||||
}
|
||||
|
||||
.tag-input input {
|
||||
border: 0;
|
||||
margin: 4px;
|
||||
padding: 3px 7px 3px 0;
|
||||
width: auto;
|
||||
outline: none;
|
||||
height: unset;
|
||||
}
|
31
common/static/scss/_markdown.scss
Normal file
31
common/static/scss/_markdown.scss
Normal file
|
@ -0,0 +1,31 @@
|
|||
.spoiler {
|
||||
background: grey;
|
||||
filter: blur(2px);
|
||||
cursor: pointer;
|
||||
|
||||
&.revealed {
|
||||
background: unset;
|
||||
filter: unset;
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.markdown-content {
|
||||
|
||||
h1 {
|
||||
font-size: 1.5rem
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.25rem
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.markdownx-editor {
|
||||
font-family: monospace;
|
||||
}
|
133
common/static/scss/_rating.scss
Normal file
133
common/static/scss/_rating.scss
Normal file
|
@ -0,0 +1,133 @@
|
|||
.rating {
|
||||
margin-top: 2vh;
|
||||
margin-bottom: 2vh;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.rating * {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.rating h3 small {
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
.rating .display {
|
||||
display: flex;
|
||||
flex: row;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.rating .display div {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.rating .display div:nth-child(1) {
|
||||
width: max-content;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
.rating .display div:nth-child(2) {
|
||||
flex-grow: 100;
|
||||
}
|
||||
|
||||
.rating .chart {
|
||||
flex-grow: 100;
|
||||
display: table;
|
||||
table-layout: fixed;
|
||||
height: max-content;
|
||||
}
|
||||
|
||||
.rating .chart li {
|
||||
position: relative;
|
||||
display: table-cell;
|
||||
vertical-align: bottom;
|
||||
height: 6vh;
|
||||
}
|
||||
|
||||
.rating .chart span {
|
||||
margin: 2%;
|
||||
display: block;
|
||||
background: var(--pico-muted-color);
|
||||
border-radius: 0.5vh 0.5vh 0 0;
|
||||
}
|
||||
|
||||
.rating .undisplay {
|
||||
position: absolute;
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
inset: 0;
|
||||
}
|
||||
|
||||
.rating.unavailable .undisplay {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.rating.unavailable .display {
|
||||
filter: blur(0.5vh);
|
||||
}
|
||||
|
||||
.rating.unavailable .chart li:nth-child(1) span {
|
||||
height: 10% !important;
|
||||
}
|
||||
|
||||
.rating.unavailable .chart li:nth-child(2) span {
|
||||
height: 20% !important;
|
||||
}
|
||||
|
||||
.rating.unavailable .chart li:nth-child(3) span {
|
||||
height: 30% !important;
|
||||
}
|
||||
|
||||
.rating.unavailable .chart li:nth-child(4) span {
|
||||
height: 40% !important;
|
||||
}
|
||||
|
||||
.rating.unavailable .chart li:nth-child(5) span {
|
||||
height: 50% !important;
|
||||
}
|
||||
|
||||
// Rating Star with Font Awesome
|
||||
.rating-star {
|
||||
position: relative;
|
||||
vertical-align: middle;
|
||||
font-family: FontAwesome;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.rating-star:before {
|
||||
content: "\f006 \f006 \f006 \f006 \f006";
|
||||
text-underline-offset: 0.125em;
|
||||
line-height: 1;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.rating-star>div {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.rating-star>div:before {
|
||||
content: "\f005 \f005 \f005 \f005 \f005";
|
||||
text-underline-offset: 0.125em;
|
||||
line-height: 1;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.rating-star .yellow {
|
||||
color: #F68127;
|
||||
text-shadow: 0 0 1px #FFE205, 0 0 2px #FFE205, 0 0 6px #EDD205;
|
||||
// color: #FFE205;
|
||||
}
|
||||
|
||||
.rating-editor {
|
||||
cursor: pointer !important;
|
||||
border: none !important;
|
||||
}
|
84
common/static/scss/_sidebar.scss
Normal file
84
common/static/scss/_sidebar.scss
Normal file
|
@ -0,0 +1,84 @@
|
|||
.sidebar {
|
||||
article {
|
||||
padding: calc(var(--pico-block-spacing-horizontal));
|
||||
}
|
||||
|
||||
details {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
hgroup {
|
||||
margin: 0;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
section.announcement {
|
||||
p {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
// details[open]>summary {
|
||||
// margin: 0;
|
||||
// }
|
||||
|
||||
details {
|
||||
margin-bottom: var(--pico-spacing);
|
||||
}
|
||||
}
|
||||
|
||||
section.profile {
|
||||
summary>div {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
grid-template-rows: auto;
|
||||
grid-column-gap: 0.5em;
|
||||
grid-row-gap: 0px;
|
||||
// align-items: center;
|
||||
// justify-content: left;
|
||||
}
|
||||
|
||||
summary::after {
|
||||
position: relative;
|
||||
bottom: calc(2rem * var(--pico-line-height));
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
height: calc(1rem * var(--pico-line-height) + var(--pico-nav-link-spacing-vertical) * 4);
|
||||
width: calc(1rem * var(--pico-line-height) + var(--pico-nav-link-spacing-vertical) * 4);
|
||||
|
||||
img {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.nickname {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
|
||||
.relation {
|
||||
width: max-content;
|
||||
float: right;
|
||||
color: var(--pico-muted-color);
|
||||
opacity: 0.5;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 768px) {
|
||||
|
||||
section,
|
||||
article,
|
||||
details {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
115
common/static/scss/_sitelabel.scss
Normal file
115
common/static/scss/_sitelabel.scss
Normal file
|
@ -0,0 +1,115 @@
|
|||
.site-list {
|
||||
a {
|
||||
display: inline;
|
||||
background: transparent;
|
||||
padding: calc(var(--pico-spacing)/8);
|
||||
border-radius: calc(var(--pico-spacing)/4);
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
font-size: 80%;
|
||||
margin: 3px;
|
||||
// padding: 1px 3px;
|
||||
// padding-top: 2px;
|
||||
font-weight: lighter;
|
||||
word-break: keep-all;
|
||||
opacity: 1;
|
||||
font-weight: 400;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.douban {
|
||||
border: none;
|
||||
color: white;
|
||||
background-color: #319840;
|
||||
}
|
||||
|
||||
.spotify {
|
||||
background-color: #1ed760;
|
||||
color: black;
|
||||
border: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.imdb {
|
||||
background-color: #F5C518;
|
||||
color: #121212;
|
||||
border: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.igdb {
|
||||
background-color: #323A44;
|
||||
color: #DFE1E2;
|
||||
border: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.steam {
|
||||
background: linear-gradient(30deg, #1387b8, #111d2e);
|
||||
color: white;
|
||||
border: none;
|
||||
// font-weight: 600
|
||||
// padding-top: 2px
|
||||
}
|
||||
|
||||
.bangumi {
|
||||
background: #F09199;
|
||||
color: #FCFCFC;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.goodreads {
|
||||
background: #F4F1EA;
|
||||
color: #372213;
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
||||
.bookstw {
|
||||
background: #7FBA19;
|
||||
color: white;
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
||||
.tmdb {
|
||||
background: linear-gradient(90deg, #91CCA3, #1FB4E2);
|
||||
color: white;
|
||||
border: none;
|
||||
font-weight: lighter;
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
.googlebooks {
|
||||
color: white;
|
||||
background-color: #4285F4;
|
||||
border-color: #4285F4;
|
||||
}
|
||||
|
||||
.rss {
|
||||
color: white;
|
||||
background-color: #E1A02F;
|
||||
border-color: #E1A02F;
|
||||
}
|
||||
|
||||
.bandcamp {
|
||||
color: white;
|
||||
background-color: #28A0C1;
|
||||
}
|
||||
|
||||
// .bandcamp {
|
||||
// color: white
|
||||
// background-color: #28A0C1
|
||||
// // transform: skewX(-30deg)
|
||||
// display: inline-block
|
||||
// }
|
||||
// .bandcamp span
|
||||
// // transform: skewX(30deg)
|
||||
// display: inline-block
|
||||
// margin: 0 4px
|
||||
|
||||
.discogs {
|
||||
color: white;
|
||||
background-color: #262626;
|
||||
border-color: #262626;
|
||||
}
|
||||
}
|
20
common/static/scss/_tag.scss
Normal file
20
common/static/scss/_tag.scss
Normal file
|
@ -0,0 +1,20 @@
|
|||
.tag-list {
|
||||
// margin-bottom: var(--pico-spacing);
|
||||
|
||||
span {
|
||||
// margin: 3px;
|
||||
|
||||
a {
|
||||
color: white;
|
||||
background: var(--pico-muted-color);
|
||||
padding: calc(var(--pico-spacing)/4);
|
||||
border-radius: calc(var(--pico-spacing)/4);
|
||||
line-height: 1.2em;
|
||||
font-size: 80%;
|
||||
margin: 3px !important;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
18
common/static/scss/neodb.scss
Normal file
18
common/static/scss/neodb.scss
Normal file
|
@ -0,0 +1,18 @@
|
|||
@import '_header.scss';
|
||||
@import '_dialog.scss';
|
||||
@import '_rating.scss';
|
||||
@import '_mark.scss';
|
||||
@import '_item.scss';
|
||||
@import '_layout.scss';
|
||||
@import '_sitelabel.scss';
|
||||
@import '_tag.scss';
|
||||
@import '_markdown.scss';
|
||||
@import '_legacy.sass';
|
||||
@import '_legacy2.scss';
|
||||
@import '_collection.scss';
|
||||
@import '_feed.scss';
|
||||
@import '_card.scss';
|
||||
@import '_gallery.scss';
|
||||
@import '_sidebar.scss';
|
||||
@import '_common.scss';
|
||||
@import '_login.scss';
|
|
@ -8,33 +8,23 @@
|
|||
{% load thumb %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ site_name }} - {% trans '无效请求' %}</title>
|
||||
{% include "common_libs.html" with jquery=0 %}
|
||||
<link rel="stylesheet" href="{% static 'css/boofilsic_box.css' %}">
|
||||
{% include "common_libs.html" with jquery=0 v2=1 %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="page-wrapper">
|
||||
<div id="content-wrapper">
|
||||
{% include "partial/_navbar.html" %}
|
||||
<div class="box">
|
||||
<a href="{% url 'common:home' %}">
|
||||
<img src="{% static 'img/logo.svg' %}" alt="logo" class="logo">
|
||||
</a>
|
||||
<div class="main-msg">
|
||||
无效的请求
|
||||
</div>
|
||||
<div class="sec-msg">
|
||||
{% include "_header.html" %}
|
||||
<main class="container">
|
||||
<article class="error">
|
||||
<header>
|
||||
<h3>🤦🏻 无效的请求</h3>
|
||||
</header>
|
||||
{{ exception }}
|
||||
您可能提交了无效的数据,或者相关内容已被作者删除。如果您确信这是我们的错误,欢迎通过页面底部的链接联系。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
您可能提交了无效的数据,或者相关内容已被作者删除。如果您确信这是我们的错误,请通过页面底部的链接联系我们。
|
||||
</article>
|
||||
</main>
|
||||
{% include "partial/_footer.html" %}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -8,32 +8,23 @@
|
|||
{% load thumb %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ site_name }} - {% trans '权限不符' %}</title>
|
||||
{% include "common_libs.html" with jquery=0 %}
|
||||
<link rel="stylesheet" href="{% static 'css/boofilsic_box.css' %}">
|
||||
{% include "common_libs.html" with jquery=0 v2=1 %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="page-wrapper">
|
||||
<div id="content-wrapper">
|
||||
{% include "partial/_navbar.html" %}
|
||||
<div class="box">
|
||||
<a href="{% url 'common:home' %}">
|
||||
<img src="{% static 'img/logo.svg' %}" alt="logo" class="logo">
|
||||
</a>
|
||||
<div class="main-msg">
|
||||
权限不符
|
||||
</div>
|
||||
<div class="sec-msg">
|
||||
您可能访问了错误的网址,或者相关内容已被作者隐藏。如果您确信这是我们的错误,欢迎通过页面底部的链接联系。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include "_header.html" %}
|
||||
<main class="container">
|
||||
<article class="error">
|
||||
<header>
|
||||
<h3>🤦🏻 权限不符</h3>
|
||||
</header>
|
||||
{{ exception }}
|
||||
您可能访问了错误的网址,或者相关内容已被作者删除。如果您确信这是我们的错误,请通过页面底部的链接联系我们。
|
||||
</article>
|
||||
</main>
|
||||
{% include "partial/_footer.html" %}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -8,32 +8,22 @@
|
|||
{% load thumb %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ site_name }} - {% trans '未找到' %}</title>
|
||||
{% include "common_libs.html" with jquery=0 %}
|
||||
<link rel="stylesheet" href="{% static 'css/boofilsic_box.css' %}">
|
||||
{% include "common_libs.html" with jquery=0 v2=1 %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="page-wrapper">
|
||||
<div id="content-wrapper">
|
||||
{% include "partial/_navbar.html" %}
|
||||
<div class="box">
|
||||
<a href="{% url 'common:home' %}">
|
||||
<img src="{% static 'img/logo.svg' %}" alt="logo" class="logo">
|
||||
</a>
|
||||
<div class="main-msg">
|
||||
请求条目未找到
|
||||
</div>
|
||||
<div class="sec-msg">
|
||||
您可能输入了一个无效的网址,或者相关内容已被作者删除。如果您确信这是我们的错误,欢迎通过页面底部的链接联系。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include "_header.html" %}
|
||||
<main class="container">
|
||||
<article class="error">
|
||||
<header>
|
||||
<h3>🤦🏻 条目未找到</h3>
|
||||
</header>
|
||||
您可能输入了一个无效的网址,或者相关内容已被作者删除。如果您确信这是我们的错误,请通过页面底部的链接联系我们。
|
||||
</article>
|
||||
</main>
|
||||
{% include "partial/_footer.html" %}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -8,32 +8,22 @@
|
|||
{% load thumb %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ site_name }} - {% trans '系统错误' %}</title>
|
||||
{% include "common_libs.html" with jquery=0 %}
|
||||
<link rel="stylesheet" href="{% static 'css/boofilsic_box.css' %}">
|
||||
{% include "common_libs.html" with jquery=0 v2=1 %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="page-wrapper">
|
||||
<div id="content-wrapper">
|
||||
{% include "partial/_navbar.html" %}
|
||||
<div class="box">
|
||||
<a href="{% url 'common:home' %}">
|
||||
<img src="{% static 'img/logo.svg' %}" alt="logo" class="logo">
|
||||
</a>
|
||||
<div class="main-msg">
|
||||
系统内部错误
|
||||
</div>
|
||||
<div class="sec-msg">
|
||||
发生了一个内部错误,如果这个错误多次出现,后台会记录并会由人工处理。如果您有紧急情况或疑问,欢迎通过页面底部的链接联系。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include "_header.html" %}
|
||||
<main class="container">
|
||||
<article class="error">
|
||||
<header>
|
||||
<h3>🤦🏻 系统内部错误</h3>
|
||||
</header>
|
||||
发生了一个内部错误,如果这个错误多次出现,后台会记录并会由人工处理。如果您有紧急情况或任何疑问,请通过页面底部的链接联系我们。
|
||||
</article>
|
||||
</main>
|
||||
{% include "partial/_footer.html" %}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
@ -7,7 +8,9 @@
|
|||
<body>
|
||||
<div class="pl">
|
||||
<div class="pl__outer-ring"></div>
|
||||
<div class="pl__inner-ring"><center>NeoDB 升级中...</center></div>
|
||||
<div class="pl__inner-ring">
|
||||
<center>NeoDB 升级中...</center>
|
||||
</div>
|
||||
<div class="pl__track-cover"></div>
|
||||
<div class="pl__ball">
|
||||
<div class="pl__ball-texture"></div>
|
||||
|
|
103
common/templates/_header.html
Normal file
103
common/templates/_header.html
Normal file
|
@ -0,0 +1,103 @@
|
|||
{% load admin_url %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
<header class="container-fluid">
|
||||
<nav>
|
||||
<ul class="nav-logo">
|
||||
<a href="{% url 'common:home' %}">
|
||||
<img src="{% static 'img/logo.svg' %}" alt="" />
|
||||
</a>
|
||||
</ul>
|
||||
<ul class="nav-search">
|
||||
<li>
|
||||
<form role="search" method="get" action="{% url 'catalog:search' %}">
|
||||
<input type="search"
|
||||
name="q"
|
||||
placeholder="搜索标题、创作者、ISBN、链接(如 https://movie.douban.com/subject/1297880/ )"
|
||||
class="search"
|
||||
value="{{ request.GET.q|default:'' }}" />
|
||||
<select name="c">
|
||||
<option value="all">全部</option>
|
||||
<option {% if request.GET.c and request.GET.c == 'book' or '/book/' in request.path %}selected{% endif %}
|
||||
value="book">书籍</option>
|
||||
<option {% if request.GET.c and request.GET.c == 'movietv' or '/movie/' in request.path or '/tv/' in request.path %}selected{% endif %}
|
||||
value="movietv">影视</option>
|
||||
<option {% if request.GET.c and request.GET.c == 'podcast' or '/podcast/' in request.path %}selected{% endif %}
|
||||
value="podcast">播客</option>
|
||||
<option {% if request.GET.c and request.GET.c == 'music' or '/album/' in request.path %}selected{% endif %}
|
||||
value="music">音乐</option>
|
||||
<option {% if request.GET.c and request.GET.c == 'game' or '/game/' in request.path %}selected{% endif %}
|
||||
value="game">游戏</option>
|
||||
</select>
|
||||
<input type="submit" value="" class="fa-solid" />
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li class="small-only">
|
||||
<a _="on click toggle .unhide on .nav-search">搜索</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="{% if current == 'discover' %}current{% endif %}"
|
||||
href="{% url 'catalog:discover' %}">发现</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="{% if current == 'timeline' %}current{% endif %}"
|
||||
href="{% url 'social:feed' %}">动态</a>
|
||||
</li>
|
||||
<li class="large-only">
|
||||
<a class="{% if current == 'home' %}current{% endif %}"
|
||||
href="{% url 'common:me' %}">个人</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="nav-dropdown">
|
||||
<li>
|
||||
<details class="dropdown">
|
||||
<summary aria-haspopup="listbox">
|
||||
<span class="avatar">
|
||||
<img alt=""
|
||||
src="{% if request.user.is_authenticated %}{{ request.user.mastodon_account.avatar }}{% else %}data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=={% endif %}" />
|
||||
</span>
|
||||
</summary>
|
||||
<ul role="listbox" style="min-width:-webkit-max-content;" dir="rtl">
|
||||
{% if request.user.is_authenticated %}
|
||||
<li class="small-only">
|
||||
<a class="{% if current == 'home' %}current{% endif %}"
|
||||
href="{% url 'common:me' %}">个人主页</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'users:data' %}">数据</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'users:preferences' %}">设置</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'users:logout' %}">登出</a>
|
||||
</li>
|
||||
{% if request.user.is_superuser %}
|
||||
<li>
|
||||
<a href="{% admin_url %}">后台</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<li>
|
||||
<a href="{% url 'users:login' %}?next={{ request.path }}">登录</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</details>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
{% if messages %}
|
||||
<div class="main-section-wrapper"
|
||||
style="margin-bottom: 10px;
|
||||
text-align:center">
|
||||
<ul class="messages">
|
||||
{% for message in messages %}
|
||||
<li {% if message.tags %}class="{{ message.tags }}"{% endif %}>{{ message }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
215
common/templates/_sidebar.html
Normal file
215
common/templates/_sidebar.html
Normal file
|
@ -0,0 +1,215 @@
|
|||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load admin_url %}
|
||||
{% load mastodon %}
|
||||
{% load oauth_token %}
|
||||
{% load truncate %}
|
||||
{% load thumb %}
|
||||
{% load collection %}
|
||||
{% load bleach_tags %}
|
||||
<aside class="grid__aside sidebar">
|
||||
{% if request.user.unread_announcements %}
|
||||
<section class="announcement">
|
||||
<article>
|
||||
<h5>
|
||||
未读公告
|
||||
<small> | <a href="{% url 'management:list' %}">全部</a> </small>
|
||||
</h5>
|
||||
{% for ann in request.user.unread_announcements %}
|
||||
<details open>
|
||||
<summary>
|
||||
{{ ann.title }}
|
||||
<small>(<a href="{% url 'management:retrieve' ann.pk %}">{{ ann.created_time|date }}</a>)</small>
|
||||
</summary>
|
||||
<div class="tldr" _="on click toggle .tldr on me">{{ ann.get_html_content | safe }}</div>
|
||||
</details>
|
||||
{% endfor %}
|
||||
<form action="{% url 'users:mark_announcements_read' %}" method="post">
|
||||
{% csrf_token %}
|
||||
<input type="submit" class="secondary outline" value="{% trans '全部标为已读' %}">
|
||||
</form>
|
||||
</article>
|
||||
</section>
|
||||
{% endif %}
|
||||
{% if show_profile %}
|
||||
<section class="profile">
|
||||
<article>
|
||||
<details class="auto-collapse" open>
|
||||
<summary>
|
||||
<div>
|
||||
<div class="avatar">
|
||||
<a href="{% url 'journal:user_profile' user.mastodon_username %}">
|
||||
<img src="{{ user.mastodon_account.avatar }}" alt="">
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<hgroup>
|
||||
<h6 class="nickname">{{ user.display_name }}</h6>
|
||||
<div>
|
||||
<a href="{{ user.mastodon_account.url }}" target="_blank" rel="noopener">
|
||||
<span class="handler">@{{ user.mastodon_username }}</span>
|
||||
</a>
|
||||
{% current_user_relationship user as relationship %}
|
||||
{% if relationship %}<span>{{ relationship }}</span>{% endif %}
|
||||
</div>
|
||||
</hgroup>
|
||||
</div>
|
||||
</div>
|
||||
</summary>
|
||||
<p class="user-profile__bio mast-brief">{{ user.mastodon_account.note|bleach:"a,p,span,br" }}</p>
|
||||
{% if request.user != user %}
|
||||
<span class="action">
|
||||
<small>
|
||||
<a href="{% url 'users:report' %}?user_id={{ user.id }}"
|
||||
class="user-profile__report-link">{% trans '投诉用户' %}</a>
|
||||
</small>
|
||||
</span>
|
||||
{% endif %}
|
||||
</details>
|
||||
</article>
|
||||
</section>
|
||||
{% endif %}
|
||||
{% if show_progress %}
|
||||
<section>
|
||||
<article>
|
||||
<details {% if user.featured_collections.all %}open{% endif %}>
|
||||
<summary>{% trans '当前目标' %}</summary>
|
||||
{% for featured_collection in user.featured_collections.all %}
|
||||
{% user_visibility_of featured_collection as visible %}
|
||||
{% if visible %}
|
||||
{% user_stats_of collection=featured_collection user=user as stats %}
|
||||
<div>
|
||||
<a href="{{ featured_collection.collection.url }}">{{ featured_collection.collection.title }}</a> <small>{{ stats.complete }} / {{ stats.total }}</small>
|
||||
<br>
|
||||
<progress value="{{ stats.percentage }}" max="100" />
|
||||
</div>
|
||||
{% endif %}
|
||||
{% empty %}
|
||||
{% if request.user == user %}
|
||||
<div class="empty">将自己或他人的收藏单设为目标,这里就会显示进度</div>
|
||||
{% else %}
|
||||
<div class="empty">暂未设置目标</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</details>
|
||||
</article>
|
||||
</section>
|
||||
{% endif %}
|
||||
{% if recent_podcast_episodes %}
|
||||
<section>
|
||||
<article>
|
||||
<details class="auto-collapse" open>
|
||||
<summary>{% trans '在听播客的近期单集' %}</summary>
|
||||
<div class="shelf">
|
||||
<ul class="cards">
|
||||
{% for item in recent_podcast_episodes %}
|
||||
<li class="card">
|
||||
<a class="episode"
|
||||
data-uuid="{{ item.uuid }}"
|
||||
data-media="{{ item.media_url }}"
|
||||
data-cover="{{ item.cover_url|default:item.program.cover.url }}"
|
||||
data-title="{{ item.title }}"
|
||||
data-album="{{ item.program.title }}"
|
||||
data-hosts="{{ item.program.hosts|join:' / ' }}"
|
||||
data-position="0"
|
||||
href="{{ item.url }}"
|
||||
title="{{ item.title }}">
|
||||
<img src="{{ item.cover_image_url | default:item.cover.url }}"
|
||||
alt="{{ item.title }}"
|
||||
loading="lazy">
|
||||
<div class="card-title">
|
||||
<i class="fa-solid fa-circle-play"></i> {{ item.title }}
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</details>
|
||||
</article>
|
||||
</section>
|
||||
{% endif %}
|
||||
{% if books_in_progress %}
|
||||
<section>
|
||||
<article>
|
||||
<details class="auto-collapse" open>
|
||||
<summary>{% trans '在读的书' %}</summary>
|
||||
<div class="shelf">
|
||||
<ul class="cards">
|
||||
{% for item in books_in_progress %}
|
||||
<li class="card">
|
||||
<a href="{{ item.url }}" title="{{ item.title }}">
|
||||
<img src="{{ item.cover|thumb:'normal' }}"
|
||||
alt="{{ item.title }}"
|
||||
loading="lazy">
|
||||
<div class="card-title">{{ item.title }}</div>
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</details>
|
||||
</article>
|
||||
</section>
|
||||
{% endif %}
|
||||
{% if tvshows_in_progress %}
|
||||
<section>
|
||||
<article>
|
||||
<details class="auto-collapse" open>
|
||||
<summary>{% trans '在看的剧集' %}</summary>
|
||||
<div class="shelf">
|
||||
<ul class="cards">
|
||||
{% for item in tvshows_in_progress %}
|
||||
<li class="card">
|
||||
<a href="{{ item.url }}" title="{{ item.title }}">
|
||||
<img src="{{ item.cover|thumb:'normal' }}"
|
||||
alt="{{ item.title }}"
|
||||
loading="lazy">
|
||||
<div class="card-title">{{ item.title }}</div>
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</details>
|
||||
</article>
|
||||
</section>
|
||||
{% endif %}
|
||||
{% if top_tags %}
|
||||
<section>
|
||||
<article>
|
||||
<details {% if top_tags %}class="auto-collapse" open{% endif %}>
|
||||
<summary>{% trans '常用标签' %}</summary>
|
||||
<div class="tag-list">
|
||||
{% for t in top_tags %}
|
||||
<span>
|
||||
<a href="{% url 'journal:user_tag_member_list' user.mastodon_username t %}">{{ t }}</a>
|
||||
</span>
|
||||
{% empty %}
|
||||
<div class="empty">暂无可见标签</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<small>
|
||||
{% if top_tags %}
|
||||
<a href="{% url 'journal:user_tag_list' user.mastodon_username %}">...{% trans '全部' %}</a>
|
||||
{% endif %}
|
||||
</small>
|
||||
</details>
|
||||
</article>
|
||||
</section>
|
||||
{% endif %}
|
||||
</aside>
|
||||
<script>
|
||||
$(function () {
|
||||
function _sidebar_auto_collapse(mm){
|
||||
if (mm.matches) {
|
||||
$('.auto-collapse').removeAttr('open')
|
||||
} else {
|
||||
$('.auto-collapse').attr('open', '')
|
||||
}
|
||||
}
|
||||
var mm = window.matchMedia("(max-width: 768px)")
|
||||
mm.addListener(_sidebar_auto_collapse);
|
||||
_sidebar_auto_collapse(mm);
|
||||
});
|
||||
</script>
|
|
@ -1,9 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/4.15.5/swagger-ui.min.css" integrity="sha512-JArlzA682ixxKlWoGxYQxF+vHv527K1/NMnGbMxZERWr/16D7ZlPZUdq9+n5cA3TM030G57bSXYdN706FU9doQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
<link rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/4.15.5/swagger-ui.min.css"
|
||||
integrity="sha512-JArlzA682ixxKlWoGxYQxF+vHv527K1/NMnGbMxZERWr/16D7ZlPZUdq9+n5cA3TM030G57bSXYdN706FU9doQ=="
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer" />
|
||||
<title>{{ api.title }} API Documentation</title>
|
||||
{% include "common_libs.html" with jquery=0 %}
|
||||
{% include "common_libs.html" with jquery=0 v2=1 %}
|
||||
<style type="text/css">
|
||||
.information-container {
|
||||
display: none;
|
||||
|
@ -11,13 +15,13 @@
|
|||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="content-wrapper">
|
||||
{% include "partial/_navbar.html" %}
|
||||
|
||||
<div id="swagger-ui">
|
||||
</div>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/4.15.5/swagger-ui-bundle.min.js" integrity="sha512-8FFvTCXo6KgUt72SMpgMgMHoHnNUOPxndku0/mc+B98qIeEfZ6dpPDYJv6a1TRWHoEZeMQAKQzcwSmQixM9v2w==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
{% include "_header.html" %}
|
||||
<div id="swagger-ui" class="container"></div>
|
||||
{% include "partial/_footer.html" %}
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/4.15.5/swagger-ui-bundle.min.js"
|
||||
integrity="sha512-8FFvTCXo6KgUt72SMpgMgMHoHnNUOPxndku0/mc+B98qIeEfZ6dpPDYJv6a1TRWHoEZeMQAKQzcwSmQixM9v2w=="
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"></script>
|
||||
<script>
|
||||
const ui = SwaggerUIBundle({
|
||||
url: '{{ openapi_json_url }}',
|
||||
|
@ -36,6 +40,5 @@
|
|||
deepLinking: true
|
||||
})
|
||||
</script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,32 +1,29 @@
|
|||
{% load i18n %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load l10n %}
|
||||
{% load admin_url %}
|
||||
{% load mastodon %}
|
||||
{% load oauth_token %}
|
||||
{% load truncate %}
|
||||
{% load thumb %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="refresh" content="5;url={% if url %}{{url}}{% else %}{% url 'common:home' %}{% endif %}">
|
||||
<link rel="stylesheet" href="https://cdn.staticfile.org/milligram/1.4.1/milligram.min.css">
|
||||
<link rel="stylesheet" href="{% static 'css/boofilsic_edit.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'css/boofilsic_box.css' %}">
|
||||
<title>{% trans '错误' %}</title>
|
||||
<title>{{ site_name }} - {% trans '错误' %}</title>
|
||||
{% include "common_libs.html" with jquery=0 v2=1 %}
|
||||
</head>
|
||||
<body>
|
||||
<div class="box">
|
||||
|
||||
<a href="{% url 'common:home' %}">
|
||||
<img src="{% static 'img/logo.svg' %}" alt="logo" class="logo">
|
||||
</a>
|
||||
<div class="main-msg">
|
||||
{{ msg }}
|
||||
</div>
|
||||
<div class="sec-msg">
|
||||
{% if secondary_msg %}
|
||||
{{ secondary_msg }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{% include "_header.html" %}
|
||||
<main class="container">
|
||||
<article class="error">
|
||||
<header>
|
||||
<h3>🙅🏻 {{ msg }}</h3>
|
||||
</header>
|
||||
{{ secondary_msg|default:"" }}
|
||||
</article>
|
||||
</main>
|
||||
{% include "partial/_footer.html" %}
|
||||
</body>
|
||||
</html>
|
|
@ -31,9 +31,7 @@
|
|||
<span class="announcement__datetime">{{ ann.created_time }}</span>
|
||||
<p class="announcement__content">{{ ann.get_plain_content | truncate:200 }}</p>
|
||||
</li>
|
||||
{% if not forloop.last %}
|
||||
<div class="dividing-line" style="border-top-style: dashed;"></div>
|
||||
{% endif %}
|
||||
{% if not forloop.last %}<div class="dividing-line" style="border-top-style: dashed;"></div>{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<div class="bottom-link">
|
||||
|
|
|
@ -2,22 +2,33 @@
|
|||
<div class="grid">
|
||||
<div class="footer__border">
|
||||
{% if social_link %}
|
||||
<a class="footer__link" target="_blank" rel="noopener" href="{{ social_link }}">关注我们</a>
|
||||
<a class="footer__link"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
href="{{ social_link }}">关注我们</a>
|
||||
{% endif %}
|
||||
{% if support_link %}
|
||||
<a class="footer__link" target="_blank" rel="noopener" href="{{ support_link }}">问题反馈</a>
|
||||
<a class="footer__link"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
href="{{ support_link }}">问题反馈</a>
|
||||
{% endif %}
|
||||
<a class="footer__link" target="_blank" rel="noopener" href="https://github.com/neodb-social">源代码</a>
|
||||
<a class="footer__link"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
href="https://github.com/neodb-social">源代码</a>
|
||||
{% if donation_link %}
|
||||
<a class="footer__link" target="_blank" rel="noopener" href="{{ donation_link }}">捐助本站</a>
|
||||
<a class="footer__link"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
href="{{ donation_link }}">捐助本站</a>
|
||||
{% endif %}
|
||||
<a class="footer__link" href="/announcement/">公告栏</a>
|
||||
<a class="footer__link" href="/api-doc/">API</a>
|
||||
<a class="footer__link" href="{% url 'management:list' %}">公告栏</a>
|
||||
<a class="footer__link" href="{% url 'common:api_doc' %}">API</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<div class="player">
|
||||
</div>
|
||||
<div class="player"></div>
|
||||
<script>
|
||||
document.body.addEventListener('htmx:configRequest', (event) => {
|
||||
event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
|
||||
|
|
|
@ -10,52 +10,84 @@
|
|||
<img src="{% static 'img/logo.svg' %}" alt="" class="navbar__logo-img">
|
||||
</a>
|
||||
<div class="navbar__search-box">
|
||||
<!-- <input type="search" name="q" id="searchInput" required="true" value="{% for v in request.GET.values %}{{ v }}{% endfor %}" -->
|
||||
<input type="search" name="q" id="searchInput" required="true" value="{% if request.GET.q %}{{ request.GET.q }}{% endif %}"
|
||||
<!-- <input type="search"
|
||||
name="q"
|
||||
id="searchInput"
|
||||
required="true"
|
||||
value="{% for v in request.GET.values %}{{ v }}{% endfor %}"
|
||||
-->
|
||||
<input type="search"
|
||||
name="q"
|
||||
id="searchInput"
|
||||
required="true"
|
||||
value="{% if request.GET.q %}{{ request.GET.q }}{% endif %}"
|
||||
placeholder="搜索书影音游戏播客,或输入站外条目链接如 https://movie.douban.com/subject/1297880/ 支持站点列表见页底公告栏">
|
||||
<select class="navbar__search-dropdown" id="searchCategory" name="c">
|
||||
<option value="all" {% if request.GET.c and request.GET.c == 'all' or not request.GET.c %}selected{% endif %}>{% trans '任意' %}</option>
|
||||
<option value="book" {% if request.GET.c and request.GET.c == 'book' or '/book/' in request.path %}selected{% endif %}>{% trans '书籍' %}</option>
|
||||
<option value="movie" {% if request.GET.c and request.GET.c == 'movie' or '/movie/' in request.path %}selected{% endif %}>{% trans '电影' %}</option>
|
||||
<option value="tv" {% if request.GET.c and request.GET.c == 'tv' or '/tv/' in request.path %}selected{% endif %}>{% trans '剧集' %}</option>
|
||||
<option value="podcast" {% if request.GET.c and request.GET.c == 'podcast' or '/podcast/' in request.path %}selected{% endif %}>{% trans '播客' %}</option>
|
||||
<option value="music" {% if request.GET.c and request.GET.c == 'music' or '/album/' in request.path %}selected{% endif %}>{% trans '音乐' %}</option>
|
||||
<option value="game" {% if request.GET.c and request.GET.c == 'game' or '/game/' in request.path %}selected{% endif %}>{% trans '游戏' %}</option>
|
||||
|
||||
<option value="all"
|
||||
{% if request.GET.c and request.GET.c == 'all' or not request.GET.c %}selected{% endif %}>
|
||||
{% trans '任意' %}
|
||||
</option>
|
||||
<option value="book"
|
||||
{% if request.GET.c and request.GET.c == 'book' or '/book/' in request.path %}selected{% endif %}>
|
||||
{% trans '书籍' %}
|
||||
</option>
|
||||
<option value="movie"
|
||||
{% if request.GET.c and request.GET.c == 'movie' or '/movie/' in request.path %}selected{% endif %}>
|
||||
{% trans '电影' %}
|
||||
</option>
|
||||
<option value="tv"
|
||||
{% if request.GET.c and request.GET.c == 'tv' or '/tv/' in request.path %}selected{% endif %}>
|
||||
{% trans '剧集' %}
|
||||
</option>
|
||||
<option value="podcast"
|
||||
{% if request.GET.c and request.GET.c == 'podcast' or '/podcast/' in request.path %}selected{% endif %}>
|
||||
{% trans '播客' %}
|
||||
</option>
|
||||
<option value="music"
|
||||
{% if request.GET.c and request.GET.c == 'music' or '/album/' in request.path %}selected{% endif %}>
|
||||
{% trans '音乐' %}
|
||||
</option>
|
||||
<option value="game"
|
||||
{% if request.GET.c and request.GET.c == 'game' or '/game/' in request.path %}selected{% endif %}>
|
||||
{% trans '游戏' %}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<ul class="navbar__link-list">
|
||||
|
||||
{% if request.user.is_authenticated %}
|
||||
|
||||
<a class="navbar__link {% if current == 'discover' %}current{% endif %}" href="{% url 'catalog:discover' %}">{% trans '发现' %}</a>
|
||||
<a class="navbar__link {% if current == 'timeline' %}current{% endif %}" href="{% url 'social:feed' %}">{% trans '动态' %}</a>
|
||||
<a class="navbar__link {% if current == 'home' %}current{% endif %}" href="{% url 'journal:user_profile' request.user.mastodon_username %}">{% trans '个人主页' %}</a>
|
||||
<a class="navbar__link {% if current == 'discover' %}current{% endif %}"
|
||||
href="{% url 'catalog:discover' %}">{% trans '发现' %}</a>
|
||||
<a class="navbar__link {% if current == 'timeline' %}current{% endif %}"
|
||||
href="{% url 'social:feed' %}">{% trans '动态' %}</a>
|
||||
<a class="navbar__link {% if current == 'home' %}current{% endif %}"
|
||||
href="{% url 'journal:user_profile' request.user.mastodon_username %}">{% trans '个人主页' %}</a>
|
||||
<div class="navbar__link dropdown">
|
||||
<a class="dropbtn"><i class="fa-solid fa-gear" title="{% trans '更多' %}"></i></a>
|
||||
<div class="dropdown-content">
|
||||
<a class="navbar__link {% if current == 'data' %}current{% endif %}" href="{% url 'users:data' %}">{% trans '数据' %}</a>
|
||||
<a class="navbar__link {% if current == 'preferences' %}current{% endif %}" href="{% url 'users:preferences' %}">{% trans '设置' %}</a>
|
||||
<a class="navbar__link {% if current == 'data' %}current{% endif %}"
|
||||
href="{% url 'users:data' %}">{% trans '数据' %}</a>
|
||||
<a class="navbar__link {% if current == 'preferences' %}current{% endif %}"
|
||||
href="{% url 'users:preferences' %}">{% trans '设置' %}</a>
|
||||
<a class="navbar__link" id="logoutLink" href="{% url 'users:logout' %}">{% trans '登出' %}</a>
|
||||
{% if request.user.is_superuser %}
|
||||
<a class="navbar__link" href="{% admin_url %}">{% trans '后台' %}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% else %}
|
||||
<a class="navbar__link" href="{% url 'users:login' %}?next={{ request.path }}">{% trans '登录' %}</a>
|
||||
<a class="navbar__link"
|
||||
href="{% url 'users:login' %}?next={{ request.path }}">{% trans '登录' %}</a>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</nav>
|
||||
</section>
|
||||
</form>
|
||||
|
||||
{% if messages %}
|
||||
<div class="main-section-wrapper" style="margin-bottom: 10px; text-align:center;">
|
||||
<div class="main-section-wrapper"
|
||||
style="margin-bottom: 10px;
|
||||
text-align:center">
|
||||
<ul class="messages">
|
||||
{% for message in messages %}
|
||||
<li {% if message.tags %}class="{{ message.tags }}"{% endif %}>{{ message }}</li>
|
||||
|
|
|
@ -7,25 +7,28 @@
|
|||
{% load thumb %}
|
||||
{% load collection %}
|
||||
{% load bleach_tags %}
|
||||
|
||||
<div class="grid__aside grid__aside--reverse-order grid__aside--tablet-column">
|
||||
<div class="aside-section-wrapper aside-section-wrapper--no-margin">
|
||||
<div class="user-profile" id="userInfoCard">
|
||||
<div class="user-profile__header">
|
||||
<!-- <img src="" class="user-profile__avatar mast-avatar" alt="{{ user.username }}"> -->
|
||||
<img src="{{ user.mastodon_account.avatar }}" class="user-profile__avatar mast-avatar">
|
||||
<!-- <img src=""
|
||||
class="user-profile__avatar mast-avatar"
|
||||
alt="{{ user.username }}"> -->
|
||||
<img src="{{ user.mastodon_account.avatar }}"
|
||||
class="user-profile__avatar mast-avatar"
|
||||
alt="">
|
||||
<a href="{% url 'journal:user_profile' user.mastodon_username %}">
|
||||
<h5 class="user-profile__username mast-displayname">{{ user.mastodon_account.display_name }}</h5>
|
||||
</a>
|
||||
<!-- {{ user.id }} -->
|
||||
</div>
|
||||
<p><a class="user-profile__link mast-acct" target="_blank" rel="me noopener" href="{{ user.mastodon_account.url }}">@{{ user.username }}@{{ user.mastodon_site }}</a>
|
||||
<p>
|
||||
<a class="user-profile__link mast-acct"
|
||||
target="_blank"
|
||||
rel="me noopener"
|
||||
href="{{ user.mastodon_account.url }}">@{{ user.username }}@{{ user.mastodon_site }}</a>
|
||||
{% current_user_relationship user as relationship %}
|
||||
{% if relationship %}
|
||||
<a class="user-profile__report-link">
|
||||
{{ relationship }}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if relationship %}<a class="user-profile__report-link">{{ relationship }}</a>{% endif %}
|
||||
</p>
|
||||
<div class="relation-dropdown">
|
||||
<div class="relation-dropdown__body">
|
||||
|
@ -38,7 +41,6 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relation-dropdown">
|
||||
<div class="relation-dropdown__button">
|
||||
<span class="icon-arrow">
|
||||
|
@ -49,17 +51,17 @@
|
|||
<div class="relation-dropdown__body">
|
||||
<div class="aside-section-wrapper aside-section-wrapper--transparent aside-section-wrapper--collapse">
|
||||
<div class="user-relation">
|
||||
<h5 class="user-relation__label">
|
||||
{% trans '当前目标' %}
|
||||
</h5>
|
||||
<h5 class="user-relation__label">{% trans '当前目标' %}</h5>
|
||||
{% for featured_collection in user.featured_collections.all %}
|
||||
{% user_visibility_of featured_collection as visible %}
|
||||
{% if visible %}
|
||||
{% user_progress_of collection=featured_collection user=user as progress %}
|
||||
<div class="tag-collection" style="margin-left: 10%;">
|
||||
<a href="{{ featured_collection.collection.url }}">{{ featured_collection.collection.title }}</a><br>
|
||||
已完成{{ progress }}% <br>
|
||||
<progress value="{{ progress }}" max="100">
|
||||
<a href="{{ featured_collection.collection.url }}">{{ featured_collection.collection.title }}</a>
|
||||
<br>
|
||||
已完成{{ progress }}%
|
||||
<br>
|
||||
<progress value="{{ progress }}" max="100" />
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
@ -68,73 +70,59 @@
|
|||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if user == request.user %}
|
||||
<div class="relation-dropdown__body">
|
||||
<div class="aside-section-wrapper aside-section-wrapper--transparent aside-section-wrapper--collapse">
|
||||
<div class="user-relation" id="followings">
|
||||
<h5 class="user-relation__label">
|
||||
{% trans '关注的人' %}
|
||||
</h5>
|
||||
<h5 class="user-relation__label">{% trans '关注的人' %}</h5>
|
||||
<a href="{% url 'users:following' user.mastodon_username %}"
|
||||
class="user-relation__more-link mast-following-more">{% trans '更多' %}</a>
|
||||
<ul class="user-relation__related-user-list mast-following">
|
||||
<li class="user-relation__related-user">
|
||||
<a>
|
||||
<img src="" alt="" class="user-relation__related-user-avatar">
|
||||
<div class="user-relation__related-user-name mast-displayname">
|
||||
</div>
|
||||
<div class="user-relation__related-user-name mast-displayname"></div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="user-relation" id="followers">
|
||||
<h5 class="user-relation__label">
|
||||
{% trans '被他们关注' %}
|
||||
</h5>
|
||||
<h5 class="user-relation__label">{% trans '被他们关注' %}</h5>
|
||||
<a href="{% url 'users:followers' user.mastodon_username %}"
|
||||
class="user-relation__more-link mast-followers-more">{% trans '更多' %}</a>
|
||||
<ul class="user-relation__related-user-list mast-followers">
|
||||
<li class="user-relation__related-user">
|
||||
<a>
|
||||
<img src="" alt="" class="user-relation__related-user-avatar">
|
||||
<div class="user-relation__related-user-name mast-displayname">
|
||||
</div>
|
||||
<div class="user-relation__related-user-name mast-displayname"></div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{% if top_tags %}
|
||||
<div class="user-relation">
|
||||
<h5 class="user-relation__label">
|
||||
{% trans '常用标签' %}
|
||||
</h5>
|
||||
<h5 class="user-relation__label">{% trans '常用标签' %}</h5>
|
||||
<a href="{% url 'journal:user_tag_list' user.mastodon_username %}">{% trans '更多' %}</a>
|
||||
<div class="tag-collection" style="margin-left: 0;">
|
||||
{% for t in top_tags %}
|
||||
<span class="tag-collection__tag">
|
||||
<a href="/users/{{ user.mastodon_username }}/tags/{{ t }}/">{{ t }}</a>
|
||||
<a href="{% url 'journal:user_tag_member_list' user.mastodon_username t %}">{{ t }}</a>
|
||||
</span>
|
||||
{% endfor %}
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if user == request.user %}
|
||||
<div id="oauth2Token" hidden="true">{{ request.user.mastodon_token }}</div>
|
||||
<div id="mastodonURI" hidden="true">{{ request.user.mastodon_site }}</div>
|
||||
<div id="userMastodonID" hidden="true">{{ user.mastodon_id }}</div>
|
||||
<div id="userPageURL" hidden="true">{% url 'journal:user_profile' 0 %}</div>
|
||||
|
||||
<div id="spinner" hidden>
|
||||
<div class="spinner">
|
||||
<div></div>
|
||||
|
|
28
common/templates/partial/_sidebar_anonymous.html
Normal file
28
common/templates/partial/_sidebar_anonymous.html
Normal file
|
@ -0,0 +1,28 @@
|
|||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load admin_url %}
|
||||
{% load mastodon %}
|
||||
{% load oauth_token %}
|
||||
{% load truncate %}
|
||||
{% load thumb %}
|
||||
{% load collection %}
|
||||
{% load bleach_tags %}
|
||||
<div class="grid__aside grid__aside--reverse-order">
|
||||
<section>
|
||||
<article>
|
||||
<h3>欢迎 🙋🏻♀️ 🙋🏻 🙋🏻♂️</h3>
|
||||
<p>
|
||||
<i class="fa-solid fa-puzzle-piece"></i> {{ site_name }}致力于提供一个涵盖书籍、影视、音乐、游戏、播客的自由开放互联的收藏评论空间。 你可以在这里记录你的收藏和想法,以及发现新的内容和朋友。
|
||||
</p>
|
||||
<p>
|
||||
<i class="fa-solid fa-globe"></i> 登录{{ site_name }}需要一个联邦网络(Fediverse,也被称为长毛象)实例账号,如果你还没有账号,可以<a href="https://joinmastodon.org/zh/servers" target="_blank">到这里注册</a>。
|
||||
</p>
|
||||
<p>
|
||||
<i class="fa-solid fa-circle-question"></i> 如果有任何问题或建议,欢迎通过<a href="https://mastodon.social/@neodb">联邦网络</a>或<a href="https://discord.gg/uprvcH8gqD">Discord</a>和我们联系。
|
||||
</p>
|
||||
<p>
|
||||
<i class="fa-solid fa-door-open"></i> <a href="/users/login/">点击这里</a>登录。
|
||||
</p>
|
||||
</article>
|
||||
</section>
|
||||
</div>
|
|
@ -9,20 +9,22 @@
|
|||
margin-left: 1%;
|
||||
}
|
||||
</style>
|
||||
<div class="widget-value-key-input" name='{{ widget.name }}'{% include "django/forms/widgets/attrs.html" %}>
|
||||
<div class="widget-value-key-input"
|
||||
name='{{ widget.name }}'
|
||||
{% include "django/forms/widgets/attrs.html" %}>
|
||||
{% if widget.value != None %}
|
||||
|
||||
{% for pair in widget.value %}
|
||||
|
||||
{% for k, v in pair.items %}
|
||||
<input type="text" value="{{ k }}"><input type="text" value="{{ v }}">
|
||||
<input type="text" value="{{ k }}">
|
||||
<input type="text" value="{{ v }}">
|
||||
{% endfor %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{% endif %}
|
||||
</div>
|
||||
<input type="text" class="widget-value-key-input-data" hidden name="{{ widget.name }}">
|
||||
<input type="text"
|
||||
class="widget-value-key-input-data"
|
||||
hidden
|
||||
name="{{ widget.name }}">
|
||||
<script>
|
||||
keyValueInput(
|
||||
$(".widget-value-key-input[name='{{ widget.name }}']"),
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
<input type="{{ widget.type }}" name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %}>
|
||||
<img src="{{ widget.value|default_if_none:''|stringformat:'s' }}" alt="" id="previewImage" style="margin:10px 0; max-width:500px;">
|
||||
<input type="{{ widget.type }}"
|
||||
name="{{ widget.name }}"
|
||||
{% include "django/forms/widgets/attrs.html" %}>
|
||||
<img src="{{ widget.value|default_if_none:''|stringformat:'s' }}"
|
||||
alt=""
|
||||
id="previewImage"
|
||||
style="margin:10px 0;
|
||||
max-width:500px">
|
||||
<script>
|
||||
$("input[type='file'][name='{{ widget.name }}']").on("change", function () {
|
||||
if (this.files && this.files[0]) {
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
<select name="{{ widget.name }}"
|
||||
{% include "django/forms/widgets/attrs.html" %}>{% for group_name, group_choices, group_index in widget.optgroups %}{% if group_name %}
|
||||
<optgroup label="{{ group_name }}">{% endif %}{% for option in group_choices %}
|
||||
{% include option.template_name with widget=option %}{% endfor %}{% if group_name %}
|
||||
</optgroup>{% endif %}{% endfor %}
|
||||
{% include "django/forms/widgets/attrs.html" %}>
|
||||
{% for group_name, group_choices, group_index in widget.optgroups %}
|
||||
{% if group_name %}<optgroup label="{{ group_name }}">{% endif %}
|
||||
{% for option in group_choices %}
|
||||
{% include option.template_name with widget=option %}
|
||||
{% endfor %}
|
||||
{% if group_name %}</optgroup>{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
<script>
|
||||
$('select[name="{{ widget.name }}"]').multipleSelect({
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<div class="tag-input">
|
||||
<input type="text" name="{{ widget.name }}" {% include "django/forms/widgets/attrs.html" %}>
|
||||
<input type="text"
|
||||
name="{{ widget.name }}"
|
||||
{% include "django/forms/widgets/attrs.html" %}>
|
||||
</div>
|
||||
<script>
|
||||
new inputTags({
|
||||
|
@ -10,8 +12,3 @@
|
|||
onTagRemove : function (tag) {},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
from django import template
|
||||
from django.template.defaultfilters import stringfilter
|
||||
from django.utils.text import Truncator
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
@ -14,3 +15,19 @@ def duration_format(value, unit):
|
|||
s = duration % 60
|
||||
return f"{h}:{m:02}:{s:02}" if h else f"{m}:{s:02}"
|
||||
# return (f"{h}小时 " if h else "") + (f"{m}分钟" if m else "")
|
||||
|
||||
|
||||
@register.filter(is_safe=True)
|
||||
@stringfilter
|
||||
def rating_star(value):
|
||||
try:
|
||||
v = float(value or 0)
|
||||
except ValueError:
|
||||
v = 0
|
||||
pct = round(10 * v)
|
||||
if pct > 100:
|
||||
pct = 100
|
||||
elif pct < 0:
|
||||
pct = 0
|
||||
html = f'<span class="rating-star" data-rating="{v}"><div style="width:{pct}%;"></div></span>'
|
||||
return mark_safe(html)
|
||||
|
|
|
@ -2,7 +2,7 @@ from django import template
|
|||
from django.utils.safestring import mark_safe
|
||||
from django.template.defaultfilters import stringfilter
|
||||
from opencc import OpenCC
|
||||
|
||||
import re
|
||||
|
||||
cc = OpenCC("t2s")
|
||||
register = template.Library()
|
||||
|
@ -23,7 +23,7 @@ def highlight(text, search):
|
|||
m = None
|
||||
for w in words:
|
||||
if otext[i : i + len(w)] == w:
|
||||
m = f'<span class="highlight">{text[i:i+len(w)]}</span>'
|
||||
m = f"<mark>{text[i:i+len(w)]}</mark>"
|
||||
i += len(w)
|
||||
break
|
||||
if not m:
|
||||
|
@ -31,3 +31,9 @@ def highlight(text, search):
|
|||
i += 1
|
||||
rtext += m
|
||||
return mark_safe(rtext)
|
||||
|
||||
|
||||
@register.filter
|
||||
@stringfilter
|
||||
def strip_season(text):
|
||||
return re.sub(r"\s*第\s*\d+\s*季$", "", text)
|
||||
|
|
|
@ -4,6 +4,7 @@ from .views import *
|
|||
app_name = "common"
|
||||
urlpatterns = [
|
||||
path("", home),
|
||||
path("api-doc/", api_doc),
|
||||
path("api-doc/", api_doc, name="api_doc"),
|
||||
path("home/", home, name="home"),
|
||||
path("me/", me, name="me"),
|
||||
]
|
||||
|
|
|
@ -6,7 +6,14 @@ from .api import api
|
|||
|
||||
|
||||
@login_required
|
||||
def me(request):
|
||||
return redirect(
|
||||
reverse("journal:user_profile", args=[request.user.mastodon_username])
|
||||
)
|
||||
|
||||
|
||||
def home(request):
|
||||
if request.user.is_authenticated:
|
||||
home = request.user.get_preference().classic_homepage
|
||||
if home == 1:
|
||||
return redirect(
|
||||
|
@ -16,6 +23,8 @@ def home(request):
|
|||
return redirect(reverse("social:feed"))
|
||||
else:
|
||||
return redirect(reverse("catalog:discover"))
|
||||
else:
|
||||
return redirect(reverse("catalog:discover"))
|
||||
|
||||
|
||||
def error_400(request, exception=None):
|
||||
|
|
|
@ -47,6 +47,7 @@ Build static assets
|
|||
```
|
||||
python3 manage.py sass common/static/sass/boofilsic.sass common/static/css/boofilsic.min.css -t compressed
|
||||
python3 manage.py sass common/static/sass/boofilsic.sass common/static/css/boofilsic.css
|
||||
python3 manage.py compilescss
|
||||
python3 manage.py collectstatic
|
||||
```
|
||||
|
||||
|
|
|
@ -156,12 +156,6 @@ class Content(Piece):
|
|||
metadata = models.JSONField(default=dict)
|
||||
item = models.ForeignKey(Item, on_delete=models.PROTECT)
|
||||
|
||||
@cached_property
|
||||
def mark(self):
|
||||
m = Mark(self.owner, self.item)
|
||||
m.review = self
|
||||
return m
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.uuid}@{self.item}"
|
||||
|
||||
|
@ -221,6 +215,16 @@ class Comment(Content):
|
|||
def html(self):
|
||||
return render_text(self.text)
|
||||
|
||||
@cached_property
|
||||
def rating_grade(self):
|
||||
return Rating.get_item_rating_by_user(self.item, self.owner)
|
||||
|
||||
@cached_property
|
||||
def mark(self):
|
||||
m = Mark(self.owner, self.item)
|
||||
m.comment = self
|
||||
return m
|
||||
|
||||
@property
|
||||
def item_url(self):
|
||||
if self.focus_item:
|
||||
|
@ -259,6 +263,19 @@ class Review(Content):
|
|||
def html_content(self):
|
||||
return render_md(self.body)
|
||||
|
||||
@property
|
||||
def plain_content(self):
|
||||
html = render_md(self.body)
|
||||
return _RE_HTML_TAG.sub(
|
||||
" ", _RE_SPOILER_TAG.sub("***", html.replace("\n", " "))
|
||||
)
|
||||
|
||||
@cached_property
|
||||
def mark(self):
|
||||
m = Mark(self.owner, self.item)
|
||||
m.review = self
|
||||
return m
|
||||
|
||||
@cached_property
|
||||
def rating_grade(self):
|
||||
return Rating.get_item_rating_by_user(self.item, self.owner)
|
||||
|
@ -291,6 +308,9 @@ class Review(Content):
|
|||
return review
|
||||
|
||||
|
||||
MIN_RATING_COUNT = 5
|
||||
|
||||
|
||||
class Rating(Content):
|
||||
class Meta:
|
||||
unique_together = [["owner", "item"]]
|
||||
|
@ -304,7 +324,7 @@ class Rating(Content):
|
|||
stat = Rating.objects.filter(item=item, grade__isnull=False).aggregate(
|
||||
average=Avg("grade"), count=Count("item")
|
||||
)
|
||||
return round(stat["average"], 1) if stat["count"] >= 5 else None
|
||||
return round(stat["average"], 1) if stat["count"] >= MIN_RATING_COUNT else None
|
||||
|
||||
@staticmethod
|
||||
def get_rating_count_for_item(item):
|
||||
|
@ -337,9 +357,34 @@ class Rating(Content):
|
|||
rating = Rating.objects.filter(owner=user, item=item).first()
|
||||
return rating.grade if rating else None
|
||||
|
||||
@staticmethod
|
||||
def get_rating_distribution_for_item(item):
|
||||
stat = (
|
||||
Rating.objects.filter(item=item, grade__isnull=False)
|
||||
.values("grade")
|
||||
.annotate(count=Count("grade"))
|
||||
.order_by("grade")
|
||||
)
|
||||
g = [0] * 11
|
||||
t = 0
|
||||
for s in stat:
|
||||
g[s["grade"]] = s["count"]
|
||||
t += s["count"]
|
||||
if t < MIN_RATING_COUNT:
|
||||
return [0] * 5
|
||||
r = [
|
||||
100 * (g[1] + g[2]) // t,
|
||||
100 * (g[3] + g[4]) // t,
|
||||
100 * (g[5] + g[6]) // t,
|
||||
100 * (g[7] + g[8]) // t,
|
||||
100 * (g[9] + g[10]) // t,
|
||||
]
|
||||
return r
|
||||
|
||||
|
||||
Item.rating = property(Rating.get_rating_for_item)
|
||||
Item.rating_count = property(Rating.get_rating_count_for_item)
|
||||
Item.rating_dist = property(Rating.get_rating_distribution_for_item)
|
||||
|
||||
|
||||
class Reply(Piece):
|
||||
|
@ -440,6 +485,17 @@ class List(Piece):
|
|||
)
|
||||
member.delete()
|
||||
|
||||
def update_member_order(self, ordered_member_ids):
|
||||
members = self.ordered_members
|
||||
for m in self.members.all():
|
||||
try:
|
||||
i = ordered_member_ids.index(m.id)
|
||||
if m.position != i + 1:
|
||||
m.position = i + 1
|
||||
m.save()
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
def move_up_item(self, item):
|
||||
members = self.ordered_members
|
||||
member = self.get_member_for_item(item)
|
||||
|
@ -674,8 +730,11 @@ class ShelfManager:
|
|||
def get_shelf(self, shelf_type):
|
||||
return self.shelf_list[shelf_type]
|
||||
|
||||
def get_members(self, shelf_type, item_category):
|
||||
def get_members(self, shelf_type, item_category=None):
|
||||
if item_category:
|
||||
return self.shelf_list[shelf_type].get_members_in_category(item_category)
|
||||
else:
|
||||
return self.shelf_list[shelf_type].members.all()
|
||||
|
||||
# def get_items_on_shelf(self, item_category, shelf_type):
|
||||
# shelf = (
|
||||
|
@ -748,6 +807,7 @@ class CollectionMember(ListMember):
|
|||
|
||||
|
||||
_RE_HTML_TAG = re.compile(r"<[^>]*>")
|
||||
_RE_SPOILER_TAG = re.compile(r'<(div|span)\sclass="spoiler">.*</(div|span)>')
|
||||
|
||||
|
||||
class Collection(List):
|
||||
|
@ -781,8 +841,9 @@ class Collection(List):
|
|||
html = render_md(self.brief)
|
||||
return _RE_HTML_TAG.sub(" ", html)
|
||||
|
||||
def is_featured_by_user(self, user):
|
||||
return self.featured_by_users.all().filter(id=user.id).exists()
|
||||
def featured_by_user_since(self, user):
|
||||
f = FeaturedCollection.objects.filter(target=self, owner=user).first()
|
||||
return f.created_time if f else None
|
||||
|
||||
def get_stats_for_user(self, user):
|
||||
items = list(self.members.all().values_list("item_id", flat=True))
|
||||
|
@ -881,13 +942,15 @@ class TagManager:
|
|||
return sorted(list(map(lambda t: t["title"], tags)))
|
||||
|
||||
@staticmethod
|
||||
def all_tags_for_user(user):
|
||||
def all_tags_for_user(user, public_only=False):
|
||||
tags = (
|
||||
user.tag_set.all()
|
||||
.values("title")
|
||||
.annotate(frequency=Count("members__id"))
|
||||
.order_by("-frequency")
|
||||
)
|
||||
if public_only:
|
||||
tags = tags.filter(visibility=0)
|
||||
return list(map(lambda t: t["title"], tags))
|
||||
|
||||
@staticmethod
|
||||
|
@ -935,6 +998,10 @@ class TagManager:
|
|||
def all_tags(self):
|
||||
return TagManager.all_tags_for_user(self.owner)
|
||||
|
||||
@property
|
||||
def public_tags(self):
|
||||
return TagManager.all_tags_for_user(self.owner, public_only=True)
|
||||
|
||||
def add_item_tags(self, item, tags, visibility=0):
|
||||
for tag in tags:
|
||||
TagManager.add_tag_by_user(item, tag, self.owner, visibility)
|
||||
|
@ -1021,6 +1088,10 @@ class Mark:
|
|||
def rating(self):
|
||||
return Rating.get_item_rating_by_user(self.item, self.owner)
|
||||
|
||||
@cached_property
|
||||
def rating_grade(self):
|
||||
return Rating.get_item_rating_by_user(self.item, self.owner)
|
||||
|
||||
@cached_property
|
||||
def comment(self):
|
||||
return Comment.objects.filter(
|
||||
|
@ -1059,7 +1130,8 @@ class Mark:
|
|||
)
|
||||
)
|
||||
share_as_new_post = shelf_type != self.shelf_type
|
||||
if shelf_type != self.shelf_type or visibility != self.visibility:
|
||||
original_visibility = self.visibility
|
||||
if shelf_type != self.shelf_type or visibility != original_visibility:
|
||||
self.shelfmember = self.owner.shelf_manager.move_item(
|
||||
self.item, shelf_type, visibility=visibility, metadata=metadata
|
||||
)
|
||||
|
@ -1082,11 +1154,11 @@ class Mark:
|
|||
metadata=self.metadata,
|
||||
timestamp=created_time,
|
||||
)
|
||||
if comment_text != self.text or visibility != self.visibility:
|
||||
if comment_text != self.text or visibility != original_visibility:
|
||||
self.comment = Comment.comment_item_by_user(
|
||||
self.item, self.owner, comment_text, visibility
|
||||
)
|
||||
if rating_grade != self.rating or visibility != self.visibility:
|
||||
if rating_grade != self.rating or visibility != original_visibility:
|
||||
Rating.rate_item_by_user(self.item, self.owner, rating_grade, visibility)
|
||||
self.rating = rating_grade
|
||||
if share:
|
||||
|
@ -1120,7 +1192,7 @@ class Mark:
|
|||
)
|
||||
|
||||
|
||||
def reset_visibility_for_user(user: User, visibility: int):
|
||||
def reset_journal_visibility_for_user(user: User, visibility: int):
|
||||
ShelfMember.objects.filter(owner=user).update(visibility=visibility)
|
||||
Comment.objects.filter(owner=user).update(visibility=visibility)
|
||||
Rating.objects.filter(owner=user).update(visibility=visibility)
|
||||
|
|
|
@ -37,7 +37,7 @@ def _spolier(s):
|
|||
r = l[1].split("!<", 1)
|
||||
return (
|
||||
escape(l[0])
|
||||
+ '<span class="spoiler">'
|
||||
+ '<span class="spoiler" _="on click toggle .revealed on me">'
|
||||
+ escape(r[0])
|
||||
+ "</span>"
|
||||
+ (_spolier(r[1]) if len(r) == 2 else "")
|
||||
|
|
17
journal/templates/_feature_stats.html
Normal file
17
journal/templates/_feature_stats.html
Normal file
|
@ -0,0 +1,17 @@
|
|||
<form style="display:none"
|
||||
action="{% if featured %}{% url 'journal:collection_remove_featured' collection.uuid %}{% else %}{% url 'journal:collection_add_featured' collection.uuid %}{% endif %}"
|
||||
method="post"
|
||||
id="feature-form">
|
||||
{% csrf_token %}
|
||||
</form>
|
||||
{% if featured %}
|
||||
<a class="activated"
|
||||
title="停止追踪目标"
|
||||
onclick="if (confirm('停止这个目标吗?')) $('#feature-form').submit();">
|
||||
<i class="fa-solid fa-circle-dot"></i>
|
||||
</a>
|
||||
{% else %}
|
||||
<a title="设为目标" onclick="$('#feature-form').submit()">
|
||||
<i class="fa-regular fa-circle-dot"></i>
|
||||
</a>
|
||||
{% endif %}
|
|
@ -8,22 +8,27 @@
|
|||
{% load truncate %}
|
||||
{% load highlight %}
|
||||
{% load thumb %}
|
||||
|
||||
<div id="modal" _="on closeModal add .closing then wait for animationend then remove me">
|
||||
<div id="modal"
|
||||
_="on closeModal add .closing then wait for animationend then remove me">
|
||||
<div class="modal-underlay" _="on click trigger closeModal"></div>
|
||||
<div class="modal-content">
|
||||
<div class="add-to-list-modal__head">
|
||||
<span class="add-to-list-modal__title">{% trans '添加到收藏单' %}</span>
|
||||
<span class="add-to-list-modal__close-button modal-close" _="on click trigger closeModal">
|
||||
<span class="add-to-list-modal__close-button modal-close"
|
||||
_="on click trigger closeModal">
|
||||
<i class="fa-solid fa-xmark"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="add-to-list-modal__body">
|
||||
<form action="{% url 'journal:add_to_collection' item.uuid %}" method="post">
|
||||
<form action="{% url 'journal:add_to_collection' item.uuid %}"
|
||||
method="post">
|
||||
{% csrf_token %}
|
||||
<select name="collection_id">
|
||||
{% for collection in collections %}
|
||||
<option value="{{ collection.id }}">{{ collection.title }}{% if collection.visibility > 0 %}🔒{% endif %}</option>
|
||||
<option value="{{ collection.id }}">
|
||||
{{ collection.title }}
|
||||
{% if collection.visibility > 0 %}🔒{% endif %}
|
||||
</option>
|
||||
{% endfor %}
|
||||
<option value="0">新建收藏单</option>
|
||||
</select>
|
||||
|
@ -31,7 +36,7 @@
|
|||
<textarea type="text" name="note" placeholder="条目备注"></textarea>
|
||||
</div>
|
||||
<div class="add-to-list-modal__confirm-button">
|
||||
<input type="submit" class="button float-right" value="{% trans '提交' %}">
|
||||
<input type="submit" class="button float-right" value="{% trans '保存' %}">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -1 +1,18 @@
|
|||
{{ calendar_data|json_script:"calendar_data" }}
|
||||
<script>
|
||||
$(".calendar_view").calendar_yearview_blocks({
|
||||
data: $("#calendar_data").text(),
|
||||
start_monday: false,
|
||||
always_show_tooltip: false,
|
||||
month_names: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
|
||||
day_names: ['', '', ''],
|
||||
colors: {
|
||||
'default': getComputedStyle(document.documentElement).getPropertyValue('--pico-form-element-background-color'),
|
||||
'book': '#B4D2A5',
|
||||
'movie': '#7CBDFE',
|
||||
'music': '#FEA36D',
|
||||
'game': '#C5A290',
|
||||
'other': '#9D6AB0'
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -9,102 +9,86 @@
|
|||
{% load thumb %}
|
||||
{% load collection %}
|
||||
{% load user_actions %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<html lang="en" class="content-page">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta property="og:title" content="{{ site_name }} {% trans '收藏单' %} - {{ collection.title }}">
|
||||
<meta property="og:title"
|
||||
content="{{ site_name }}{% trans '收藏单' %} - {{ collection.title }}">
|
||||
<meta property="og:description" content="{{ collection.description }}">
|
||||
<meta property="og:type" content="article">
|
||||
<meta property="og:article:author" content="{{ collection.owner.username }}">
|
||||
<meta property="og:article:author"
|
||||
content="{{ collection.owner.username }}">
|
||||
<meta property="og:url" content="{{ request.build_absolute_uri }}">
|
||||
<meta property="og:image" content="{{ collection.cover|thumb:'normal' }}">
|
||||
|
||||
<title>{{ site_name }} {% trans '收藏单' %} - {{ collection.title }}</title>
|
||||
|
||||
{% include "common_libs.html" with jquery=0 %}
|
||||
{% include "common_libs.html" with jquery=0 v2=1 %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="page-wrapper">
|
||||
<div id="content-wrapper">
|
||||
{% include "partial/_navbar.html" %}
|
||||
|
||||
<section id="content">
|
||||
<div class="grid">
|
||||
<div class="grid__main" id="main">
|
||||
<div class="main-section-wrapper">
|
||||
<div class="review-head">
|
||||
<h5 class="review-head__title">
|
||||
{{ collection.title }}
|
||||
</h5>
|
||||
{% if collection.visibility > 0 %}
|
||||
<i class="fa-solid fa-lock"></i>
|
||||
{% endif %}
|
||||
<div class="review-head__body">
|
||||
<div class="review-head__info">
|
||||
|
||||
<a href="{% url 'journal:user_profile' collection.owner.mastodon_username %}" class="review-head__owner-link">{{ collection.owner.mastodon_username }}</a>
|
||||
|
||||
|
||||
<span class="review-head__time">{{ collection.edited_time }}</span>
|
||||
|
||||
</div>
|
||||
<div class="action-bar">
|
||||
{% include "_header.html" %}
|
||||
<main>
|
||||
<div class="grid__main">
|
||||
<article>
|
||||
<header>
|
||||
<hgroup>
|
||||
<h3>
|
||||
<div class="action">
|
||||
{% if request.user.is_authenticated %}
|
||||
<span>
|
||||
{% liked_piece collection as liked %}
|
||||
{% include 'like_stats.html' with liked=liked piece=collection %}
|
||||
{% include 'like_stats.html' with liked=liked piece=collection label='关注' icon='fa-bookmark' %}
|
||||
</span>
|
||||
{% if request.user == collection.owner %}
|
||||
<span>{% include '_feature_stats.html' with featured=featured_since %}</span>
|
||||
<span>
|
||||
<a class="review-head__action-link" href="{% url 'journal:collection_edit' collection.uuid %}">{% trans '编辑' %}</a>
|
||||
<a class="review-head__action-link" href="{% url 'journal:collection_delete' collection.uuid %}">{% trans '删除' %}</a>
|
||||
<a href="#"
|
||||
hx-get="{% url 'journal:collection_share' collection.uuid %}"
|
||||
hx-target="body"
|
||||
hx-swap="beforeend"
|
||||
title="分享到联邦网络"><i class="fa-solid fa-share-nodes"></i></a>
|
||||
</span>
|
||||
{% elif editable %}
|
||||
<span class="review-head__time">可协作整理</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="dividing-line"></div> --> <!-- <div class="entity-card__img-wrapper" style="text-align: center;"> <img src="{{ collection.cover|thumb:'normal' }}" alt="" class="entity-card__img"> </div> -->
|
||||
<div class="markdown-content">
|
||||
{{ collection.html | safe }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="entity-list" hx-get="{% url 'journal:collection_retrieve_items' collection.uuid %}" hx-trigger="load">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid__aside" id="aside">
|
||||
<div class="aside-section-wrapper">
|
||||
<div class="entity-card">
|
||||
<div class="entity-card__img-wrapper">
|
||||
<a href="{{ collection.url }}">
|
||||
<img src="{{ collection.cover|thumb:'normal' }}" alt="" class="entity-card__img">
|
||||
</a>
|
||||
</div>
|
||||
<div class="entity-card__info-wrapper">
|
||||
<h5 class="entity-card__title">
|
||||
<a href="{{ collection.url }}">
|
||||
{{ collection.title }}
|
||||
</a>
|
||||
</h5>
|
||||
{% if collection.visibility > 0 %}<small><i class="fa-solid fa-lock"></i></small>{% endif %}
|
||||
</h3>
|
||||
</hgroup>
|
||||
<div class="owner-info">
|
||||
<div class="owner">
|
||||
<span class="avatar">
|
||||
<img src="{{ collection.owner.mastodon_account.avatar }}"
|
||||
alt="{{ collection.owner.username }}">
|
||||
</span>
|
||||
</div>
|
||||
<div class="info">
|
||||
<p>
|
||||
<a href="{% url 'journal:user_profile' collection.owner.mastodon_username %}">{{ collection.owner.mastodon_account.display_name }}</a>
|
||||
<span class="handler">@{{ collection.owner.mastodon_username }}</span>
|
||||
</p>
|
||||
<p>
|
||||
{% for cat, count in collection.get_summary.items %}
|
||||
{% if count %}
|
||||
{{count}}{{cat|prural_items}}
|
||||
{% endif %}
|
||||
{% if count %}<span>{{ count }} {{ cat|prural_items }}</span> {% endif %}
|
||||
{% endfor %}
|
||||
</p>
|
||||
{% if featured_since %}
|
||||
<p>
|
||||
<progress value="{{ stats.percentage }}"
|
||||
max="100"
|
||||
title="{{ stats.percentage }}%" />
|
||||
</p>
|
||||
{% endif %}
|
||||
<div class="markdown-content">{{ collection.html | safe }}</div>
|
||||
</div>
|
||||
<div class="more">
|
||||
<div style="text-align: center;">
|
||||
<img src="{{ collection.cover|thumb:'normal' }}" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if is_featured %}
|
||||
<div class="aside-section-wrapper">
|
||||
<div class="action-panel">
|
||||
</header>
|
||||
{% comment %}
|
||||
{% if featured_since %}
|
||||
<section style="min-width:10vw;">
|
||||
<div class="donut" style="background: conic-gradient(#7CBDFE 0deg {{ stats.complete_deg }}deg, #B4D2A5 {{ stats.complete_deg }}deg {{ stats.complete_deg|add:stats.progress_deg }}deg, #ccc {{ stats.complete_deg|add:stats.progress_deg }}deg 1deg );"><div class="hole"><div class="text">
|
||||
{% if stats.progress %}
|
||||
{{ stats.progress }} 进行中<br>
|
||||
|
@ -115,81 +99,40 @@
|
|||
尚未开始
|
||||
{% endif %}
|
||||
</div></div></div>
|
||||
</div>
|
||||
|
||||
<div class="action-panel" style="margin-bottom: 0;">
|
||||
<div class="action-panel__button-group action-panel__button-group--center">
|
||||
<form action="{% url 'journal:collection_remove_featured' collection.uuid %}" method="post">
|
||||
<div style="margin:8px; color:lightgray" class="muted">
|
||||
开始于{{ featured_since|date }}
|
||||
<a class="muted" href="#" title="停止" onclick="if (confirm('停止这个目标吗?')) $('#stop-featured').submit();"><i class="fa-solid fa-ban"></i></a>
|
||||
<form action="{% url 'journal:collection_remove_featured' collection.uuid %}" method="post" id="stop-featured">
|
||||
{% csrf_token %}
|
||||
<button class="action-panel__button" title="点击取消目标设置">{% trans '当前进度' %} {{ stats.percentage }}%</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if available_as_featured %}
|
||||
<div class="aside-section-wrapper">
|
||||
<div class="action-panel">
|
||||
<div class="action-panel__button-group action-panel__button-group--center">
|
||||
<form action="{% url 'journal:collection_add_featured' collection.uuid %}" method="post">
|
||||
{% csrf_token %}
|
||||
<button class="action-panel__button">{% trans '设为目标' %}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if not is_featured and request.user.is_authenticated and request.user != collection.owner %}
|
||||
<div class="aside-section-wrapper">
|
||||
<div class="action-panel">
|
||||
<div class="action-panel__button-group action-panel__button-group--center">
|
||||
{% if following %}
|
||||
<form action="{% url 'journal:unlike' collection.uuid %}?back=1" method="post">
|
||||
{% csrf_token %}
|
||||
<button class="action-panel__button">{% trans '取消关注' %}</button>
|
||||
</form>
|
||||
{% else %}
|
||||
<form action="{% url 'journal:like' collection.uuid %}?back=1" method="post">
|
||||
{% csrf_token %}
|
||||
<button class="action-panel__button">{% trans '关注' %}</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if request.user.is_authenticated %}
|
||||
<div class="aside-section-wrapper">
|
||||
<div class="action-panel">
|
||||
<div class="action-panel__button-group action-panel__button-group--center">
|
||||
<form>
|
||||
<button class="action-panel__button add-to-list" hx-get="{% url 'journal:collection_share' collection.uuid %}" hx-target="body" hx-swap="beforeend">{% trans '分享到联邦网络' %}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
{% endcomment %}
|
||||
<section>
|
||||
<div class="entity-list"
|
||||
hx-get="{% url 'journal:collection_retrieve_items' collection.uuid %}"
|
||||
hx-trigger="load"></div>
|
||||
</section>
|
||||
<footer>
|
||||
<div class="action">
|
||||
{% if request.user == collection.owner %}
|
||||
<span>
|
||||
<a href="{% url 'journal:collection_edit' collection.uuid %}">{% trans '编辑' %}</a>
|
||||
</span>
|
||||
<span>
|
||||
<a href="{% url 'journal:collection_delete' collection.uuid %}">{% trans '删除' %}</a>
|
||||
</span>
|
||||
{% elif editable %}
|
||||
<a href="{% url 'journal:collection_edit' collection.uuid %}">{% trans '协助整理' %}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<span>创建于 {{ collection.created_time | date }}</span>
|
||||
</footer>
|
||||
</article>
|
||||
</div>
|
||||
{% include "_sidebar.html" with user=collection.owner show_profile=1 %}
|
||||
</main>
|
||||
{% include "partial/_footer.html" %}
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
$(".markdownx textarea").hide();
|
||||
</script>
|
||||
<script>
|
||||
document.body.addEventListener('htmx:configRequest', (event) => {
|
||||
event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
</html>
|
||||
|
|
|
@ -5,47 +5,56 @@
|
|||
{% load oauth_token %}
|
||||
{% load truncate %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<html lang="en" class="content-page">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ site_name }} - 编辑收藏单 - {{ title }}</title>
|
||||
{% include "common_libs.html" with jquery=0 %}
|
||||
{% include "common_libs.html" with jquery=0 v2=1 %}
|
||||
<script src="https://cdn.staticfile.org/html5sortable/0.13.3/html5sortable.min.js"
|
||||
crossorigin="anonymous"></script>
|
||||
<style type="text/css">
|
||||
#id_collaborative li, #id_visibility li {display: inline-block !important;}
|
||||
.grid__main details {
|
||||
margin: 2rem 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="page-wrapper">
|
||||
{% include "partial/_navbar.html" %}
|
||||
<div id="content-wrapper">
|
||||
<section id="content" class="container">
|
||||
<div class="grid">
|
||||
<div class="single-section-wrapper" id="main">
|
||||
<form class="entity-form markdown-content" method="post" enctype="multipart/form-data">
|
||||
{% include "_header.html" %}
|
||||
<main>
|
||||
<div class="grid__main">
|
||||
<h4>
|
||||
{% if collection %}
|
||||
编辑 <a href="{{ collection.url }}">{{ collection.title }}</a>
|
||||
{% else %}
|
||||
创建收藏单
|
||||
{% endif %}
|
||||
</h4>
|
||||
<hr>
|
||||
<details {% if not collection %}open{% endif %}>
|
||||
<summary>标题和描述</summary>
|
||||
<form class="entity-form markdown-content"
|
||||
method="post"
|
||||
enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form }}
|
||||
<input class="button" type="submit" value="{% trans '提交' %}">
|
||||
<input class="button" type="submit" value="{% trans '保存' %}">
|
||||
</form>
|
||||
{{ form.media }}
|
||||
</div>
|
||||
</details>
|
||||
{% if collection %}
|
||||
<div class="dividing-line"></div>
|
||||
<div class="single-section-wrapper">
|
||||
<div id="collection_items" class="entity-list" hx-get="{% url 'journal:collection_retrieve_items' collection.uuid %}?edit=1" hx-trigger="load"></div>
|
||||
</div>
|
||||
<hr>
|
||||
<details open>
|
||||
<summary>条目</summary>
|
||||
<div id="collection_items"
|
||||
hx-get="{% url 'journal:collection_retrieve_items' collection.uuid %}?edit=1"
|
||||
hx-trigger="load"></div>
|
||||
</details>
|
||||
{% endif %}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
{% include "_sidebar.html" with user=collection.owner show_profile=1 fold_profile=1 %}
|
||||
</main>
|
||||
{% include "partial/_footer.html" %}
|
||||
</div>
|
||||
<script>
|
||||
document.body.addEventListener('htmx:configRequest', (event) => {
|
||||
event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{% load thumb %}
|
||||
{% load i18n %}
|
||||
{% load l10n %}
|
||||
<ul class="entity-list__entities">
|
||||
<div class="item-list sortable">
|
||||
{% for member in collection.ordered_members %}
|
||||
{% with "list_item_"|add:member.item.class_name|add:".html" as template %}
|
||||
{% include template with item=member.item mark=None collection_member=member %}
|
||||
|
@ -9,19 +9,49 @@
|
|||
{% empty %}
|
||||
暂无条目
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% if collection_edit %}
|
||||
<li>
|
||||
<form class="entity-form" hx-target=".entity-list" hx-post="{% url 'journal:collection_append_item' collection.uuid %}" method="POST">
|
||||
<form class="entity-form"
|
||||
hx-target="#collection_items"
|
||||
hx-post="{% url 'journal:collection_append_item' collection.uuid %}"
|
||||
method="post">
|
||||
{% csrf_token %}
|
||||
<input type="url" name="url" placeholder="{{ request.scheme }}://{{ request.get_host }}/item/abcd123" style="min-width:24rem" required>
|
||||
<input type="text" name="comment" placeholder="{% trans '备注' %}" style="min-width:24rem">
|
||||
<input class="button" type="submit" value="{% trans '添加' %}" >
|
||||
<input type="url"
|
||||
name="url"
|
||||
placeholder="{{ request.scheme }}://{{ request.get_host }}/item/abcd123"
|
||||
style="min-width:24rem"
|
||||
required>
|
||||
<input type="text"
|
||||
name="comment"
|
||||
placeholder="{% trans '备注' %}"
|
||||
style="min-width:24rem">
|
||||
<input class="button" type="submit" value="{% trans '添加站内条目到收藏夹' %}">
|
||||
</form>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
{% if msg %}
|
||||
<script type="text/javascript">
|
||||
alert("{{ msg|escapejs }}");
|
||||
<script>
|
||||
$(function () {
|
||||
sortable('.sortable', {
|
||||
forcePlaceholderSize: true,
|
||||
placeholderClass: 'entity-sort--placeholder',
|
||||
hoverClass: 'entity-sort--hover'
|
||||
});
|
||||
});
|
||||
function update_member_order() {
|
||||
var member_ids = [];
|
||||
$('.sortable>.item-card').each(function () {
|
||||
member_ids.push($(this).data('member-id'));
|
||||
});
|
||||
$('#member_ids').val(member_ids.join(','));
|
||||
return true;
|
||||
}
|
||||
</script>
|
||||
<form class="entity-form"
|
||||
hx-target="#collection_items"
|
||||
hx-post="{% url 'journal:collection_update_member_order' collection.uuid %}"
|
||||
onsubmit="return update_member_order()"
|
||||
method="post">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="member_ids" id="member_ids" required>
|
||||
<input type="submit" class="secondary" value="拖拽修改条目顺序后点击这里保存">
|
||||
</form>
|
||||
{% endif %}
|
||||
{% if msg %}<script type="text/javascript">alert("{{ msg|escapejs }}");</script>{% endif %}
|
||||
|
|
|
@ -8,33 +8,56 @@
|
|||
{% load truncate %}
|
||||
{% load highlight %}
|
||||
{% load thumb %}
|
||||
|
||||
<div id="modal" _="on closeModal add .closing then wait for animationend then remove me">
|
||||
<div id="modal"
|
||||
_="on closeModal add .closing then wait for animationend then remove me">
|
||||
<div class="modal-underlay" _="on click trigger closeModal"></div>
|
||||
<div class="modal-content">
|
||||
<div class="add-to-list-modal__head">
|
||||
<span class="add-to-list-modal__title">{% trans '分享收藏单' %} - {{ collection.title }}</span>
|
||||
<span class="add-to-list-modal__close-button modal-close" _="on click trigger closeModal">
|
||||
<span class="add-to-list-modal__close-button modal-close"
|
||||
_="on click trigger closeModal">
|
||||
<i class="fa-solid fa-xmark"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="add-to-list-modal__body">
|
||||
<form action="{% url 'journal:collection_share' collection.uuid %}" method="post">
|
||||
<form action="{% url 'journal:collection_share' collection.uuid %}"
|
||||
method="post">
|
||||
{% csrf_token %}
|
||||
<div>
|
||||
<label for="id_visibility_0">分享可见性(不同于收藏单本身的权限):</label>
|
||||
<ul id="id_visibility">
|
||||
<li><label for="id_visibility_0"><input type="radio" name="visibility" value="0" required="" id="id_visibility_0" {% if collection.visibility == 0 %}checked{% endif %}>
|
||||
公开</label>
|
||||
|
||||
<li>
|
||||
<label for="id_visibility_0">
|
||||
<input type="radio"
|
||||
name="visibility"
|
||||
value="0"
|
||||
required=""
|
||||
id="id_visibility_0"
|
||||
{% if collection.visibility == 0 %}checked{% endif %}>
|
||||
公开
|
||||
</label>
|
||||
</li>
|
||||
<li><label for="id_visibility_1"><input type="radio" name="visibility" value="1" required="" id="id_visibility_1" {% if collection.visibility == 1 %}checked{% endif %}>
|
||||
仅关注者</label>
|
||||
|
||||
<li>
|
||||
<label for="id_visibility_1">
|
||||
<input type="radio"
|
||||
name="visibility"
|
||||
value="1"
|
||||
required=""
|
||||
id="id_visibility_1"
|
||||
{% if collection.visibility == 1 %}checked{% endif %}>
|
||||
仅关注者
|
||||
</label>
|
||||
</li>
|
||||
<li><label for="id_visibility_2"><input type="radio" name="visibility" value="2" required="" id="id_visibility_2" {% if collection.visibility == 2 %}checked{% endif %}>
|
||||
仅自己</label>
|
||||
|
||||
<li>
|
||||
<label for="id_visibility_2">
|
||||
<input type="radio"
|
||||
name="visibility"
|
||||
value="2"
|
||||
required=""
|
||||
id="id_visibility_2"
|
||||
{% if collection.visibility == 2 %}checked{% endif %}>
|
||||
仅自己
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue