mirror of
https://github.com/minetest/contentdb.git
synced 2024-11-10 01:23:48 +01:00
Allow ordering packages in collections
This commit is contained in:
parent
4bd53e4b1a
commit
e5e68826fb
@ -84,6 +84,7 @@ class CollectionForm(FlaskForm):
|
|||||||
min_entries=0)
|
min_entries=0)
|
||||||
package_ids = FieldList(HiddenField(), min_entries=0)
|
package_ids = FieldList(HiddenField(), min_entries=0)
|
||||||
package_removed = FieldList(HiddenField(), min_entries=0)
|
package_removed = FieldList(HiddenField(), min_entries=0)
|
||||||
|
order = HiddenField()
|
||||||
submit = SubmitField(lazy_gettext("Save"))
|
submit = SubmitField(lazy_gettext("Save"))
|
||||||
|
|
||||||
|
|
||||||
@ -178,7 +179,10 @@ def handle_create_edit(collection: Collection, form: CollectionForm,
|
|||||||
form.populate_obj(collection)
|
form.populate_obj(collection)
|
||||||
collection.name = name
|
collection.name = name
|
||||||
|
|
||||||
order = 1
|
item_lookup = {}
|
||||||
|
for link in collection.items:
|
||||||
|
item_lookup[link.package.get_id()] = link
|
||||||
|
|
||||||
for i, package_id in enumerate(form.package_ids):
|
for i, package_id in enumerate(form.package_ids):
|
||||||
link = next((x for x in collection.items if str(x.package.get_id()) == package_id.data), None)
|
link = next((x for x in collection.items if str(x.package.get_id()) == package_id.data), None)
|
||||||
to_delete = form.package_removed[i].data == "1"
|
to_delete = form.package_removed[i].data == "1"
|
||||||
@ -194,15 +198,15 @@ def handle_create_edit(collection: Collection, form: CollectionForm,
|
|||||||
link.package = package
|
link.package = package
|
||||||
link.collection = collection
|
link.collection = collection
|
||||||
link.description = form.descriptions[i].data
|
link.description = form.descriptions[i].data
|
||||||
link.order = order
|
item_lookup[link.package.get_id()] = link
|
||||||
order += 1
|
|
||||||
db.session.add(link)
|
db.session.add(link)
|
||||||
elif to_delete:
|
elif to_delete:
|
||||||
db.session.delete(link)
|
db.session.delete(link)
|
||||||
else:
|
else:
|
||||||
link.description = form.descriptions[i].data
|
link.description = form.descriptions[i].data
|
||||||
link.order = order
|
|
||||||
order += 1
|
for i, package_id in enumerate(form.order.data.split(",")):
|
||||||
|
item_lookup[package_id].order = i + 1
|
||||||
|
|
||||||
add_audit_log(severity, current_user,
|
add_audit_log(severity, current_user,
|
||||||
f"Edited collection {collection.author.username}/{collection.name}",
|
f"Edited collection {collection.author.username}/{collection.name}",
|
||||||
|
@ -57,7 +57,7 @@ class Collection(db.Model):
|
|||||||
private = db.Column(db.Boolean, nullable=False, default=False)
|
private = db.Column(db.Boolean, nullable=False, default=False)
|
||||||
|
|
||||||
packages = db.relationship("Package", secondary=CollectionPackage.__table__, backref="collections")
|
packages = db.relationship("Package", secondary=CollectionPackage.__table__, backref="collections")
|
||||||
items = db.relationship("CollectionPackage", back_populates="collection", order_by=db.asc("created_at"),
|
items = db.relationship("CollectionPackage", back_populates="collection", order_by=db.asc("order"),
|
||||||
cascade="all, delete, delete-orphan")
|
cascade="all, delete, delete-orphan")
|
||||||
|
|
||||||
collection_name_valid = db.CheckConstraint("name ~* '^[a-z0-9_]+$' AND name != '_game'")
|
collection_name_valid = db.CheckConstraint("name ~* '^[a-z0-9_]+$' AND name != '_game'")
|
||||||
|
@ -2,6 +2,18 @@
|
|||||||
// @license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3-or-Later
|
// @license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3-or-Later
|
||||||
|
|
||||||
|
|
||||||
|
function updateOrder() {
|
||||||
|
const elements = [...document.querySelector(".sortable").children];
|
||||||
|
const ids = elements
|
||||||
|
.filter(x => !x.classList.contains("d-none"))
|
||||||
|
.map(x => x.dataset.id)
|
||||||
|
.filter(x => x);
|
||||||
|
|
||||||
|
console.log(ids);
|
||||||
|
document.querySelector("input[name='order']").value = ids.join(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function removePackage(card) {
|
function removePackage(card) {
|
||||||
const message = document.getElementById("confirm_delete").innerText.trim();
|
const message = document.getElementById("confirm_delete").innerText.trim();
|
||||||
const title = card.querySelector("h5 a").innerText.trim();
|
const title = card.querySelector("h5 a").innerText.trim();
|
||||||
@ -12,6 +24,7 @@ function removePackage(card) {
|
|||||||
card.querySelector("input[name^=package_removed]").value = "1";
|
card.querySelector("input[name^=package_removed]").value = "1";
|
||||||
card.classList.add("d-none");
|
card.classList.add("d-none");
|
||||||
onPackageQueryUpdate();
|
onPackageQueryUpdate();
|
||||||
|
updateOrder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -26,6 +39,7 @@ function restorePackage(id) {
|
|||||||
card.querySelector("input[name^=package_removed]").value = "0";
|
card.querySelector("input[name^=package_removed]").value = "0";
|
||||||
card.scrollIntoView();
|
card.scrollIntoView();
|
||||||
onPackageQueryUpdate();
|
onPackageQueryUpdate();
|
||||||
|
updateOrder();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +73,7 @@ function addPackage(pkg) {
|
|||||||
const url = `/packages/${id}/`;
|
const url = `/packages/${id}/`;
|
||||||
const temp = document.createElement("div");
|
const temp = document.createElement("div");
|
||||||
temp.innerHTML = `
|
temp.innerHTML = `
|
||||||
<article class="card my-3">
|
<article class="card my-3" data-id="${escapeHtml(id)}">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<button class="btn btn-sm btn-danger remove-package float-right" type="button" aria-label="Remove">
|
<button class="btn btn-sm btn-danger remove-package float-right" type="button" aria-label="Remove">
|
||||||
<i class="fas fa-trash"></i>
|
<i class="fas fa-trash"></i>
|
||||||
@ -90,6 +104,8 @@ function addPackage(pkg) {
|
|||||||
|
|
||||||
const button = card.querySelector(".btn-danger");
|
const button = card.querySelector(".btn-danger");
|
||||||
button.addEventListener("click", () => removePackage(card));
|
button.addEventListener("click", () => removePackage(card));
|
||||||
|
|
||||||
|
updateOrder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -169,4 +185,9 @@ window.onload = () => {
|
|||||||
addPackageQuery.value = "";
|
addPackageQuery.value = "";
|
||||||
addPackageQuery.classList.remove("d-none");
|
addPackageQuery.classList.remove("d-none");
|
||||||
addPackageQuery.addEventListener("input", onPackageQueryUpdate);
|
addPackageQuery.addEventListener("input", onPackageQueryUpdate);
|
||||||
|
|
||||||
|
updateOrder();
|
||||||
|
$(".sortable").sortable({
|
||||||
|
update: updateOrder,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block scriptextra %}
|
{% block scriptextra %}
|
||||||
<script src="/static/collection_editor.js?v=4"></script>
|
<script src="/static/libs/jquery-ui.min.js"></script>
|
||||||
|
<script src="/static/collection_editor.js?v=5"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
@ -45,30 +46,38 @@
|
|||||||
</p>
|
</p>
|
||||||
<div id="add_package_results" class="list-group"></div>
|
<div id="add_package_results" class="list-group"></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="package_list">
|
<div id="package_list" class="sortable">
|
||||||
{% for item in collection.items %}
|
{% for item in collection.items %}
|
||||||
{% set package = item.package %}
|
{% set package = item.package %}
|
||||||
<article class="card my-3">
|
<article class="card my-3" data-id="{{ package.get_id() }}">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<button class="btn btn-sm btn-danger remove-package float-right"
|
<div class="row">
|
||||||
type="button" aria-label="{{ _('Remove') }}">
|
<div class="col-auto text-muted pr-2">
|
||||||
<i class="fas fa-trash"></i>
|
<i class="fas fa-bars"></i>
|
||||||
</button>
|
</div>
|
||||||
<h5>
|
<div class="col">
|
||||||
<a href="{{ package.get_url('packages.view') }}" target="_blank">
|
<button class="btn btn-sm btn-danger remove-package float-right"
|
||||||
{{ _("%(title)s by %(author)s", title=package.title, author=package.author.display_name) }}
|
type="button" aria-label="{{ _('Remove') }}">
|
||||||
</a>
|
<i class="fas fa-trash"></i>
|
||||||
</h5>
|
</button>
|
||||||
<p class="text-muted">
|
<h5>
|
||||||
{{ package.short_desc }}
|
<a href="{{ package.get_url('packages.view') }}" target="_blank">
|
||||||
</p>
|
{{ _("%(title)s by %(author)s", title=package.title, author=package.author.display_name) }}
|
||||||
{{ render_field(form.descriptions[loop.index - 1], hint=_("You can replace the description with your own")) }}
|
</a>
|
||||||
{{ form.package_ids[loop.index - 1]() }}
|
</h5>
|
||||||
{{ form.package_removed[loop.index - 1]() }}
|
<p class="text-muted">
|
||||||
|
{{ package.short_desc }}
|
||||||
|
</p>
|
||||||
|
{{ render_field(form.descriptions[loop.index - 1], hint=_("You can replace the description with your own")) }}
|
||||||
|
{{ form.package_ids[loop.index - 1]() }}
|
||||||
|
{{ form.package_removed[loop.index - 1]() }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
{{ form.order() }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="mt-5">
|
<div class="mt-5">
|
||||||
|
Loading…
Reference in New Issue
Block a user