lazy load collection page

This commit is contained in:
Your Name 2025-01-20 10:21:57 -05:00 committed by Henri Dickson
parent 47cffef24b
commit adfc9984e2
8 changed files with 83 additions and 69 deletions

View file

@ -28,7 +28,7 @@ repos:
rev: v0.9.2 rev: v0.9.2
hooks: hooks:
- id: ruff - id: ruff
args: [ --fix ] args: [ "--fix" ]
- id: ruff-format - id: ruff-format
# - repo: https://github.com/pycqa/isort # - repo: https://github.com/pycqa/isort

View file

@ -78,11 +78,11 @@ def add_note_for_item(request, item_uuid: str, n_in: NoteInSchema):
response={200: NoteSchema, 401: Result, 403: Result, 404: Result}, response={200: NoteSchema, 401: Result, 403: Result, 404: Result},
tags=["note"], tags=["note"],
) )
def update_note(request, tag_uuid: str, n_in: NoteInSchema): def update_note(request, note_uuid: str, n_in: NoteInSchema):
""" """
Update a note. Update a note.
""" """
note = Note.get_by_url_and_owner(tag_uuid, request.user.identity.pk) note = Note.get_by_url_and_owner(note_uuid, request.user.identity.pk)
if not note: if not note:
return NOT_FOUND return NOT_FOUND
note.title = n_in.title note.title = n_in.title
@ -101,11 +101,11 @@ def update_note(request, tag_uuid: str, n_in: NoteInSchema):
response={200: Result, 401: Result, 403: Result, 404: Result}, response={200: Result, 401: Result, 403: Result, 404: Result},
tags=["note"], tags=["note"],
) )
def delete_note(request, tag_uuid: str): def delete_note(request, note_uuid: str):
""" """
Delete a note. Delete a note.
""" """
note = Note.get_by_url_and_owner(tag_uuid, request.user.identity.pk) note = Note.get_by_url_and_owner(note_uuid, request.user.identity.pk)
if not note: if not note:
return NOT_FOUND return NOT_FOUND
note.delete() note.delete()

View file

@ -40,7 +40,7 @@ class List(Piece):
@property @property
def ordered_members(self): def ordered_members(self):
return self.members.all().order_by("position") return self.members.all().order_by("position", "item_id")
@property @property
def ordered_items(self): def ordered_items(self):
@ -104,7 +104,7 @@ class List(Piece):
i = ordered_member_ids.index(m.pk) i = ordered_member_ids.index(m.pk)
if m.position != i + 1: if m.position != i + 1:
m.position = i + 1 m.position = i + 1
m.save() m.save(update_fields=["position"])
except ValueError: except ValueError:
pass pass

View file

@ -86,7 +86,7 @@
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if collection_member %} {% if collection_member %}
<p hx-target="this" hx-swap="innerHTML"> <div hx-swap="innerHTML" hx-target="this">
{% if collection_edit %} {% if collection_edit %}
<span class="action"> <span class="action">
<a title="{% trans "Update note" %}" <a title="{% trans "Update note" %}"
@ -94,7 +94,8 @@
</span> </span>
{% endif %} {% endif %}
{% if collection_member.note %}{{ collection_member.note }}{% endif %} {% if collection_member.note %}{{ collection_member.note }}{% endif %}
</p> &nbsp;
</div>
{% endif %} {% endif %}
</footer> </footer>
{% endif %} {% endif %}

View file

@ -111,7 +111,8 @@
{% endif %} {% endif %}
{% endcomment %} {% endcomment %}
<section> <section>
<div class="entity-list" <div id="collection_items"
class="item-list sortable"
hx-get="{% url 'journal:collection_retrieve_items' collection.uuid %}" hx-get="{% url 'journal:collection_retrieve_items' collection.uuid %}"
hx-trigger="load"> hx-trigger="load">
<i class="fa-solid fa-compact-disc fa-spin loading"></i> <i class="fa-solid fa-compact-disc fa-spin loading"></i>

View file

@ -43,9 +43,57 @@
<hr> <hr>
<details open> <details open>
<summary>{% trans "Items" %}</summary> <summary>{% trans "Items" %}</summary>
<div id="collection_items" <section>
hx-get="{% url 'journal:collection_retrieve_items' collection.uuid %}?edit=1" <div id="collection_items"
hx-trigger="load"></div> hx-get="{% url 'journal:collection_retrieve_items' collection.uuid %}?edit=1"
hx-trigger="load"></div>
</section>
<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 'note' %}"
style="min-width:24rem">
<input class="button"
type="submit"
value="{% trans 'Add an item to this collection' %}">
</form>
<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="{% trans "Drag and drop to change the order order and click here to save" %}">
</form>
</details> </details>
{% endif %} {% endif %}
</div> </div>

View file

@ -1,59 +1,18 @@
{% load thumb %} {% load thumb %}
{% load i18n %} {% load i18n %}
{% load l10n %} {% load l10n %}
<div class="item-list sortable"> {% for member in members %}
{% for member in collection.ordered_members %} {% include '_list_item.html' with item=member.item mark=None collection_member=member %}
{% include '_list_item.html' with item=member.item mark=None collection_member=member %} {% if forloop.last %}
{% empty %} <div hx-get="{% url 'journal:collection_retrieve_items' collection.uuid %}?last_pos={{ member.position }}&amp;last_member={{ member.id }}&amp;edit={{ request.GET.edit }}"
hx-trigger="{% if request.GET.edit %}load{% else %}revealed{% endif %}"
hx-swap="outerHTML">
<i class="fa-solid fa-compact-disc fa-spin loading"></i>{{ member.position }}
</div>
{% endif %}
{% empty %}
{% if not request.GET.last_pos %}
{% trans "nothing so far." %} {% trans "nothing so far." %}
{% endfor %} {% endif %}
</div> {% endfor %}
{% if collection_edit %}
<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 'note' %}"
style="min-width:24rem">
<input class="button"
type="submit"
value="{% trans 'Add an item to this collection' %}">
</form>
<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="{% trans "Drag and drop to change the order order and click here to save" %}">
</form>
{% endif %}
{% if msg %}<script type="text/javascript">alert("{{ msg|escapejs }}");</script>{% endif %} {% if msg %}<script type="text/javascript">alert("{{ msg|escapejs }}");</script>{% endif %}

View file

@ -194,13 +194,18 @@ def collection_retrieve_items(
collection = get_object_or_404(Collection, uid=get_uuid_or_404(collection_uuid)) collection = get_object_or_404(Collection, uid=get_uuid_or_404(collection_uuid))
if not collection.is_visible_to(request.user): if not collection.is_visible_to(request.user):
raise PermissionDenied(_("Insufficient permission")) raise PermissionDenied(_("Insufficient permission"))
form = CollectionForm(instance=collection) members = collection.ordered_members
last_pos = int_(request.GET.get("last_pos"))
print("p", last_pos)
if last_pos:
last_member = int_(request.GET.get("last_member"))
members = members.filter(position__gte=last_pos).exclude(id=last_member)
return render( return render(
request, request,
"collection_items.html", "collection_items.html",
{ {
"collection": collection, "collection": collection,
"form": form, "members": members[:20],
"collection_edit": edit or request.GET.get("edit"), "collection_edit": edit or request.GET.get("edit"),
"msg": msg, "msg": msg,
}, },