add progress to note
This commit is contained in:
parent
3eafcd3ec8
commit
7157f3b0b0
22 changed files with 779 additions and 192 deletions
|
@ -90,18 +90,25 @@
|
||||||
{% include "action_open_post.html" with post=note.latest_post %}
|
{% include "action_open_post.html" with post=note.latest_post %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</span>
|
</span>
|
||||||
<h6>{{ note.title|default:'' }}</h6>
|
{% if note.title %}<h6>{{ note.title|default:'' }}</h6>{% endif %}
|
||||||
<p>{{ note.content|linebreaks }}</p>
|
<p>
|
||||||
<div>
|
{% if note.progress_value %}<span class="tag-list"><span><a>{{ note.progress_display }}</a></span></span>{% endif %}
|
||||||
{% for attachment in note.attachments %}
|
{{ note.content|linebreaksbr }}
|
||||||
{% if attachment.type == 'image' %}
|
<div class="attachments">
|
||||||
<img src="{{ attachment.url }}"
|
{% for attachment in note.attachments %}
|
||||||
alt="image attachment"
|
{% if attachment.type == 'image' %}
|
||||||
style="max-height:6em;
|
<a href="#img_{{ note.uuid }}_{{ loop.index }}">
|
||||||
max-width:50%">
|
<img src="{{ attachment.preview_url }}"
|
||||||
{% endif %}
|
alt="image attachment"
|
||||||
{% endfor %}
|
class="preview">
|
||||||
</div>
|
</a>
|
||||||
|
<a href="#" class="lightbox" id="img_{{ note.uuid }}_{{ loop.index }}">
|
||||||
|
<span style="background-image: url('{{ attachment.url }}')"></span>
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</p>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
|
|
|
@ -3,11 +3,23 @@ import json
|
||||||
import django.contrib.postgres.forms as postgres
|
import django.contrib.postgres.forms as postgres
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
from django.forms import ModelForm
|
||||||
from django.utils import formats
|
from django.utils import formats
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from markdownx.fields import MarkdownxFormField
|
from markdownx.fields import MarkdownxFormField
|
||||||
|
|
||||||
|
|
||||||
|
class NeoModelForm(ModelForm):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
# if "uuid" in self.fields:
|
||||||
|
# if self.instance and self.instance.pk:
|
||||||
|
# self.fields["uuid"].initial = self.instance.uuid
|
||||||
|
for visible in self.visible_fields():
|
||||||
|
w = visible.field.widget
|
||||||
|
w.attrs["class"] = "widget " + w.__class__.__name__.lower()
|
||||||
|
|
||||||
|
|
||||||
class PreviewImageInput(forms.FileInput):
|
class PreviewImageInput(forms.FileInput):
|
||||||
template_name = "widgets/image.html"
|
template_name = "widgets/image.html"
|
||||||
|
|
||||||
|
|
|
@ -86,6 +86,16 @@ dialog {
|
||||||
|
|
||||||
article {
|
article {
|
||||||
padding-bottom: 1em;
|
padding-bottom: 1em;
|
||||||
|
form {
|
||||||
|
overflow: hidden;
|
||||||
|
input[type="submit"] {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
div.widget.radioselect {
|
||||||
|
display: flex;
|
||||||
|
grid-column-gap: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="date"] {
|
input[type="date"] {
|
||||||
|
|
26
common/static/scss/_lightbox.scss
Normal file
26
common/static/scss/_lightbox.scss
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
.lightbox {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 999;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
padding: 1em;
|
||||||
|
background: rgba(0, 0, 0, 0.8);
|
||||||
|
-webkit-backdrop-filter: var(--pico-modal-overlay-backdrop-filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
.lightbox:target {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lightbox span {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: contain;
|
||||||
|
}
|
|
@ -27,3 +27,10 @@ section.replies {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.attachements {
|
||||||
|
img.preview {
|
||||||
|
max-height: 6em;
|
||||||
|
max-width: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -20,3 +20,4 @@
|
||||||
@import '_form.scss';
|
@import '_form.scss';
|
||||||
@import '_post.scss';
|
@import '_post.scss';
|
||||||
@import '_l10n.scss';
|
@import '_l10n.scss';
|
||||||
|
@import '_lightbox.scss';
|
||||||
|
|
|
@ -159,7 +159,17 @@ class Migration(migrations.Migration):
|
||||||
to="journal.piece",
|
to="journal.piece",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
(
|
||||||
|
"visibility",
|
||||||
|
models.PositiveSmallIntegerField(
|
||||||
|
choices=[
|
||||||
|
(0, "Public"),
|
||||||
|
(1, "Followers Only"),
|
||||||
|
(2, "Mentioned Only"),
|
||||||
|
],
|
||||||
|
default=0,
|
||||||
|
),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"created_time",
|
"created_time",
|
||||||
models.DateTimeField(default=django.utils.timezone.now),
|
models.DateTimeField(default=django.utils.timezone.now),
|
||||||
|
@ -205,7 +215,17 @@ class Migration(migrations.Migration):
|
||||||
to="journal.piece",
|
to="journal.piece",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
(
|
||||||
|
"visibility",
|
||||||
|
models.PositiveSmallIntegerField(
|
||||||
|
choices=[
|
||||||
|
(0, "Public"),
|
||||||
|
(1, "Followers Only"),
|
||||||
|
(2, "Mentioned Only"),
|
||||||
|
],
|
||||||
|
default=0,
|
||||||
|
),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"created_time",
|
"created_time",
|
||||||
models.DateTimeField(default=django.utils.timezone.now),
|
models.DateTimeField(default=django.utils.timezone.now),
|
||||||
|
@ -233,7 +253,17 @@ class Migration(migrations.Migration):
|
||||||
to="journal.piece",
|
to="journal.piece",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
(
|
||||||
|
"visibility",
|
||||||
|
models.PositiveSmallIntegerField(
|
||||||
|
choices=[
|
||||||
|
(0, "Public"),
|
||||||
|
(1, "Followers Only"),
|
||||||
|
(2, "Mentioned Only"),
|
||||||
|
],
|
||||||
|
default=0,
|
||||||
|
),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"created_time",
|
"created_time",
|
||||||
models.DateTimeField(default=django.utils.timezone.now),
|
models.DateTimeField(default=django.utils.timezone.now),
|
||||||
|
@ -265,7 +295,17 @@ class Migration(migrations.Migration):
|
||||||
to="journal.piece",
|
to="journal.piece",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
(
|
||||||
|
"visibility",
|
||||||
|
models.PositiveSmallIntegerField(
|
||||||
|
choices=[
|
||||||
|
(0, "Public"),
|
||||||
|
(1, "Followers Only"),
|
||||||
|
(2, "Mentioned Only"),
|
||||||
|
],
|
||||||
|
default=0,
|
||||||
|
),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"created_time",
|
"created_time",
|
||||||
models.DateTimeField(default=django.utils.timezone.now),
|
models.DateTimeField(default=django.utils.timezone.now),
|
||||||
|
@ -316,7 +356,17 @@ class Migration(migrations.Migration):
|
||||||
to="journal.piece",
|
to="journal.piece",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
(
|
||||||
|
"visibility",
|
||||||
|
models.PositiveSmallIntegerField(
|
||||||
|
choices=[
|
||||||
|
(0, "Public"),
|
||||||
|
(1, "Followers Only"),
|
||||||
|
(2, "Mentioned Only"),
|
||||||
|
],
|
||||||
|
default=0,
|
||||||
|
),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"created_time",
|
"created_time",
|
||||||
models.DateTimeField(default=django.utils.timezone.now),
|
models.DateTimeField(default=django.utils.timezone.now),
|
||||||
|
@ -343,7 +393,17 @@ class Migration(migrations.Migration):
|
||||||
to="journal.piece",
|
to="journal.piece",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
(
|
||||||
|
"visibility",
|
||||||
|
models.PositiveSmallIntegerField(
|
||||||
|
choices=[
|
||||||
|
(0, "Public"),
|
||||||
|
(1, "Followers Only"),
|
||||||
|
(2, "Mentioned Only"),
|
||||||
|
],
|
||||||
|
default=0,
|
||||||
|
),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"created_time",
|
"created_time",
|
||||||
models.DateTimeField(default=django.utils.timezone.now),
|
models.DateTimeField(default=django.utils.timezone.now),
|
||||||
|
@ -382,7 +442,17 @@ class Migration(migrations.Migration):
|
||||||
to="journal.piece",
|
to="journal.piece",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
(
|
||||||
|
"visibility",
|
||||||
|
models.PositiveSmallIntegerField(
|
||||||
|
choices=[
|
||||||
|
(0, "Public"),
|
||||||
|
(1, "Followers Only"),
|
||||||
|
(2, "Mentioned Only"),
|
||||||
|
],
|
||||||
|
default=0,
|
||||||
|
),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"created_time",
|
"created_time",
|
||||||
models.DateTimeField(default=django.utils.timezone.now),
|
models.DateTimeField(default=django.utils.timezone.now),
|
||||||
|
@ -415,7 +485,17 @@ class Migration(migrations.Migration):
|
||||||
to="journal.piece",
|
to="journal.piece",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
(
|
||||||
|
"visibility",
|
||||||
|
models.PositiveSmallIntegerField(
|
||||||
|
choices=[
|
||||||
|
(0, "Public"),
|
||||||
|
(1, "Followers Only"),
|
||||||
|
(2, "Mentioned Only"),
|
||||||
|
],
|
||||||
|
default=0,
|
||||||
|
),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"created_time",
|
"created_time",
|
||||||
models.DateTimeField(default=django.utils.timezone.now),
|
models.DateTimeField(default=django.utils.timezone.now),
|
||||||
|
@ -451,7 +531,17 @@ class Migration(migrations.Migration):
|
||||||
to="journal.piece",
|
to="journal.piece",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
(
|
||||||
|
"visibility",
|
||||||
|
models.PositiveSmallIntegerField(
|
||||||
|
choices=[
|
||||||
|
(0, "Public"),
|
||||||
|
(1, "Followers Only"),
|
||||||
|
(2, "Mentioned Only"),
|
||||||
|
],
|
||||||
|
default=0,
|
||||||
|
),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"created_time",
|
"created_time",
|
||||||
models.DateTimeField(default=django.utils.timezone.now),
|
models.DateTimeField(default=django.utils.timezone.now),
|
||||||
|
@ -596,7 +686,17 @@ class Migration(migrations.Migration):
|
||||||
to="journal.piece",
|
to="journal.piece",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
(
|
||||||
|
"visibility",
|
||||||
|
models.PositiveSmallIntegerField(
|
||||||
|
choices=[
|
||||||
|
(0, "Public"),
|
||||||
|
(1, "Followers Only"),
|
||||||
|
(2, "Mentioned Only"),
|
||||||
|
],
|
||||||
|
default=0,
|
||||||
|
),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"created_time",
|
"created_time",
|
||||||
models.DateTimeField(default=django.utils.timezone.now),
|
models.DateTimeField(default=django.utils.timezone.now),
|
||||||
|
@ -656,7 +756,17 @@ class Migration(migrations.Migration):
|
||||||
to="journal.piece",
|
to="journal.piece",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
(
|
||||||
|
"visibility",
|
||||||
|
models.PositiveSmallIntegerField(
|
||||||
|
choices=[
|
||||||
|
(0, "Public"),
|
||||||
|
(1, "Followers Only"),
|
||||||
|
(2, "Mentioned Only"),
|
||||||
|
],
|
||||||
|
default=0,
|
||||||
|
),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"created_time",
|
"created_time",
|
||||||
models.DateTimeField(default=django.utils.timezone.now),
|
models.DateTimeField(default=django.utils.timezone.now),
|
||||||
|
|
|
@ -27,7 +27,17 @@ class Migration(migrations.Migration):
|
||||||
to="journal.piece",
|
to="journal.piece",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
("visibility", models.PositiveSmallIntegerField(default=0)),
|
(
|
||||||
|
"visibility",
|
||||||
|
models.PositiveSmallIntegerField(
|
||||||
|
choices=[
|
||||||
|
(0, "Public"),
|
||||||
|
(1, "Followers Only"),
|
||||||
|
(2, "Mentioned Only"),
|
||||||
|
],
|
||||||
|
default=0,
|
||||||
|
),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"created_time",
|
"created_time",
|
||||||
models.DateTimeField(default=django.utils.timezone.now),
|
models.DateTimeField(default=django.utils.timezone.now),
|
||||||
|
|
44
journal/migrations/0003_note_progress.py
Normal file
44
journal/migrations/0003_note_progress.py
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
# Generated by Django 4.2.13 on 2024-06-14 22:05
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("journal", "0002_note"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="note",
|
||||||
|
name="progress_type",
|
||||||
|
field=models.CharField(
|
||||||
|
blank=True,
|
||||||
|
choices=[
|
||||||
|
("page", "Page"),
|
||||||
|
("chapter", "Chapter"),
|
||||||
|
("part", "Part"),
|
||||||
|
("episode", "Episode"),
|
||||||
|
("track", "Track"),
|
||||||
|
("cycle", "Cycle"),
|
||||||
|
("timestamp", "Timestamp"),
|
||||||
|
("percentage", "Percentage"),
|
||||||
|
],
|
||||||
|
default=None,
|
||||||
|
max_length=50,
|
||||||
|
null=True,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="note",
|
||||||
|
name="progress_value",
|
||||||
|
field=models.CharField(blank=True, default=None, max_length=500, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name="note",
|
||||||
|
index=models.Index(
|
||||||
|
fields=["owner", "item", "created_time"],
|
||||||
|
name="journal_not_owner_i_7f9460_idx",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -434,8 +434,8 @@ class PieceInteraction(models.Model):
|
||||||
class Content(Piece):
|
class Content(Piece):
|
||||||
owner = models.ForeignKey(APIdentity, on_delete=models.PROTECT)
|
owner = models.ForeignKey(APIdentity, on_delete=models.PROTECT)
|
||||||
visibility = models.PositiveSmallIntegerField(
|
visibility = models.PositiveSmallIntegerField(
|
||||||
default=0
|
choices=VisibilityType.choices, default=0, null=False
|
||||||
) # 0: Public / 1: Follower only / 2: Self only # type:ignore
|
) # type:ignore
|
||||||
created_time = models.DateTimeField(default=timezone.now)
|
created_time = models.DateTimeField(default=timezone.now)
|
||||||
edited_time = models.DateTimeField(auto_now=True)
|
edited_time = models.DateTimeField(auto_now=True)
|
||||||
metadata = models.JSONField(default=dict)
|
metadata = models.JSONField(default=dict)
|
||||||
|
|
|
@ -8,7 +8,7 @@ from django.utils import timezone
|
||||||
from catalog.models import Item, ItemCategory
|
from catalog.models import Item, ItemCategory
|
||||||
from users.models import APIdentity
|
from users.models import APIdentity
|
||||||
|
|
||||||
from .common import Piece
|
from .common import Piece, VisibilityType
|
||||||
|
|
||||||
list_add = django.dispatch.Signal()
|
list_add = django.dispatch.Signal()
|
||||||
list_remove = django.dispatch.Signal()
|
list_remove = django.dispatch.Signal()
|
||||||
|
@ -25,8 +25,8 @@ class List(Piece):
|
||||||
items: "models.ManyToManyField[Item, List]"
|
items: "models.ManyToManyField[Item, List]"
|
||||||
owner = models.ForeignKey(APIdentity, on_delete=models.PROTECT)
|
owner = models.ForeignKey(APIdentity, on_delete=models.PROTECT)
|
||||||
visibility = models.PositiveSmallIntegerField(
|
visibility = models.PositiveSmallIntegerField(
|
||||||
default=0
|
choices=VisibilityType.choices, default=0, null=False
|
||||||
) # 0: Public / 1: Follower only / 2: Self only # type:ignore
|
) # type:ignore
|
||||||
created_time = models.DateTimeField(default=timezone.now)
|
created_time = models.DateTimeField(default=timezone.now)
|
||||||
edited_time = models.DateTimeField(auto_now=True)
|
edited_time = models.DateTimeField(auto_now=True)
|
||||||
metadata = models.JSONField(default=dict)
|
metadata = models.JSONField(default=dict)
|
||||||
|
@ -151,8 +151,8 @@ class ListMember(Piece):
|
||||||
parent: models.ForeignKey["ListMember", "List"]
|
parent: models.ForeignKey["ListMember", "List"]
|
||||||
owner = models.ForeignKey(APIdentity, on_delete=models.PROTECT)
|
owner = models.ForeignKey(APIdentity, on_delete=models.PROTECT)
|
||||||
visibility = models.PositiveSmallIntegerField(
|
visibility = models.PositiveSmallIntegerField(
|
||||||
default=0
|
choices=VisibilityType.choices, default=0, null=False
|
||||||
) # 0: Public / 1: Follower only / 2: Self only # type:ignore[reportAssignmentType]
|
) # type:ignore
|
||||||
created_time = models.DateTimeField(default=timezone.now)
|
created_time = models.DateTimeField(default=timezone.now)
|
||||||
edited_time = models.DateTimeField(auto_now=True)
|
edited_time = models.DateTimeField(auto_now=True)
|
||||||
metadata = models.JSONField(default=dict)
|
metadata = models.JSONField(default=dict)
|
||||||
|
|
|
@ -5,14 +5,14 @@ from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from users.models import APIdentity
|
from users.models import APIdentity
|
||||||
|
|
||||||
from .common import Piece
|
from .common import Piece, VisibilityType
|
||||||
|
|
||||||
|
|
||||||
class Like(Piece): # TODO remove
|
class Like(Piece): # TODO remove
|
||||||
owner = models.ForeignKey(APIdentity, on_delete=models.PROTECT)
|
owner = models.ForeignKey(APIdentity, on_delete=models.PROTECT)
|
||||||
visibility = models.PositiveSmallIntegerField(
|
visibility = models.PositiveSmallIntegerField(
|
||||||
default=0
|
choices=VisibilityType.choices, default=0, null=False
|
||||||
) # 0: Public / 1: Follower only / 2: Self only # type: ignore
|
) # type:ignore
|
||||||
created_time = models.DateTimeField(default=timezone.now)
|
created_time = models.DateTimeField(default=timezone.now)
|
||||||
edited_time = models.DateTimeField(auto_now=True)
|
edited_time = models.DateTimeField(auto_now=True)
|
||||||
target = models.ForeignKey(Piece, on_delete=models.CASCADE, related_name="likes")
|
target = models.ForeignKey(Piece, on_delete=models.CASCADE, related_name="likes")
|
||||||
|
|
|
@ -108,7 +108,9 @@ class Mark:
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def notes(self):
|
def notes(self):
|
||||||
return Note.objects.filter(owner=self.owner, item=self.item)
|
return Note.objects.filter(owner=self.owner, item=self.item).order_by(
|
||||||
|
"-created_time"
|
||||||
|
)
|
||||||
# post_ids = PiecePost.objects.filter(
|
# post_ids = PiecePost.objects.filter(
|
||||||
# piece__note__owner_id=self.owner.pk, piece__note__item_id=self.item.pk
|
# piece__note__owner_id=self.owner.pk, piece__note__item_id=self.item.pk
|
||||||
# ).values_list("post_id", flat=True)
|
# ).values_list("post_id", flat=True)
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
|
import re
|
||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
from typing import override
|
from typing import override
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
|
from catalog.models import Item
|
||||||
from mastodon.api import delete_toot_later
|
from mastodon.api import delete_toot_later
|
||||||
from takahe.utils import Takahe
|
from takahe.utils import Takahe
|
||||||
|
|
||||||
|
@ -11,17 +14,74 @@ from .common import Content
|
||||||
from .renderers import render_text
|
from .renderers import render_text
|
||||||
from .shelf import ShelfMember
|
from .shelf import ShelfMember
|
||||||
|
|
||||||
|
_progress = re.compile(
|
||||||
|
r"^\s*(?P<prefix>(p|pg|page|ch|chapter|pt|part|e|ep|episode|trk|track|cycle))?(\s|\.|#)*(?P<value>(\d[\d\:\.\-]*\d|\d))\s*(?P<postfix>(%))?\s*(\s|\n|\.|:)",
|
||||||
|
re.IGNORECASE,
|
||||||
|
)
|
||||||
|
|
||||||
|
_number = re.compile(r"^[\s\d\:\.]+$")
|
||||||
|
|
||||||
|
|
||||||
class Note(Content):
|
class Note(Content):
|
||||||
|
class ProgressType(models.TextChoices):
|
||||||
|
PAGE = "page", _("Page")
|
||||||
|
CHAPTER = "chapter", _("Chapter")
|
||||||
|
# SECTION = "section", _("Section")
|
||||||
|
# VOLUME = "volume", _("Volume")
|
||||||
|
PART = "part", _("Part")
|
||||||
|
EPISODE = "episode", _("Episode")
|
||||||
|
TRACK = "track", _("Track")
|
||||||
|
CYCLE = "cycle", _("Cycle")
|
||||||
|
TIMESTAMP = "timestamp", _("Timestamp")
|
||||||
|
PERCENTAGE = "percentage", _("Percentage")
|
||||||
|
|
||||||
title = models.TextField(blank=True, null=True, default=None)
|
title = models.TextField(blank=True, null=True, default=None)
|
||||||
content = models.TextField(blank=False, null=False)
|
content = models.TextField(blank=False, null=False)
|
||||||
sensitive = models.BooleanField(default=False, null=False)
|
sensitive = models.BooleanField(default=False, null=False)
|
||||||
attachments = models.JSONField(default=list)
|
attachments = models.JSONField(default=list)
|
||||||
|
progress_type = models.CharField(
|
||||||
|
max_length=50,
|
||||||
|
choices=ProgressType.choices,
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
default=None,
|
||||||
|
)
|
||||||
|
progress_value = models.CharField(
|
||||||
|
max_length=500, blank=True, null=True, default=None
|
||||||
|
)
|
||||||
|
_progress_display_template = {
|
||||||
|
ProgressType.PAGE: _("Page {value}"),
|
||||||
|
ProgressType.CHAPTER: _("Chapter {value}"),
|
||||||
|
# ProgressType.SECTION: _("Section {value}"),
|
||||||
|
# ProgressType.VOLUME: _("Volume {value}"),
|
||||||
|
ProgressType.PART: _("Part {value}"),
|
||||||
|
ProgressType.EPISODE: _("Episode {value}"),
|
||||||
|
ProgressType.TRACK: _("Track {value}"),
|
||||||
|
ProgressType.CYCLE: _("Cycle {value}"),
|
||||||
|
ProgressType.PERCENTAGE: "{value}%",
|
||||||
|
ProgressType.TIMESTAMP: "{value}",
|
||||||
|
}
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
indexes = [models.Index(fields=["owner", "item", "created_time"])]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def html(self):
|
def html(self):
|
||||||
return render_text(self.content)
|
return render_text(self.content)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def progress_display(self) -> str:
|
||||||
|
if not self.progress_value:
|
||||||
|
return ""
|
||||||
|
if not self.progress_type:
|
||||||
|
return str(self.progress_value)
|
||||||
|
tpl = Note._progress_display_template.get(self.progress_type, None)
|
||||||
|
if not tpl:
|
||||||
|
return str(self.progress_value)
|
||||||
|
if _number.match(self.progress_value):
|
||||||
|
return tpl.format(value=self.progress_value)
|
||||||
|
return self.progress_type.display + ": " + self.progress_value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ap_object(self):
|
def ap_object(self):
|
||||||
d = {
|
d = {
|
||||||
|
@ -36,6 +96,11 @@ class Note(Content):
|
||||||
"withRegardTo": self.item.absolute_url,
|
"withRegardTo": self.item.absolute_url,
|
||||||
"href": self.absolute_url,
|
"href": self.absolute_url,
|
||||||
}
|
}
|
||||||
|
if self.progress_value:
|
||||||
|
d["progress"] = {
|
||||||
|
"type": self.progress_type,
|
||||||
|
"value": self.progress_value,
|
||||||
|
}
|
||||||
return d
|
return d
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -47,6 +112,17 @@ class Note(Content):
|
||||||
"sensitive": obj.get("sensitive", post.sensitive),
|
"sensitive": obj.get("sensitive", post.sensitive),
|
||||||
"attachments": [],
|
"attachments": [],
|
||||||
}
|
}
|
||||||
|
progress = obj.get("progress", {})
|
||||||
|
if progress.get("type"):
|
||||||
|
params["progress_type"] = progress.get("type")
|
||||||
|
if progress.get("value"):
|
||||||
|
params["progress_value"] = progress.get("value")
|
||||||
|
if post.local:
|
||||||
|
progress_type, progress_value = cls.extract_progress(params["content"])
|
||||||
|
print(progress_type, progress_value)
|
||||||
|
if progress_value:
|
||||||
|
params["progress_type"] = progress_type
|
||||||
|
params["progress_value"] = progress_value
|
||||||
if post:
|
if post:
|
||||||
for atta in post.attachments.all():
|
for atta in post.attachments.all():
|
||||||
params["attachments"].append(
|
params["attachments"].append(
|
||||||
|
@ -103,3 +179,79 @@ class Note(Content):
|
||||||
),
|
),
|
||||||
# not passing "attachments" so it won't change
|
# not passing "attachments" so it won't change
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def extract_progress(cls, content):
|
||||||
|
m = _progress.match(content)
|
||||||
|
if m and m["value"]:
|
||||||
|
typ_ = "percentage" if m["postfix"] == "%" else m["prefix"]
|
||||||
|
match typ_:
|
||||||
|
case "p" | "pg" | "page":
|
||||||
|
typ = Note.ProgressType.PAGE
|
||||||
|
case "ch" | "chapter":
|
||||||
|
typ = Note.ProgressType.CHAPTER
|
||||||
|
# case "vol" | "volume":
|
||||||
|
# typ = ProgressType.VOLUME
|
||||||
|
# case "section":
|
||||||
|
# typ = ProgressType.SECTION
|
||||||
|
case "pt" | "part":
|
||||||
|
typ = Note.ProgressType.PART
|
||||||
|
case "e" | "ep" | "episode":
|
||||||
|
typ = Note.ProgressType.EPISODE
|
||||||
|
case "trk" | "track":
|
||||||
|
typ = Note.ProgressType.TRACK
|
||||||
|
case "cycle":
|
||||||
|
typ = Note.ProgressType.CYCLE
|
||||||
|
case "percentage":
|
||||||
|
typ = Note.ProgressType.PERCENTAGE
|
||||||
|
case _:
|
||||||
|
typ = "timestamp" if ":" in m["value"] else None
|
||||||
|
return typ, m["value"]
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_progress_types_by_item(cls, item: Item):
|
||||||
|
match item.__class__.__name__:
|
||||||
|
case "Edition":
|
||||||
|
v = [
|
||||||
|
Note.ProgressType.PAGE,
|
||||||
|
Note.ProgressType.CHAPTER,
|
||||||
|
Note.ProgressType.PERCENTAGE,
|
||||||
|
]
|
||||||
|
case "TVShow" | "TVSeason":
|
||||||
|
v = [
|
||||||
|
Note.ProgressType.PART,
|
||||||
|
Note.ProgressType.EPISODE,
|
||||||
|
Note.ProgressType.PERCENTAGE,
|
||||||
|
]
|
||||||
|
case "Movie":
|
||||||
|
v = [
|
||||||
|
Note.ProgressType.PART,
|
||||||
|
Note.ProgressType.TIMESTAMP,
|
||||||
|
Note.ProgressType.PERCENTAGE,
|
||||||
|
]
|
||||||
|
case "Podcast":
|
||||||
|
v = [
|
||||||
|
Note.ProgressType.EPISODE,
|
||||||
|
]
|
||||||
|
case "TVEpisode" | "PodcastEpisode":
|
||||||
|
v = []
|
||||||
|
case "Album":
|
||||||
|
v = [
|
||||||
|
Note.ProgressType.TRACK,
|
||||||
|
Note.ProgressType.TIMESTAMP,
|
||||||
|
Note.ProgressType.PERCENTAGE,
|
||||||
|
]
|
||||||
|
case "Game":
|
||||||
|
v = [
|
||||||
|
Note.ProgressType.CYCLE,
|
||||||
|
]
|
||||||
|
case "Performance" | "PerformanceProduction":
|
||||||
|
v = [
|
||||||
|
Note.ProgressType.PART,
|
||||||
|
Note.ProgressType.TIMESTAMP,
|
||||||
|
Note.ProgressType.PERCENTAGE,
|
||||||
|
]
|
||||||
|
case _:
|
||||||
|
v = []
|
||||||
|
return v
|
||||||
|
|
|
@ -16,50 +16,23 @@
|
||||||
<strong>{% trans 'Note' %} - {{ item.display_title }}</strong>
|
<strong>{% trans 'Note' %} - {{ item.display_title }}</strong>
|
||||||
</header>
|
</header>
|
||||||
<div>
|
<div>
|
||||||
<form action="{% url 'journal:note' item.uuid %}" method="post">
|
<form action="{% url 'journal:note' item.uuid %}"
|
||||||
|
method="post"
|
||||||
|
onsubmit="return !!$('#{{ form.content.id_for_label }}').val() || confirm('{% trans "Note with empty content will be deleted, sure to continue?" %}');;">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input type="hidden" name="uuid" value="{{ note.uuid|default:'' }}">
|
{{ form.uuid }}
|
||||||
<textarea name="content" cols="40" rows="10" placeholder="" id="id_content">{{ note.content|default:'' }}</textarea>
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
|
<div>{{ form.progress_type }}</div>
|
||||||
|
<div>{{ form.progress_value }}</div>
|
||||||
|
</div>
|
||||||
|
{{ form.content }}
|
||||||
|
{{ form.title }}
|
||||||
|
<div class="grid">
|
||||||
|
<div>{{ form.visibility }}</div>
|
||||||
<div>
|
<div>
|
||||||
<fieldset>
|
<label for="{{ form.share_to_mastodon.id_for_label }}">
|
||||||
<input type="radio"
|
{{ form.share_to_mastodon }} {{ form.share_to_mastodon.label }}
|
||||||
name="visibility"
|
</label>
|
||||||
value="0"
|
|
||||||
required=""
|
|
||||||
id="id_visibility_0"
|
|
||||||
{% if note.visibility == 0 or not note %}checked{% endif %}>
|
|
||||||
<label for="id_visibility_0">{% trans "Public" %}</label>
|
|
||||||
<input type="radio"
|
|
||||||
name="visibility"
|
|
||||||
value="1"
|
|
||||||
required=""
|
|
||||||
id="id_visibility_1"
|
|
||||||
{% if note.visibility == 1 %}checked{% endif %}>
|
|
||||||
<label for="id_visibility_1">{% trans "Followers Only" %}</label>
|
|
||||||
<input type="radio"
|
|
||||||
name="visibility"
|
|
||||||
value="2"
|
|
||||||
required=""
|
|
||||||
id="id_visibility_2"
|
|
||||||
{% if note.visibility == 2 %}checked{% endif %}>
|
|
||||||
<label for="id_visibility_2">{% trans "Mentioned Only" %}</label>
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<fieldset>
|
|
||||||
{% if request.user.mastodon_acct %}
|
|
||||||
<label for="id_share_to_mastodon">
|
|
||||||
<input role="switch"
|
|
||||||
type="checkbox"
|
|
||||||
name="share_to_mastodon"
|
|
||||||
id="id_share_to_mastodon"
|
|
||||||
value="1"
|
|
||||||
{% if request.user.preference.mastodon_default_repost %}checked{% endif %}>
|
|
||||||
{% trans "Repost to timeline" %}
|
|
||||||
</label>
|
|
||||||
{% endif %}
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -25,13 +25,17 @@
|
||||||
</span>
|
</span>
|
||||||
<div>{{ post.summary|default:'' }}</div>
|
<div>{{ post.summary|default:'' }}</div>
|
||||||
<div {% if post.summary or post.sensitive %}class="spoiler" _="on click toggle .revealed on me"{% endif %}>
|
<div {% if post.summary or post.sensitive %}class="spoiler" _="on click toggle .revealed on me"{% endif %}>
|
||||||
<div>
|
<div class="attachments">
|
||||||
{% for attachment in post.attachments.all %}
|
{% for attachment in post.attachments.all %}
|
||||||
{% if attachment.is_image %}
|
{% if attachment.is_image %}
|
||||||
<img src="{{ attachment.full_url.relative }}"
|
<a href="#img_{{ post.pk }}_{{ loop.index }}">
|
||||||
alt="attachment.file_display_name"
|
<img src="{{ attachment.thumbnail_url.relative }}"
|
||||||
style="max-height:6em;
|
alt="image attachment"
|
||||||
max-width:50%">
|
class="preview">
|
||||||
|
</a>
|
||||||
|
<a href="#" class="lightbox" id="img_{{ post.pk }}_{{ loop.index }}">
|
||||||
|
<span style="background-image: url('{{ attachment.full_url.relative }}')"></span>
|
||||||
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -21,8 +21,8 @@ urlpatterns = [
|
||||||
path("wish/<str:item_uuid>", wish, name="wish"),
|
path("wish/<str:item_uuid>", wish, name="wish"),
|
||||||
path("mark/<str:item_uuid>", mark, name="mark"),
|
path("mark/<str:item_uuid>", mark, name="mark"),
|
||||||
path("comment/<str:item_uuid>", comment, name="comment"),
|
path("comment/<str:item_uuid>", comment, name="comment"),
|
||||||
path("note/<str:item_uuid>", note, name="note"),
|
path("item/<str:item_uuid>/note", note_edit, name="note"),
|
||||||
path("note/<str:item_uuid>/<str:note_uuid>", note, name="note"),
|
path("item/<str:item_uuid>/note/<str:note_uuid>", note_edit, name="note"),
|
||||||
path("piece/<str:piece_uuid>/replies", piece_replies, name="piece_replies"),
|
path("piece/<str:piece_uuid>/replies", piece_replies, name="piece_replies"),
|
||||||
path("post/<int:post_id>/replies", post_replies, name="post_replies"),
|
path("post/<int:post_id>/replies", post_replies, name="post_replies"),
|
||||||
path("post/<int:post_id>/reply", post_reply, name="post_reply"),
|
path("post/<int:post_id>/reply", post_reply, name="post_reply"),
|
||||||
|
|
|
@ -16,7 +16,8 @@ from .collection import (
|
||||||
user_liked_collection_list,
|
user_liked_collection_list,
|
||||||
)
|
)
|
||||||
from .common import piece_delete
|
from .common import piece_delete
|
||||||
from .mark import comment, mark, mark_log, note, user_mark_list, wish
|
from .mark import comment, mark, mark_log, user_mark_list, wish
|
||||||
|
from .note import note_edit
|
||||||
from .post import (
|
from .post import (
|
||||||
piece_replies,
|
piece_replies,
|
||||||
post_boost,
|
post_boost,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
from django import forms
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.core.exceptions import BadRequest, ObjectDoesNotExist, PermissionDenied
|
from django.core.exceptions import BadRequest, ObjectDoesNotExist, PermissionDenied
|
||||||
|
@ -13,10 +14,8 @@ from loguru import logger
|
||||||
|
|
||||||
from catalog.models import *
|
from catalog.models import *
|
||||||
from common.utils import AuthedHttpRequest, get_uuid_or_404
|
from common.utils import AuthedHttpRequest, get_uuid_or_404
|
||||||
from mastodon.api import boost_toot_later
|
|
||||||
from takahe.utils import Takahe
|
|
||||||
|
|
||||||
from ..models import Comment, Mark, Note, ShelfManager, ShelfType, TagManager
|
from ..models import Comment, Mark, ShelfManager, ShelfType, TagManager
|
||||||
from .common import render_list, render_relogin, target_identity_required
|
from .common import render_list, render_relogin, target_identity_required
|
||||||
|
|
||||||
PAGE_SIZE = 10
|
PAGE_SIZE = 10
|
||||||
|
@ -190,53 +189,6 @@ def comment(request: AuthedHttpRequest, item_uuid):
|
||||||
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
|
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
@require_http_methods(["GET", "POST"])
|
|
||||||
def note(request: AuthedHttpRequest, item_uuid: str, note_uuid: str = ""):
|
|
||||||
item = get_object_or_404(Item, uid=get_uuid_or_404(item_uuid))
|
|
||||||
note_uuid = request.POST.get("uuid", note_uuid)
|
|
||||||
note = None
|
|
||||||
content = request.POST.get("content")
|
|
||||||
if note_uuid:
|
|
||||||
note = get_object_or_404(
|
|
||||||
Note, owner=request.user.identity, item=item, uid=get_uuid_or_404(note_uuid)
|
|
||||||
)
|
|
||||||
if request.method == "GET":
|
|
||||||
return render(
|
|
||||||
request,
|
|
||||||
"note.html",
|
|
||||||
{
|
|
||||||
"item": item,
|
|
||||||
"note": note,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
if request.POST.get("delete", default=False) or not content:
|
|
||||||
if not note:
|
|
||||||
raise Http404(_("Content not found"))
|
|
||||||
note.delete()
|
|
||||||
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
|
|
||||||
share_to_mastodon = bool(request.POST.get("share_to_mastodon", default=False))
|
|
||||||
visibility = int(request.POST.get("visibility", default=0))
|
|
||||||
delete_existing_post = False
|
|
||||||
if note:
|
|
||||||
delete_existing_post = visibility != note.visibility
|
|
||||||
note.content = content
|
|
||||||
note.visibility = visibility
|
|
||||||
note.save()
|
|
||||||
else:
|
|
||||||
note = Note.objects.create(
|
|
||||||
owner=request.user.identity,
|
|
||||||
item=item,
|
|
||||||
content=content,
|
|
||||||
visibility=visibility,
|
|
||||||
)
|
|
||||||
note.sync_to_timeline(delete_existing=delete_existing_post)
|
|
||||||
if share_to_mastodon:
|
|
||||||
note.sync_to_mastodon(delete_existing=delete_existing_post)
|
|
||||||
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
|
|
||||||
|
|
||||||
|
|
||||||
def user_mark_list(request: AuthedHttpRequest, user_name, shelf_type, item_category):
|
def user_mark_list(request: AuthedHttpRequest, user_name, shelf_type, item_category):
|
||||||
return render_list(
|
return render_list(
|
||||||
request, user_name, "mark", shelf_type=shelf_type, item_category=item_category
|
request, user_name, "mark", shelf_type=shelf_type, item_category=item_category
|
||||||
|
|
110
journal/views/note.py
Normal file
110
journal/views/note.py
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
from django import forms
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.core.exceptions import BadRequest, ObjectDoesNotExist, PermissionDenied
|
||||||
|
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
||||||
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
|
from django.utils.translation import gettext as _
|
||||||
|
from django.views.decorators.http import require_http_methods
|
||||||
|
|
||||||
|
from catalog.models import Item
|
||||||
|
from common.forms import NeoModelForm
|
||||||
|
from common.utils import AuthedHttpRequest, get_uuid_or_404
|
||||||
|
|
||||||
|
from ..models import Note
|
||||||
|
from ..models.common import VisibilityType
|
||||||
|
|
||||||
|
|
||||||
|
class NoteForm(NeoModelForm):
|
||||||
|
# _progress_choices = [
|
||||||
|
# ("", _("Progress Type (optional)"))
|
||||||
|
# ] + Note.ProgressType.choices
|
||||||
|
# progress_type = forms.ChoiceField(choices=_progress_choices, required=False)
|
||||||
|
visibility = forms.ChoiceField(
|
||||||
|
widget=forms.RadioSelect(), choices=VisibilityType.choices, initial=0
|
||||||
|
)
|
||||||
|
share_to_mastodon = forms.BooleanField(
|
||||||
|
label=_("Post to Fediverse"), initial=True, required=False
|
||||||
|
)
|
||||||
|
uuid = forms.CharField(widget=forms.HiddenInput(), required=False)
|
||||||
|
# content = forms.CharField(required=False, widget=forms.Textarea)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Note
|
||||||
|
fields = [
|
||||||
|
"id",
|
||||||
|
"title",
|
||||||
|
"content",
|
||||||
|
"visibility",
|
||||||
|
"progress_type",
|
||||||
|
"progress_value",
|
||||||
|
"sensitive",
|
||||||
|
]
|
||||||
|
widgets = {
|
||||||
|
"progress_value": forms.TextInput(
|
||||||
|
attrs={"placeholder": _("Progress (optional)")}
|
||||||
|
),
|
||||||
|
"content": forms.Textarea(attrs={"placeholder": _("Note Content")}),
|
||||||
|
"title": forms.TextInput(
|
||||||
|
attrs={"placeholder": _("Content Warning (optional)")}
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
item = kwargs.pop("item")
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
# allow submit empty content for existing note, and we'll delete it
|
||||||
|
if self.instance.id:
|
||||||
|
self.fields["content"].required = False
|
||||||
|
# get the corresponding progress types for the item
|
||||||
|
types = Note.get_progress_types_by_item(item)
|
||||||
|
if self.instance.progress_type and self.instance.progress_type not in types:
|
||||||
|
types.append(self.instance.progress_type)
|
||||||
|
choices = [("", _("Progress Type (optional)"))] + [(x, x.label) for x in types]
|
||||||
|
self.fields["progress_type"].choices = choices # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@require_http_methods(["GET", "POST"])
|
||||||
|
def note_edit(request: AuthedHttpRequest, item_uuid: str, note_uuid: str = ""):
|
||||||
|
item = get_object_or_404(Item, uid=get_uuid_or_404(item_uuid))
|
||||||
|
owner = request.user.identity
|
||||||
|
note_uuid = request.POST.get("uuid", note_uuid)
|
||||||
|
note = None
|
||||||
|
if note_uuid:
|
||||||
|
note = get_object_or_404(
|
||||||
|
Note, owner=owner, item=item, uid=get_uuid_or_404(note_uuid)
|
||||||
|
)
|
||||||
|
form = NoteForm(
|
||||||
|
request.POST or None, item=item, instance=note, initial={"uuid": note_uuid}
|
||||||
|
)
|
||||||
|
form.instance.owner = owner
|
||||||
|
form.instance.item = item
|
||||||
|
if request.method == "GET":
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"note.html",
|
||||||
|
{
|
||||||
|
"item": item,
|
||||||
|
"note": note,
|
||||||
|
"form": form,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if not form.data["content"]:
|
||||||
|
if not note:
|
||||||
|
raise Http404(_("Content not found"))
|
||||||
|
note.delete()
|
||||||
|
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
|
||||||
|
if note:
|
||||||
|
orig_visibility = note.visibility
|
||||||
|
else:
|
||||||
|
orig_visibility = None
|
||||||
|
if not form.is_valid():
|
||||||
|
raise BadRequest(_("Invalid form data"))
|
||||||
|
note = form.save()
|
||||||
|
delete_existing_post = (
|
||||||
|
orig_visibility is not None and orig_visibility != note.visibility
|
||||||
|
)
|
||||||
|
note.sync_to_timeline(delete_existing=delete_existing_post)
|
||||||
|
if form.cleaned_data["share_to_mastodon"]:
|
||||||
|
note.sync_to_mastodon(delete_existing=delete_existing_post)
|
||||||
|
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
|
|
@ -6,7 +6,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2024-06-13 20:50-0400\n"
|
"POT-Creation-Date: 2024-06-15 18:22-0400\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -715,15 +715,15 @@ msgstr "我的短评和标签"
|
||||||
msgid "my notes"
|
msgid "my notes"
|
||||||
msgstr "我的笔记"
|
msgstr "我的笔记"
|
||||||
|
|
||||||
#: catalog/templates/_item_user_pieces.html:101
|
#: catalog/templates/_item_user_pieces.html:118
|
||||||
msgid "my review"
|
msgid "my review"
|
||||||
msgstr "我的评论"
|
msgstr "我的评论"
|
||||||
|
|
||||||
#: catalog/templates/_item_user_pieces.html:143
|
#: catalog/templates/_item_user_pieces.html:160
|
||||||
msgid "my collection"
|
msgid "my collection"
|
||||||
msgstr "我的收藏单"
|
msgstr "我的收藏单"
|
||||||
|
|
||||||
#: catalog/templates/_item_user_pieces.html:173
|
#: catalog/templates/_item_user_pieces.html:190
|
||||||
msgid "mark history"
|
msgid "mark history"
|
||||||
msgstr "标记历史"
|
msgstr "标记历史"
|
||||||
|
|
||||||
|
@ -1029,7 +1029,7 @@ msgstr "创建"
|
||||||
#: catalog/templates/catalog_edit.html:50
|
#: catalog/templates/catalog_edit.html:50
|
||||||
#: journal/templates/add_to_collection.html:35
|
#: journal/templates/add_to_collection.html:35
|
||||||
#: journal/templates/collection_edit.html:38 journal/templates/comment.html:69
|
#: journal/templates/collection_edit.html:38 journal/templates/comment.html:69
|
||||||
#: journal/templates/mark.html:147 journal/templates/note.html:66
|
#: journal/templates/mark.html:147 journal/templates/note.html:39
|
||||||
#: journal/templates/review_edit.html:39 journal/templates/tag_edit.html:51
|
#: journal/templates/review_edit.html:39 journal/templates/tag_edit.html:51
|
||||||
#: users/templates/users/account.html:43 users/templates/users/account.html:104
|
#: users/templates/users/account.html:43 users/templates/users/account.html:104
|
||||||
#: users/templates/users/preferences.html:168
|
#: users/templates/users/preferences.html:168
|
||||||
|
@ -1114,7 +1114,7 @@ msgstr "热门标签"
|
||||||
#: catalog/templates/item_review_list.html:50 common/templates/_sidebar.html:99
|
#: catalog/templates/item_review_list.html:50 common/templates/_sidebar.html:99
|
||||||
#: common/templates/_sidebar_anonymous.html:43
|
#: common/templates/_sidebar_anonymous.html:43
|
||||||
#: common/templates/_sidebar_anonymous.html:58
|
#: common/templates/_sidebar_anonymous.html:58
|
||||||
#: journal/templates/collection_items.html:8 journal/templates/posts.html:45
|
#: journal/templates/collection_items.html:8 journal/templates/posts.html:49
|
||||||
#: journal/templates/profile.html:109 journal/templates/profile.html:151
|
#: journal/templates/profile.html:109 journal/templates/profile.html:151
|
||||||
#: journal/templates/profile.html:187
|
#: journal/templates/profile.html:187
|
||||||
#: journal/templates/user_collection_list.html:51
|
#: journal/templates/user_collection_list.html:51
|
||||||
|
@ -1393,7 +1393,7 @@ msgstr "权限不足"
|
||||||
|
|
||||||
#: catalog/views_edit.py:200 journal/views/collection.py:229
|
#: catalog/views_edit.py:200 journal/views/collection.py:229
|
||||||
#: journal/views/collection.py:296 journal/views/common.py:81
|
#: journal/views/collection.py:296 journal/views/common.py:81
|
||||||
#: journal/views/mark.py:142 journal/views/post.py:41 journal/views/post.py:55
|
#: journal/views/mark.py:141 journal/views/post.py:41 journal/views/post.py:55
|
||||||
#: journal/views/review.py:93 journal/views/review.py:96 users/views.py:169
|
#: journal/views/review.py:93 journal/views/review.py:96 users/views.py:169
|
||||||
msgid "Invalid parameter"
|
msgid "Invalid parameter"
|
||||||
msgstr "无效参数"
|
msgstr "无效参数"
|
||||||
|
@ -1678,7 +1678,7 @@ msgstr "标题"
|
||||||
msgid "Content (Markdown)"
|
msgid "Content (Markdown)"
|
||||||
msgstr "内容 (Markdown格式)"
|
msgstr "内容 (Markdown格式)"
|
||||||
|
|
||||||
#: journal/forms.py:21
|
#: journal/forms.py:21 journal/views/note.py:26
|
||||||
msgid "Post to Fediverse"
|
msgid "Post to Fediverse"
|
||||||
msgstr "发布到联邦宇宙"
|
msgstr "发布到联邦宇宙"
|
||||||
|
|
||||||
|
@ -1722,31 +1722,96 @@ msgstr "备注"
|
||||||
#: journal/templates/action_open_post.html:14
|
#: journal/templates/action_open_post.html:14
|
||||||
#: journal/templates/action_open_post.html:16
|
#: journal/templates/action_open_post.html:16
|
||||||
#: journal/templates/collection_share.html:35 journal/templates/comment.html:35
|
#: journal/templates/collection_share.html:35 journal/templates/comment.html:35
|
||||||
#: journal/templates/mark.html:93 journal/templates/note.html:32
|
#: journal/templates/mark.html:93 journal/templates/tag_edit.html:42
|
||||||
#: journal/templates/tag_edit.html:42 journal/templates/wrapped_share.html:43
|
#: journal/templates/wrapped_share.html:43 users/templates/users/data.html:47
|
||||||
#: users/templates/users/data.html:47 users/templates/users/data.html:139
|
#: users/templates/users/data.html:139
|
||||||
#: users/templates/users/preferences.html:54
|
#: users/templates/users/preferences.html:54
|
||||||
msgid "Public"
|
msgid "Public"
|
||||||
msgstr "公开"
|
msgstr "公开"
|
||||||
|
|
||||||
#: journal/models/common.py:34 journal/templates/action_open_post.html:10
|
#: journal/models/common.py:34 journal/templates/action_open_post.html:10
|
||||||
#: journal/templates/collection_share.html:46 journal/templates/comment.html:42
|
#: journal/templates/collection_share.html:46 journal/templates/comment.html:42
|
||||||
#: journal/templates/mark.html:100 journal/templates/note.html:39
|
#: journal/templates/mark.html:100 journal/templates/wrapped_share.html:49
|
||||||
#: journal/templates/wrapped_share.html:49 users/templates/users/data.html:55
|
#: users/templates/users/data.html:55 users/templates/users/data.html:147
|
||||||
#: users/templates/users/data.html:147
|
|
||||||
#: users/templates/users/preferences.html:61
|
#: users/templates/users/preferences.html:61
|
||||||
msgid "Followers Only"
|
msgid "Followers Only"
|
||||||
msgstr "仅关注者"
|
msgstr "仅关注者"
|
||||||
|
|
||||||
#: journal/models/common.py:35 journal/templates/action_open_post.html:12
|
#: journal/models/common.py:35 journal/templates/action_open_post.html:12
|
||||||
#: journal/templates/collection_share.html:57 journal/templates/comment.html:49
|
#: journal/templates/collection_share.html:57 journal/templates/comment.html:49
|
||||||
#: journal/templates/mark.html:107 journal/templates/note.html:46
|
#: journal/templates/mark.html:107 journal/templates/wrapped_share.html:55
|
||||||
#: journal/templates/wrapped_share.html:55 users/templates/users/data.html:63
|
#: users/templates/users/data.html:63 users/templates/users/data.html:155
|
||||||
#: users/templates/users/data.html:155
|
|
||||||
#: users/templates/users/preferences.html:68
|
#: users/templates/users/preferences.html:68
|
||||||
msgid "Mentioned Only"
|
msgid "Mentioned Only"
|
||||||
msgstr "自己和提到的人"
|
msgstr "自己和提到的人"
|
||||||
|
|
||||||
|
#: journal/models/note.py:27
|
||||||
|
msgid "Page"
|
||||||
|
msgstr "页码"
|
||||||
|
|
||||||
|
#: journal/models/note.py:28
|
||||||
|
msgid "Chapter"
|
||||||
|
msgstr "章节"
|
||||||
|
|
||||||
|
#: journal/models/note.py:31
|
||||||
|
msgid "Part"
|
||||||
|
msgstr "分部"
|
||||||
|
|
||||||
|
#: journal/models/note.py:32
|
||||||
|
msgid "Episode"
|
||||||
|
msgstr "单集"
|
||||||
|
|
||||||
|
#: journal/models/note.py:33
|
||||||
|
msgid "Track"
|
||||||
|
msgstr "曲目"
|
||||||
|
|
||||||
|
#: journal/models/note.py:34
|
||||||
|
msgid "Cycle"
|
||||||
|
msgstr "周目"
|
||||||
|
|
||||||
|
#: journal/models/note.py:35
|
||||||
|
msgid "Timestamp"
|
||||||
|
msgstr "时间戳"
|
||||||
|
|
||||||
|
#: journal/models/note.py:36
|
||||||
|
msgid "Percentage"
|
||||||
|
msgstr "百分比"
|
||||||
|
|
||||||
|
#: journal/models/note.py:53
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "Page {value}"
|
||||||
|
msgstr "第{value}页"
|
||||||
|
|
||||||
|
#: journal/models/note.py:54
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "Chapter {value}"
|
||||||
|
msgstr "第{value}章"
|
||||||
|
|
||||||
|
#: journal/models/note.py:57
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "Part {value}"
|
||||||
|
msgstr "第{value}部"
|
||||||
|
|
||||||
|
#: journal/models/note.py:58
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "Episode {value}"
|
||||||
|
msgstr "第{value}集"
|
||||||
|
|
||||||
|
#: journal/models/note.py:59
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "Track {value}"
|
||||||
|
msgstr "第{value}首"
|
||||||
|
|
||||||
|
#: journal/models/note.py:60
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "Cycle {value}"
|
||||||
|
msgstr "{value}周目"
|
||||||
|
|
||||||
|
#: journal/models/renderers.py:94 mastodon/api.py:619 takahe/utils.py:540
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "regarding {item_title}, may contain spoiler or triggering content"
|
||||||
|
msgstr "关于 {item_title},可能包含剧透或敏感内容"
|
||||||
|
|
||||||
#: journal/models/shelf.py:24
|
#: journal/models/shelf.py:24
|
||||||
msgid "WISHLIST"
|
msgid "WISHLIST"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -2323,7 +2388,6 @@ msgid "Tips: use >!text!< for spoilers; some instances may not be able to
|
||||||
msgstr "提示: 善用 >!文字!< 标记可隐藏剧透; 超过360字可能无法分享到联邦宇宙实例时间轴。"
|
msgstr "提示: 善用 >!文字!< 标记可隐藏剧透; 超过360字可能无法分享到联邦宇宙实例时间轴。"
|
||||||
|
|
||||||
#: journal/templates/comment.html:62 journal/templates/mark.html:120
|
#: journal/templates/comment.html:62 journal/templates/mark.html:120
|
||||||
#: journal/templates/note.html:59
|
|
||||||
msgid "Repost to timeline"
|
msgid "Repost to timeline"
|
||||||
msgstr "转发到时间轴"
|
msgstr "转发到时间轴"
|
||||||
|
|
||||||
|
@ -2450,6 +2514,10 @@ msgstr ""
|
||||||
msgid "Note"
|
msgid "Note"
|
||||||
msgstr "笔记"
|
msgstr "笔记"
|
||||||
|
|
||||||
|
#: journal/templates/note.html:21
|
||||||
|
msgid "Note with empty content will be deleted, sure to continue?"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: journal/templates/profile.html:55
|
#: journal/templates/profile.html:55
|
||||||
msgid "calendar"
|
msgid "calendar"
|
||||||
msgstr "日历"
|
msgstr "日历"
|
||||||
|
@ -2458,7 +2526,7 @@ msgstr "日历"
|
||||||
msgid "annual summary"
|
msgid "annual summary"
|
||||||
msgstr "年度小结"
|
msgstr "年度小结"
|
||||||
|
|
||||||
#: journal/templates/profile.html:131 mastodon/api.py:747
|
#: journal/templates/profile.html:131 mastodon/api.py:678
|
||||||
msgid "collection"
|
msgid "collection"
|
||||||
msgstr "收藏单"
|
msgstr "收藏单"
|
||||||
|
|
||||||
|
@ -2590,7 +2658,7 @@ msgstr "找不到条目,请使用本站条目网址。"
|
||||||
msgid "Login required"
|
msgid "Login required"
|
||||||
msgstr "登录后访问"
|
msgstr "登录后访问"
|
||||||
|
|
||||||
#: journal/views/common.py:33 journal/views/mark.py:119
|
#: journal/views/common.py:33 journal/views/mark.py:118
|
||||||
msgid "Data saved but unable to repost to Fediverse instance."
|
msgid "Data saved but unable to repost to Fediverse instance."
|
||||||
msgstr "数据已保存但未能转发到联邦实例。"
|
msgstr "数据已保存但未能转发到联邦实例。"
|
||||||
|
|
||||||
|
@ -2602,15 +2670,35 @@ msgstr "正在重定向到你的联邦实例以重新认证。"
|
||||||
msgid "List not found."
|
msgid "List not found."
|
||||||
msgstr "列表未找到"
|
msgstr "列表未找到"
|
||||||
|
|
||||||
#: journal/views/mark.py:110
|
#: journal/views/mark.py:109
|
||||||
msgid "Content too long for your Fediverse instance."
|
msgid "Content too long for your Fediverse instance."
|
||||||
msgstr "内容过长,超出了你的联邦实例的限制。"
|
msgstr "内容过长,超出了你的联邦实例的限制。"
|
||||||
|
|
||||||
#: journal/views/mark.py:164 journal/views/mark.py:218
|
#: journal/views/mark.py:163 journal/views/note.py:94
|
||||||
#: journal/views/review.py:30
|
#: journal/views/review.py:30
|
||||||
msgid "Content not found"
|
msgid "Content not found"
|
||||||
msgstr "内容未找到"
|
msgstr "内容未找到"
|
||||||
|
|
||||||
|
#: journal/views/note.py:44
|
||||||
|
msgid "Progress (optional)"
|
||||||
|
msgstr "进度(选填)"
|
||||||
|
|
||||||
|
#: journal/views/note.py:46
|
||||||
|
msgid "Note Content"
|
||||||
|
msgstr "笔记内容"
|
||||||
|
|
||||||
|
#: journal/views/note.py:48
|
||||||
|
msgid "Content Warning (optional)"
|
||||||
|
msgstr "剧透或敏感内容提示(选填)"
|
||||||
|
|
||||||
|
#: journal/views/note.py:62
|
||||||
|
msgid "Progress Type (optional)"
|
||||||
|
msgstr "进度类型(选填)"
|
||||||
|
|
||||||
|
#: journal/views/note.py:102
|
||||||
|
msgid "Invalid form data"
|
||||||
|
msgstr "无效表单信息。"
|
||||||
|
|
||||||
#: journal/views/review.py:112 journal/views/review.py:126
|
#: journal/views/review.py:112 journal/views/review.py:126
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Reviews by {0}"
|
msgid "Reviews by {0}"
|
||||||
|
@ -2649,16 +2737,11 @@ msgstr "标签已更新"
|
||||||
msgid "Summary posted to timeline."
|
msgid "Summary posted to timeline."
|
||||||
msgstr "总结已发布到时间轴"
|
msgstr "总结已发布到时间轴"
|
||||||
|
|
||||||
#: mastodon/api.py:600 takahe/utils.py:540
|
#: mastodon/api.py:683
|
||||||
#, python-brace-format
|
|
||||||
msgid "regarding {item_title}, may contain spoiler or triggering content"
|
|
||||||
msgstr "关于 {item_title},可能包含剧透或敏感内容"
|
|
||||||
|
|
||||||
#: mastodon/api.py:752
|
|
||||||
msgid "shared my collection"
|
msgid "shared my collection"
|
||||||
msgstr "分享我的收藏单"
|
msgstr "分享我的收藏单"
|
||||||
|
|
||||||
#: mastodon/api.py:755
|
#: mastodon/api.py:686
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "shared {username}'s collection"
|
msgid "shared {username}'s collection"
|
||||||
msgstr "分享 {username} 的收藏单"
|
msgstr "分享 {username} 的收藏单"
|
||||||
|
|
|
@ -6,7 +6,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2024-06-13 20:50-0400\n"
|
"POT-Creation-Date: 2024-06-15 18:22-0400\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -715,15 +715,15 @@ msgstr "我的短評和標籤"
|
||||||
msgid "my notes"
|
msgid "my notes"
|
||||||
msgstr "我的筆記"
|
msgstr "我的筆記"
|
||||||
|
|
||||||
#: catalog/templates/_item_user_pieces.html:101
|
#: catalog/templates/_item_user_pieces.html:118
|
||||||
msgid "my review"
|
msgid "my review"
|
||||||
msgstr "我的評論"
|
msgstr "我的評論"
|
||||||
|
|
||||||
#: catalog/templates/_item_user_pieces.html:143
|
#: catalog/templates/_item_user_pieces.html:160
|
||||||
msgid "my collection"
|
msgid "my collection"
|
||||||
msgstr "我的收藏單"
|
msgstr "我的收藏單"
|
||||||
|
|
||||||
#: catalog/templates/_item_user_pieces.html:173
|
#: catalog/templates/_item_user_pieces.html:190
|
||||||
msgid "mark history"
|
msgid "mark history"
|
||||||
msgstr "標記歷史"
|
msgstr "標記歷史"
|
||||||
|
|
||||||
|
@ -1029,7 +1029,7 @@ msgstr "創建"
|
||||||
#: catalog/templates/catalog_edit.html:50
|
#: catalog/templates/catalog_edit.html:50
|
||||||
#: journal/templates/add_to_collection.html:35
|
#: journal/templates/add_to_collection.html:35
|
||||||
#: journal/templates/collection_edit.html:38 journal/templates/comment.html:69
|
#: journal/templates/collection_edit.html:38 journal/templates/comment.html:69
|
||||||
#: journal/templates/mark.html:147 journal/templates/note.html:66
|
#: journal/templates/mark.html:147 journal/templates/note.html:39
|
||||||
#: journal/templates/review_edit.html:39 journal/templates/tag_edit.html:51
|
#: journal/templates/review_edit.html:39 journal/templates/tag_edit.html:51
|
||||||
#: users/templates/users/account.html:43 users/templates/users/account.html:104
|
#: users/templates/users/account.html:43 users/templates/users/account.html:104
|
||||||
#: users/templates/users/preferences.html:168
|
#: users/templates/users/preferences.html:168
|
||||||
|
@ -1114,7 +1114,7 @@ msgstr "熱門標籤"
|
||||||
#: catalog/templates/item_review_list.html:50 common/templates/_sidebar.html:99
|
#: catalog/templates/item_review_list.html:50 common/templates/_sidebar.html:99
|
||||||
#: common/templates/_sidebar_anonymous.html:43
|
#: common/templates/_sidebar_anonymous.html:43
|
||||||
#: common/templates/_sidebar_anonymous.html:58
|
#: common/templates/_sidebar_anonymous.html:58
|
||||||
#: journal/templates/collection_items.html:8 journal/templates/posts.html:45
|
#: journal/templates/collection_items.html:8 journal/templates/posts.html:49
|
||||||
#: journal/templates/profile.html:109 journal/templates/profile.html:151
|
#: journal/templates/profile.html:109 journal/templates/profile.html:151
|
||||||
#: journal/templates/profile.html:187
|
#: journal/templates/profile.html:187
|
||||||
#: journal/templates/user_collection_list.html:51
|
#: journal/templates/user_collection_list.html:51
|
||||||
|
@ -1393,7 +1393,7 @@ msgstr "權限不足"
|
||||||
|
|
||||||
#: catalog/views_edit.py:200 journal/views/collection.py:229
|
#: catalog/views_edit.py:200 journal/views/collection.py:229
|
||||||
#: journal/views/collection.py:296 journal/views/common.py:81
|
#: journal/views/collection.py:296 journal/views/common.py:81
|
||||||
#: journal/views/mark.py:142 journal/views/post.py:41 journal/views/post.py:55
|
#: journal/views/mark.py:141 journal/views/post.py:41 journal/views/post.py:55
|
||||||
#: journal/views/review.py:93 journal/views/review.py:96 users/views.py:169
|
#: journal/views/review.py:93 journal/views/review.py:96 users/views.py:169
|
||||||
msgid "Invalid parameter"
|
msgid "Invalid parameter"
|
||||||
msgstr "無效參數"
|
msgstr "無效參數"
|
||||||
|
@ -1678,7 +1678,7 @@ msgstr "標題"
|
||||||
msgid "Content (Markdown)"
|
msgid "Content (Markdown)"
|
||||||
msgstr "內容 (Markdown格式)"
|
msgstr "內容 (Markdown格式)"
|
||||||
|
|
||||||
#: journal/forms.py:21
|
#: journal/forms.py:21 journal/views/note.py:26
|
||||||
msgid "Post to Fediverse"
|
msgid "Post to Fediverse"
|
||||||
msgstr "發佈到聯邦宇宙"
|
msgstr "發佈到聯邦宇宙"
|
||||||
|
|
||||||
|
@ -1722,31 +1722,96 @@ msgstr "備註"
|
||||||
#: journal/templates/action_open_post.html:14
|
#: journal/templates/action_open_post.html:14
|
||||||
#: journal/templates/action_open_post.html:16
|
#: journal/templates/action_open_post.html:16
|
||||||
#: journal/templates/collection_share.html:35 journal/templates/comment.html:35
|
#: journal/templates/collection_share.html:35 journal/templates/comment.html:35
|
||||||
#: journal/templates/mark.html:93 journal/templates/note.html:32
|
#: journal/templates/mark.html:93 journal/templates/tag_edit.html:42
|
||||||
#: journal/templates/tag_edit.html:42 journal/templates/wrapped_share.html:43
|
#: journal/templates/wrapped_share.html:43 users/templates/users/data.html:47
|
||||||
#: users/templates/users/data.html:47 users/templates/users/data.html:139
|
#: users/templates/users/data.html:139
|
||||||
#: users/templates/users/preferences.html:54
|
#: users/templates/users/preferences.html:54
|
||||||
msgid "Public"
|
msgid "Public"
|
||||||
msgstr "公開"
|
msgstr "公開"
|
||||||
|
|
||||||
#: journal/models/common.py:34 journal/templates/action_open_post.html:10
|
#: journal/models/common.py:34 journal/templates/action_open_post.html:10
|
||||||
#: journal/templates/collection_share.html:46 journal/templates/comment.html:42
|
#: journal/templates/collection_share.html:46 journal/templates/comment.html:42
|
||||||
#: journal/templates/mark.html:100 journal/templates/note.html:39
|
#: journal/templates/mark.html:100 journal/templates/wrapped_share.html:49
|
||||||
#: journal/templates/wrapped_share.html:49 users/templates/users/data.html:55
|
#: users/templates/users/data.html:55 users/templates/users/data.html:147
|
||||||
#: users/templates/users/data.html:147
|
|
||||||
#: users/templates/users/preferences.html:61
|
#: users/templates/users/preferences.html:61
|
||||||
msgid "Followers Only"
|
msgid "Followers Only"
|
||||||
msgstr "僅關注者"
|
msgstr "僅關注者"
|
||||||
|
|
||||||
#: journal/models/common.py:35 journal/templates/action_open_post.html:12
|
#: journal/models/common.py:35 journal/templates/action_open_post.html:12
|
||||||
#: journal/templates/collection_share.html:57 journal/templates/comment.html:49
|
#: journal/templates/collection_share.html:57 journal/templates/comment.html:49
|
||||||
#: journal/templates/mark.html:107 journal/templates/note.html:46
|
#: journal/templates/mark.html:107 journal/templates/wrapped_share.html:55
|
||||||
#: journal/templates/wrapped_share.html:55 users/templates/users/data.html:63
|
#: users/templates/users/data.html:63 users/templates/users/data.html:155
|
||||||
#: users/templates/users/data.html:155
|
|
||||||
#: users/templates/users/preferences.html:68
|
#: users/templates/users/preferences.html:68
|
||||||
msgid "Mentioned Only"
|
msgid "Mentioned Only"
|
||||||
msgstr "自己和提到的人"
|
msgstr "自己和提到的人"
|
||||||
|
|
||||||
|
#: journal/models/note.py:27
|
||||||
|
msgid "Page"
|
||||||
|
msgstr "頁碼"
|
||||||
|
|
||||||
|
#: journal/models/note.py:28
|
||||||
|
msgid "Chapter"
|
||||||
|
msgstr "章節"
|
||||||
|
|
||||||
|
#: journal/models/note.py:31
|
||||||
|
msgid "Part"
|
||||||
|
msgstr "分部"
|
||||||
|
|
||||||
|
#: journal/models/note.py:32
|
||||||
|
msgid "Episode"
|
||||||
|
msgstr "單集"
|
||||||
|
|
||||||
|
#: journal/models/note.py:33
|
||||||
|
msgid "Track"
|
||||||
|
msgstr "曲目"
|
||||||
|
|
||||||
|
#: journal/models/note.py:34
|
||||||
|
msgid "Cycle"
|
||||||
|
msgstr "周目"
|
||||||
|
|
||||||
|
#: journal/models/note.py:35
|
||||||
|
msgid "Timestamp"
|
||||||
|
msgstr "時間戳"
|
||||||
|
|
||||||
|
#: journal/models/note.py:36
|
||||||
|
msgid "Percentage"
|
||||||
|
msgstr "百分比"
|
||||||
|
|
||||||
|
#: journal/models/note.py:53
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "Page {value}"
|
||||||
|
msgstr "第{value}頁"
|
||||||
|
|
||||||
|
#: journal/models/note.py:54
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "Chapter {value}"
|
||||||
|
msgstr "第{value}章"
|
||||||
|
|
||||||
|
#: journal/models/note.py:57
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "Part {value}"
|
||||||
|
msgstr "第{value}部"
|
||||||
|
|
||||||
|
#: journal/models/note.py:58
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "Episode {value}"
|
||||||
|
msgstr "第{value}集"
|
||||||
|
|
||||||
|
#: journal/models/note.py:59
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "Track {value}"
|
||||||
|
msgstr "第{value}首"
|
||||||
|
|
||||||
|
#: journal/models/note.py:60
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "Cycle {value}"
|
||||||
|
msgstr "{value}周目"
|
||||||
|
|
||||||
|
#: journal/models/renderers.py:94 mastodon/api.py:619 takahe/utils.py:540
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "regarding {item_title}, may contain spoiler or triggering content"
|
||||||
|
msgstr "關於 {item_title},可能包含劇透或敏感內容"
|
||||||
|
|
||||||
#: journal/models/shelf.py:24
|
#: journal/models/shelf.py:24
|
||||||
msgid "WISHLIST"
|
msgid "WISHLIST"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -2323,7 +2388,6 @@ msgid "Tips: use >!text!< for spoilers; some instances may not be able to
|
||||||
msgstr "提示: 善用 >!文字!< 標記可隱藏劇透; 超過360字可能無法分享到聯邦宇宙實例時間軸。"
|
msgstr "提示: 善用 >!文字!< 標記可隱藏劇透; 超過360字可能無法分享到聯邦宇宙實例時間軸。"
|
||||||
|
|
||||||
#: journal/templates/comment.html:62 journal/templates/mark.html:120
|
#: journal/templates/comment.html:62 journal/templates/mark.html:120
|
||||||
#: journal/templates/note.html:59
|
|
||||||
msgid "Repost to timeline"
|
msgid "Repost to timeline"
|
||||||
msgstr "轉發到時間軸"
|
msgstr "轉發到時間軸"
|
||||||
|
|
||||||
|
@ -2450,6 +2514,10 @@ msgstr ""
|
||||||
msgid "Note"
|
msgid "Note"
|
||||||
msgstr "筆記"
|
msgstr "筆記"
|
||||||
|
|
||||||
|
#: journal/templates/note.html:21
|
||||||
|
msgid "Note with empty content will be deleted, sure to continue?"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: journal/templates/profile.html:55
|
#: journal/templates/profile.html:55
|
||||||
msgid "calendar"
|
msgid "calendar"
|
||||||
msgstr "日曆"
|
msgstr "日曆"
|
||||||
|
@ -2458,7 +2526,7 @@ msgstr "日曆"
|
||||||
msgid "annual summary"
|
msgid "annual summary"
|
||||||
msgstr "年度小結"
|
msgstr "年度小結"
|
||||||
|
|
||||||
#: journal/templates/profile.html:131 mastodon/api.py:747
|
#: journal/templates/profile.html:131 mastodon/api.py:678
|
||||||
msgid "collection"
|
msgid "collection"
|
||||||
msgstr "收藏單"
|
msgstr "收藏單"
|
||||||
|
|
||||||
|
@ -2590,7 +2658,7 @@ msgstr "找不到條目,請使用本站條目網址。"
|
||||||
msgid "Login required"
|
msgid "Login required"
|
||||||
msgstr "登錄後訪問"
|
msgstr "登錄後訪問"
|
||||||
|
|
||||||
#: journal/views/common.py:33 journal/views/mark.py:119
|
#: journal/views/common.py:33 journal/views/mark.py:118
|
||||||
msgid "Data saved but unable to repost to Fediverse instance."
|
msgid "Data saved but unable to repost to Fediverse instance."
|
||||||
msgstr "數據已保存但未能轉發到聯邦實例。"
|
msgstr "數據已保存但未能轉發到聯邦實例。"
|
||||||
|
|
||||||
|
@ -2602,15 +2670,35 @@ msgstr "正在重定向到你的聯邦實例以重新認證。"
|
||||||
msgid "List not found."
|
msgid "List not found."
|
||||||
msgstr "列表未找到"
|
msgstr "列表未找到"
|
||||||
|
|
||||||
#: journal/views/mark.py:110
|
#: journal/views/mark.py:109
|
||||||
msgid "Content too long for your Fediverse instance."
|
msgid "Content too long for your Fediverse instance."
|
||||||
msgstr "內容過長,超出了你的聯邦實例的限制。"
|
msgstr "內容過長,超出了你的聯邦實例的限制。"
|
||||||
|
|
||||||
#: journal/views/mark.py:164 journal/views/mark.py:218
|
#: journal/views/mark.py:163 journal/views/note.py:94
|
||||||
#: journal/views/review.py:30
|
#: journal/views/review.py:30
|
||||||
msgid "Content not found"
|
msgid "Content not found"
|
||||||
msgstr "內容未找到"
|
msgstr "內容未找到"
|
||||||
|
|
||||||
|
#: journal/views/note.py:44
|
||||||
|
msgid "Progress (optional)"
|
||||||
|
msgstr "進度(選填)"
|
||||||
|
|
||||||
|
#: journal/views/note.py:46
|
||||||
|
msgid "Note Content"
|
||||||
|
msgstr "筆記內容"
|
||||||
|
|
||||||
|
#: journal/views/note.py:48
|
||||||
|
msgid "Content Warning (optional)"
|
||||||
|
msgstr "劇透或敏感內容提示(選填)"
|
||||||
|
|
||||||
|
#: journal/views/note.py:62
|
||||||
|
msgid "Progress Type (optional)"
|
||||||
|
msgstr "進度類型(選填)"
|
||||||
|
|
||||||
|
#: journal/views/note.py:102
|
||||||
|
msgid "Invalid form data"
|
||||||
|
msgstr "無效表單信息。"
|
||||||
|
|
||||||
#: journal/views/review.py:112 journal/views/review.py:126
|
#: journal/views/review.py:112 journal/views/review.py:126
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Reviews by {0}"
|
msgid "Reviews by {0}"
|
||||||
|
@ -2649,16 +2737,11 @@ msgstr "標籤已更新"
|
||||||
msgid "Summary posted to timeline."
|
msgid "Summary posted to timeline."
|
||||||
msgstr "總結已發佈到時間軸"
|
msgstr "總結已發佈到時間軸"
|
||||||
|
|
||||||
#: mastodon/api.py:600 takahe/utils.py:540
|
#: mastodon/api.py:683
|
||||||
#, python-brace-format
|
|
||||||
msgid "regarding {item_title}, may contain spoiler or triggering content"
|
|
||||||
msgstr "關於 {item_title},可能包含劇透或敏感內容"
|
|
||||||
|
|
||||||
#: mastodon/api.py:752
|
|
||||||
msgid "shared my collection"
|
msgid "shared my collection"
|
||||||
msgstr "分享我的收藏單"
|
msgstr "分享我的收藏單"
|
||||||
|
|
||||||
#: mastodon/api.py:755
|
#: mastodon/api.py:686
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "shared {username}'s collection"
|
msgid "shared {username}'s collection"
|
||||||
msgstr "分享 {username} 的收藏單"
|
msgstr "分享 {username} 的收藏單"
|
||||||
|
|
Loading…
Add table
Reference in a new issue