diff --git a/backend/internal/controller/app_images_controller.go b/backend/internal/controller/app_images_controller.go index ec3215aa..2230b6f0 100644 --- a/backend/internal/controller/app_images_controller.go +++ b/backend/internal/controller/app_images_controller.go @@ -2,7 +2,9 @@ package controller import ( "net/http" + "slices" "strconv" + "strings" "time" "github.com/gin-gonic/gin" @@ -34,6 +36,7 @@ func NewAppImagesController( group.PUT("/application-images/favicon", authMiddleware.Add(), controller.updateFaviconHandler) group.PUT("/application-images/default-profile-picture", authMiddleware.Add(), controller.updateDefaultProfilePicture) + group.DELETE("/application-images/background", authMiddleware.Add(), controller.deleteBackgroundImageHandler) group.DELETE("/application-images/default-profile-picture", authMiddleware.Add(), controller.deleteDefaultProfilePicture) } @@ -192,12 +195,27 @@ func (c *AppImagesController) updateBackgroundImageHandler(ctx *gin.Context) { ctx.Status(http.StatusNoContent) } +// deleteBackgroundImageHandler godoc +// @Summary Delete background image +// @Description Delete the application background image +// @Tags Application Images +// @Success 204 "No Content" +// @Router /api/application-images/background [delete] +func (c *AppImagesController) deleteBackgroundImageHandler(ctx *gin.Context) { + if err := c.appImagesService.DeleteImage(ctx.Request.Context(), "background"); err != nil { + _ = ctx.Error(err) + return + } + + ctx.Status(http.StatusNoContent) +} + // updateFaviconHandler godoc // @Summary Update favicon // @Description Update the application favicon // @Tags Application Images // @Accept multipart/form-data -// @Param file formData file true "Favicon file (.ico)" +// @Param file formData file true "Favicon file (.svg/.png/.ico)" // @Success 204 "No Content" // @Router /api/application-images/favicon [put] func (c *AppImagesController) updateFaviconHandler(ctx *gin.Context) { @@ -208,8 +226,9 @@ func (c *AppImagesController) updateFaviconHandler(ctx *gin.Context) { } fileType := utils.GetFileExtension(file.Filename) - if fileType != "ico" { - _ = ctx.Error(&common.WrongFileTypeError{ExpectedFileType: ".ico"}) + mimeType := utils.GetImageMimeType(strings.ToLower(fileType)) + if !slices.Contains([]string{"image/svg+xml", "image/png", "image/x-icon"}, mimeType) { + _ = ctx.Error(&common.WrongFileTypeError{ExpectedFileType: ".svg or .png or .ico"}) return } diff --git a/frontend/src/lib/components/login-wrapper.svelte b/frontend/src/lib/components/login-wrapper.svelte index 60683044..f8671866 100644 --- a/frontend/src/lib/components/login-wrapper.svelte +++ b/frontend/src/lib/components/login-wrapper.svelte @@ -1,3 +1,9 @@ + + {#if isDesktop.current} -
+
@@ -69,16 +94,18 @@
- -
- {m.login_background()} -
+ {#if !imageError} + +
+ {m.login_background()} +
+ {/if}
{:else}
{ + await this.api.delete(`/application-images/background`); + cachedBackgroundImage.bustCache(); + }; + deleteDefaultProfilePicture = async () => { await this.api.delete('/application-images/default-profile-picture'); cachedDefaultProfilePicture.bustCache(); diff --git a/frontend/src/routes/settings/admin/application-configuration/+page.svelte b/frontend/src/routes/settings/admin/application-configuration/+page.svelte index a2244e70..c4c592ba 100644 --- a/frontend/src/routes/settings/admin/application-configuration/+page.svelte +++ b/frontend/src/routes/settings/admin/application-configuration/+page.svelte @@ -44,7 +44,7 @@ logoDark: File | undefined, logoEmail: File | undefined, defaultProfilePicture: File | null | undefined, - backgroundImage: File | undefined, + backgroundImage: File | null | undefined, favicon: File | undefined ) { const faviconPromise = favicon ? appConfigService.updateFavicon(favicon) : Promise.resolve(); @@ -68,9 +68,12 @@ ? appConfigService.updateDefaultProfilePicture(defaultProfilePicture) : Promise.resolve(); - const backgroundImagePromise = backgroundImage - ? appConfigService.updateBackgroundImage(backgroundImage) - : Promise.resolve(); + const backgroundImagePromise = + backgroundImage === null + ? appConfigService.deleteBackgroundImage() + : backgroundImage + ? appConfigService.updateBackgroundImage(backgroundImage) + : Promise.resolve(); await Promise.all([ lightLogoPromise, diff --git a/frontend/src/routes/settings/admin/application-configuration/update-application-images.svelte b/frontend/src/routes/settings/admin/application-configuration/update-application-images.svelte index e59795ee..df8e8a94 100644 --- a/frontend/src/routes/settings/admin/application-configuration/update-application-images.svelte +++ b/frontend/src/routes/settings/admin/application-configuration/update-application-images.svelte @@ -17,7 +17,7 @@ logoDark: File | undefined, logoEmail: File | undefined, defaultProfilePicture: File | null | undefined, - backgroundImage: File | undefined, + backgroundImage: File | null | undefined, favicon: File | undefined ) => void; } = $props(); @@ -26,10 +26,11 @@ let logoDark = $state(); let logoEmail = $state(); let defaultProfilePicture = $state(); - let backgroundImage = $state(); + let backgroundImage = $state(); let favicon = $state(); let defaultProfilePictureSet = $state(true); + let backgroundImageSet = $state(true);
@@ -39,7 +40,7 @@ label={m.favicon()} bind:image={favicon} imageURL="/api/application-images/favicon" - accept="image/x-icon" + accept="image/svg+xml, image/png, image/x-icon" />