diff --git a/com.woltlab.wcf/fileDelete.xml b/com.woltlab.wcf/fileDelete.xml
index 10520b1ddc4..acb51b66fde 100644
--- a/com.woltlab.wcf/fileDelete.xml
+++ b/com.woltlab.wcf/fileDelete.xml
@@ -62,5 +62,6 @@
lib/system/upload/AvatarUploadFileValidationStrategy.class.php
lib/system/upload/UserCoverPhotoUploadFileSaveStrategy.class.php
lib/system/upload/UserCoverPhotoUploadFileValidationStrategy.class.php
+ lib/system/upload/TrophyImageUploadFileValidationStrategy.class.php
diff --git a/com.woltlab.wcf/objectType.xml b/com.woltlab.wcf/objectType.xml
index e6cf1f372f7..f08cd2d53cd 100644
--- a/com.woltlab.wcf/objectType.xml
+++ b/com.woltlab.wcf/objectType.xml
@@ -1767,6 +1767,11 @@
com.woltlab.wcf.file
wcf\system\file\processor\UnfurlUrlImageFileProcessor
+
+ com.woltlab.wcf.trophy
+ com.woltlab.wcf.file
+ wcf\system\file\processor\TrophyFileProcessor
+
com.woltlab.wcf.page.controller
diff --git a/com.woltlab.wcf/package.xml b/com.woltlab.wcf/package.xml
index 79930be5e66..b3281619196 100644
--- a/com.woltlab.wcf/package.xml
+++ b/com.woltlab.wcf/package.xml
@@ -55,5 +55,6 @@
acp/database/update_com.woltlab.wcf_6.3_step1.php
acp/update_com.woltlab.wcf_6.3_userGroupAssignment.php
acp/update_com.woltlab.wcf_6.3_notice.php
+ acp/update_com.woltlab.wcf_6.3_trophy.php
-->
diff --git a/com.woltlab.wcf/templates/shared_colorFormField.tpl b/com.woltlab.wcf/templates/shared_colorFormField.tpl
index 94b941f6429..c3b4451ccd4 100644
--- a/com.woltlab.wcf/templates/shared_colorFormField.tpl
+++ b/com.woltlab.wcf/templates/shared_colorFormField.tpl
@@ -3,9 +3,9 @@
getValue()} style="background-color: {$field->getValue()}"{/if}>
{else}
-
- getValue()} style="background-color: {$field->getValue()}"{/if}>
-
+
getPrefixedId()}" {*
*}name="{$field->getPrefixedId()}" {*
diff --git a/com.woltlab.wcf/templates/shared_conditionFormContainer.tpl b/com.woltlab.wcf/templates/shared_conditionFormContainer.tpl
index bf7fabb2f1f..941edf0fef8 100644
--- a/com.woltlab.wcf/templates/shared_conditionFormContainer.tpl
+++ b/com.woltlab.wcf/templates/shared_conditionFormContainer.tpl
@@ -21,6 +21,10 @@
+
+ {if $container->isRequired() && $container->isEmpty()}
+ {lang}wcf.global.form.error.empty{/lang}
+ {/if}
{include file='shared_formContainerDependencies'}
diff --git a/com.woltlab.wcf/templates/shared_trophyImage.tpl b/com.woltlab.wcf/templates/shared_trophyImage.tpl
index 22d9ebb7840..798a77114c9 100644
--- a/com.woltlab.wcf/templates/shared_trophyImage.tpl
+++ b/com.woltlab.wcf/templates/shared_trophyImage.tpl
@@ -1,5 +1,5 @@
getTitle()}"{/if}
diff --git a/ts/WoltLabSuite/Core/Component/Icon/Badge.ts b/ts/WoltLabSuite/Core/Component/Icon/Badge.ts
new file mode 100644
index 00000000000..4fa17d3e0b7
--- /dev/null
+++ b/ts/WoltLabSuite/Core/Component/Icon/Badge.ts
@@ -0,0 +1,31 @@
+/**
+ * Handles the display of an icon badge with customizable colors.
+ *
+ * @author Olaf Braun
+ * @copyright 2001-2025 WoltLab GmbH
+ * @license GNU Lesser General Public License
+ * @since 6.3
+ */
+
+export function setup(iconFieldId: string, colorFieldId: string, backgroundColorFieldId: string) {
+ const container = document.getElementById(`${iconFieldId}_icon`)!;
+ container.classList.add("iconBadge");
+
+ if (colorFieldId !== "") {
+ const colorInput = document.getElementById(colorFieldId) as HTMLInputElement;
+ colorInput.addEventListener("color-picker:submit", () => {
+ container.style.setProperty("color", colorInput.value);
+ });
+
+ container.style.setProperty("color", colorInput.value);
+ }
+
+ if (backgroundColorFieldId !== "") {
+ const backgroundColorInput = document.getElementById(backgroundColorFieldId) as HTMLInputElement;
+ backgroundColorInput.addEventListener("color-picker:submit", () => {
+ container.style.setProperty("background-color", backgroundColorInput.value);
+ });
+
+ container.style.setProperty("background-color", backgroundColorInput.value);
+ }
+}
diff --git a/ts/WoltLabSuite/Core/Ui/Color/Picker.ts b/ts/WoltLabSuite/Core/Ui/Color/Picker.ts
index e42372471eb..dfdfb36ef19 100644
--- a/ts/WoltLabSuite/Core/Ui/Color/Picker.ts
+++ b/ts/WoltLabSuite/Core/Ui/Color/Picker.ts
@@ -131,10 +131,10 @@ class UiColorPicker implements DialogCallbackObject {
${Language.get("wcf.style.colorPicker.new")}
-
+
-
+
${Language.get("wcf.style.colorPicker.current")}
@@ -356,13 +356,13 @@ class UiColorPicker implements DialogCallbackObject {
this.oldColor!.style.backgroundColor = colorString;
this.input.value = colorString;
- if (!(this.element instanceof HTMLButtonElement)) {
- const span = this.element.querySelector("span");
- if (span) {
- span.style.backgroundColor = colorString;
- } else {
- this.element.style.backgroundColor = colorString;
- }
+ const event = new CustomEvent("color-picker:submit");
+ this.input.dispatchEvent(event);
+
+ const span = this.element.querySelector("span")
+ if (span !== null) {
+ span.classList.add("colorPickerButton__color");
+ span.style.setProperty("background-color", colorString);
}
UiDialog.close(this);
diff --git a/wcfsetup/install/files/acp/database/update_com.woltlab.wcf_6.3_step1.php b/wcfsetup/install/files/acp/database/update_com.woltlab.wcf_6.3_step1.php
index cf7a3517cd6..eca3fbe033c 100644
--- a/wcfsetup/install/files/acp/database/update_com.woltlab.wcf_6.3_step1.php
+++ b/wcfsetup/install/files/acp/database/update_com.woltlab.wcf_6.3_step1.php
@@ -9,7 +9,9 @@
*/
use wcf\system\database\table\column\DefaultFalseBooleanDatabaseTableColumn;
+use wcf\system\database\table\column\IntDatabaseTableColumn;
use wcf\system\database\table\column\MediumtextDatabaseTableColumn;
+use wcf\system\database\table\index\DatabaseTableForeignKey;
use wcf\system\database\table\PartialDatabaseTable;
return [
@@ -23,4 +25,17 @@
MediumtextDatabaseTableColumn::create('conditions'),
DefaultFalseBooleanDatabaseTableColumn::create('isLegacy'),
]),
+ PartialDatabaseTable::create('wcf1_trophy')
+ ->columns([
+ MediumtextDatabaseTableColumn::create('conditions'),
+ DefaultFalseBooleanDatabaseTableColumn::create('isLegacy'),
+ IntDatabaseTableColumn::create('imageFileID'),
+ ])
+ ->foreignKeys([
+ DatabaseTableForeignKey::create()
+ ->columns(['imageFileID'])
+ ->referencedTable('wcf1_file')
+ ->referencedColumns(['fileID'])
+ ->onDelete('SET NULL'),
+ ]),
];
diff --git a/wcfsetup/install/files/acp/templates/trophyAdd.tpl b/wcfsetup/install/files/acp/templates/trophyAdd.tpl
index 7188406b92a..2d5344d4d48 100644
--- a/wcfsetup/install/files/acp/templates/trophyAdd.tpl
+++ b/wcfsetup/install/files/acp/templates/trophyAdd.tpl
@@ -1,22 +1,5 @@
{include file='header' pageTitle='wcf.acp.menu.link.trophy.'|concat:$action}
-{include file='shared_colorPickerJavaScript'}
-{include file='shared_fontAwesomeJavaScript'}
-
-
-