From ae9b4dc111be15d9c1c40d3b1f244aad11ef623b Mon Sep 17 00:00:00 2001 From: Luca Stancapiano Date: Sat, 24 Oct 2026 09:42:11 +0200 Subject: [PATCH] fix(web): save an app that has no cover image Saving stopped when the image path was missing. Omit the empty path so the existing initial-letter placeholder remains. --- src/confighttp.cpp | 11 +++++++++++ src_assets/common/assets/web/Apps.vue | 7 +++++-- tests/web/Apps.test.js | 13 ++++++++++++- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index edf1c5758a1..e94e9daafc1 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -1199,6 +1199,17 @@ namespace confighttp { input_tree.erase("detached"); } + std::string image_path; + if (input_tree.contains("image-path") && input_tree["image-path"].is_string()) { + image_path = input_tree["image-path"].get(); + } + boost::trim(image_path); + if (image_path.empty()) { + input_tree.erase("image-path"); + } else { + input_tree["image-path"] = image_path; + } + auto &apps_node = file_tree["apps"]; int index = input_tree["index"].get(); // this will intentionally cause an exception if the provided value is the wrong type diff --git a/src_assets/common/assets/web/Apps.vue b/src_assets/common/assets/web/Apps.vue index 1465eb817e9..5f950a74b06 100644 --- a/src_assets/common/assets/web/Apps.vue +++ b/src_assets/common/assets/web/Apps.vue @@ -1024,10 +1024,13 @@ }, save() { this.editFormError = ""; - this.editForm["image-path"] = this.editForm["image-path"].toString().replaceAll('"', ''); + const currentImagePath = this.editForm["image-path"] == null ? "" : String(this.editForm["image-path"]).trim(); + this.editForm["image-path"] = currentImagePath.replaceAll('"', ''); const imagePath = this.editForm["image-path"]; - if (imagePath && !imagePath.toLowerCase().endsWith('.png')) { + if (!imagePath) { + delete this.editForm["image-path"]; + } else if (!imagePath.toLowerCase().endsWith('.png')) { this.editFormError = this.$t('file_browser.error_invalid_extension', { extensions: '.png' }); const modalBody = this.$refs.editModal.querySelector('.modal-body'); if (modalBody) modalBody.scrollTop = 0; diff --git a/tests/web/Apps.test.js b/tests/web/Apps.test.js index cd9ed6c2840..a5db635ab15 100644 --- a/tests/web/Apps.test.js +++ b/tests/web/Apps.test.js @@ -154,12 +154,23 @@ describe('save – cover image validation', () => { ) }) - it('submits when the image path is empty', () => { + it('submits when the image path is empty and leaves the letter cover as the default', () => { const ctx = saveContext('') Apps.methods.save.call(ctx) expect(ctx.editFormError).toBe('') + expect(ctx.editForm['image-path']).toBeUndefined() + expect(apiFetch).toHaveBeenCalledOnce() + }) + + it('submits when the image path is missing', () => { + const ctx = saveContext(null) + + expect(() => Apps.methods.save.call(ctx)).not.toThrow() + + expect(ctx.editFormError).toBe('') + expect(ctx.editForm['image-path']).toBeUndefined() expect(apiFetch).toHaveBeenCalledOnce() })