Add contained items tree view

This commit is contained in:
2025-07-19 03:28:56 +03:00
parent afc439e245
commit 0ab5fc4570
2 changed files with 112 additions and 0 deletions

View File

@@ -216,6 +216,8 @@ def save_inventory_item(item_id=None, **_):
d = {} d = {}
form.populate_dict(d) form.populate_dict(d)
d['tags'] = list(set(request.form.getlist('tags[]'))) d['tags'] = list(set(request.form.getlist('tags[]')))
if d.get('location'):
d['location_code'] = render_location_link(d['location'])
custom_errors = {} custom_errors = {}
try: try:
if item_id: if item_id:
@@ -256,6 +258,16 @@ def save_inventory_item(item_id=None, **_):
return render_template("inventory_edit.html", **locals()) return render_template("inventory_edit.html", **locals())
return redirect("/m/inventory/%s/view" % item_id) return redirect("/m/inventory/%s/view" % item_id)
def render_location_link(location: str):
if location == "":
return
linkstart = location.find("k6.ee/")
if linkstart == -1:
return
return location[linkstart:].split(" ", 1)[0].split("/", 1)[1]
def is_image_ext(filename): def is_image_ext(filename):
return '.' in filename and \ return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ["jpg", "jpeg"] filename.rsplit('.', 1)[1].lower() in ["jpg", "jpeg"]
@@ -598,3 +610,18 @@ def view_inventory_vacate(item_id):
}, },
}) })
return redirect("/m/inventory/%s/view" % item_id) return redirect("/m/inventory/%s/view" % item_id)
@page_inventory.route("/m/inventory/contains", methods=["GET"])
@login_required(groups=["k-space:inventory:audit"])
def get_contains():
slug = request.args.get("slug")
if not slug:
return []
return list(db.inventory.find({
"location_code": slug
}, {
"_id": 0,
"shortener.slug": 1,
"name": 1
}))

View File

@@ -136,6 +136,15 @@
{% endif %} {% endif %}
</div> </div>
<div class="browser-default" id="contains">
<h3>Contains</h3>
<ul class="browser-default">
<li class="closed browser-default" data-name="{{ item.name }}" data-slug="{{ item.get("shortener", {}).get("slug") }}">
This item
</li>
</ul>
</div>
</div> </div>
<script> <script>
@@ -170,6 +179,82 @@ $(function() {
} }
}); });
{% endif %} {% endif %}
function slugLink(slug) {
if (!slug) {
return "";
}
var href = "k6.ee/" + slug;
return $("<a/>").attr("href", "https://" + href).text(" " + href);
}
function expandLocation(e) {
e.stopPropagation();
var cur = $(this);
var slug = cur.data("slug");
var name = cur.data("name");
if (cur.hasClass("empty")) {
return;
}
if (!cur.hasClass("closed")) {
cur.empty();
cur.text(name);
cur.append(slugLink(slug));
cur.addClass("closed");
return;
}
var expand = $("<ul/>").data("slug", slug);
expand.attr("class", "browser-default");
$.get("/m/inventory/contains", { slug }, function(data) {
cur.removeClass("closed");
if (!data.length) {
cur.addClass("empty");
return;
}
$.each(data, function(k, v) {
var inner = $("<li/>").data("slug", v.shortener.slug);
inner.text(v.name);
inner.data("name", v.name);
inner.on("click", expandLocation);
inner.attr("class", "closed browser-default");
inner.append(slugLink(v.shortener.slug));
expand.append(inner);
});
cur.html(expand);
cur.prepend(slugLink(slug));
cur.prepend(name);
});
}
var contains = $("div#contains li");
contains.on("click", expandLocation);
}); });
</script> </script>
<style>
div#contains {
padding-bottom: 6em;
}
div#contains ul {
list-style: none;
padding: 0;
margin: 0;
}
div#contains li {
padding-left: 16px;
}
div#contains li::before {
content: "▼";
padding-right: 8px;
}
div#contains li.closed::before {
content: "►";
}
div#contains li.empty::before {
content: "";
}
</style>
{% endblock %} {% endblock %}