add: product thumbnails ui

This commit is contained in:
trisua 2025-08-10 00:17:21 -04:00
parent 815e730fc0
commit 7a31dcbd9b
6 changed files with 111 additions and 12 deletions

View file

@ -349,3 +349,4 @@ version = "1.0.0"
"economy:label.snippet_data" = "Snippet data"
"economy:action.apply" = "Apply"
"economy:action.unapply" = "Unapply"
"economy:label.thumbnails" = "Thumbnails"

View file

@ -201,8 +201,7 @@ p {
.name {
max-width: 250px;
overflow: hidden;
/* overflow-wrap: break-word; */
overflow-wrap: anywhere;
white-space: nowrap;
text-overflow: ellipsis;
}

View file

@ -476,8 +476,7 @@
(text "{{ text \"communities:action.create\" }}"))
(span
("class" "fade")
(text "Emojis can be a maximum of 256 KiB, or 512x512px (width x
height)."))))
(text "Emojis can be a maximum of 256 KiB."))))
(text "{% for emoji in emojis %}")
(div
("class" "card secondary flex flex_wrap gap_2 items_center justify_between")

View file

@ -87,13 +87,13 @@
(span
(text "{{ dislikes }}"))
(text "{%- endif %}"))
(text "{%- endif %} {%- endmacro %} {% macro full_username(user, wrap=true) -%} {% if user and user.username -%}")
(text "{%- endif %} {%- endmacro %} {% macro full_username(user, wrap=true, max_width=\"180px\") -%} {% if user and user.username -%}")
(div
("class" "flex {% if wrap -%} flex_wrap {%- endif %} items_center")
(a
("href" "/@{{ user.username }}")
("class" "flush flex gap_1")
("style" "font-weight: 600")
("class" "name flush flex gap_1")
("style" "font-weight: 600; max-width: {{ max_width }}")
("target" "_top")
(text "{% if user.settings.private_profile -%}")
(span
@ -384,7 +384,7 @@
(text "{{ self::avatar(username=owner.username, size=\"24px\", selector_type=\"username\") }}"))
(text "{%- endif %}")
(span
("class" "name")
; ("class" "name")
(text "{{ self::full_username(user=owner) }}"))
(text "{{ self::post_info(post=post, community=community) }}")
(text "{% if post.context.is_pinned or post.context.is_profile_pinned -%} {{ icon \"pin\" }} {%- endif %}"))
@ -465,14 +465,15 @@
(text "{% if community and show_community and community.id != config.town_square or question %}"))
(text "{%- endif %} {%- endmacro %}")
(text "{% macro post_media(upload_ids) -%} {% if upload_ids|length > 0 -%}")
(text "{% macro post_media(upload_ids, custom_click=false) -%} {% if upload_ids|length > 0 -%}")
(div
("class" "media_gallery gap_2")
(text "{% for upload in upload_ids %}")
(img
("src" "/api/v1/uploads/{{ upload }}")
("data-upload-id" "{{ upload }}")
("alt" "Image upload")
("onclick" "trigger('ui::lightbox_open', ['/api/v1/uploads/{{ upload }}'])"))
("onclick" "{% if custom_click -%} {{ custom_click }} {%- else -%} trigger('ui::lightbox_open', ['/api/v1/uploads/{{ upload }}']) {%- endif %}"))
(text "{% endfor %}"))
(text "{%- endif %} {%- endmacro %} {% macro notification(notification) -%}")
(div
@ -623,7 +624,7 @@
(div
("class" "flex items_center")
(b
(text "{{ self::username(user=user) }}"))
(text "{{ self::full_username(user=user, max_width=\"calc(100% - 42px - var(--pad-4))\") }}"))
(text "{{ self::online_indicator(user=user) }}"))))
(text "{%- endmacro %} {% macro pagination(page=0, items=0, key=\"\", value=\"\") -%}")

View file

@ -4,6 +4,23 @@
(text "{% endblock %} {% block body %} {{ macros::nav(selected=\"\") }}")
(main
("class" "flex flex_col gap_2")
(div
("class" "card_nest")
(div
("class" "card small flex items_center gap_2")
(icon (text "images"))
(b
(str (text "economy:label.thumbnails"))))
(div
("class" "card flex flex_col gap_2")
(text "{{ components::post_media(upload_ids=product.uploads.thumbnails, custom_click=\"remove_thumbnail(event.target)\") }}")
(text "{% if product.uploads.thumbnails|length < 4 -%}")
(button
("onclick" "add_thumbnail()")
(icon (text "plus"))
(str (text "communities:label.upload")))
(text "{%- endif %}")))
(div
("class" "card_nest")
(div
@ -220,7 +237,88 @@
(str (text "general:action.delete")))))
(script
(text "async function update_title_from_form(e) {
(text "async function add_thumbnail() {
await trigger(\"atto::debounce\", [\"products::update\"]);
const picker = document.createElement(\"input\");
picker.type = \"file\";
picker.accept = \"image/*\";
document.body.appendChild(picker);
picker.click();
picker.addEventListener(\"change\", () => {
// create body
const body = new FormData();
for (const file of picker.files) {
body.append(file.name, file);
}
body.append(
\"body\",
JSON.stringify({
target: \"Thumbnails\"
}),
);
// ...
picker.remove();
fetch(\"/api/v1/products/{{ product.id }}/uploads\", {
method: \"POST\",
body,
})
.then((res) => res.json())
.then(async (res) => {
trigger(\"atto::toast\", [
res.ok ? \"success\" : \"error\",
res.message,
]);
if (res.ok) {
setTimeout(() => {
window.location.reload();
}, 100);
}
});
});
}
async function remove_thumbnail(target) {
await trigger(\"atto::debounce\", [\"products::update\"]);
if (
!(await trigger(\"atto::confirm\", [
\"Are you sure you would like to do this?\",
]))
) {
return;
}
fetch(\"/api/v1/products/{{ product.id }}/uploads/thumbnails\", {
method: \"DELETE\",
headers: {
\"Content-Type\": \"application/json\",
},
body: JSON.stringify({
idx: Array.from(target.parentElement.children).findIndex((x) => x.getAttribute(\"data-upload-id\") === target.getAttribute(\"data-upload-id\")),
}),
})
.then((res) => res.json())
.then(async (res) => {
trigger(\"atto::toast\", [
res.ok ? \"success\" : \"error\",
res.message,
]);
if (res.ok) {
setTimeout(() => {
window.location.reload();
}, 100);
}
});
}
async function update_title_from_form(e) {
e.preventDefault();
await trigger(\"atto::debounce\", [\"products::update\"]);

View file

@ -4,6 +4,7 @@
(text "{% endblock %} {% block body %} {{ macros::nav(selected=\"\") }}")
(main
("class" "flex flex_col gap_2")
(text "{{ components::post_media(upload_ids=product.uploads.thumbnails) }}")
(div
("class" "card flex flex_col gap_2")
(h3