diff --git a/app/assets/javascripts/admin/addon/components/emoji-value-list.hbs b/app/assets/javascripts/admin/addon/components/emoji-value-list.hbs
index 56c883807fc..1be68d11178 100644
--- a/app/assets/javascripts/admin/addon/components/emoji-value-list.hbs
+++ b/app/assets/javascripts/admin/addon/components/emoji-value-list.hbs
@@ -56,6 +56,4 @@
@isEditorFocused={{this.isEditorFocused}}
@emojiSelected={{this.emojiSelected}}
@onEmojiPickerClose={{this.closeEmojiPicker}}
-/>
-
-
\ No newline at end of file
+/>
\ No newline at end of file
diff --git a/app/assets/javascripts/admin/addon/components/emoji-value-list.js b/app/assets/javascripts/admin/addon/components/emoji-value-list.js
index b788ecefc00..0166c48ed07 100644
--- a/app/assets/javascripts/admin/addon/components/emoji-value-list.js
+++ b/app/assets/javascripts/admin/addon/components/emoji-value-list.js
@@ -10,7 +10,6 @@ import I18n from "discourse-i18n";
@classNameBindings(":value-list", ":emoji-list")
export default class EmojiValueList extends Component {
values = null;
- validationMessage = null;
emojiPickerIsActive = false;
isEditorFocused = false;
@@ -137,16 +136,14 @@ export default class EmojiValueList extends Component {
}
_validateInput(input) {
- this.set("validationMessage", null);
-
if (!emojiUrlFor(input)) {
- this.set(
- "validationMessage",
+ this.setValidationMessage(
I18n.t("admin.site_settings.emoji_list.invalid_input")
);
return false;
}
+ this.setValidationMessage(null);
return true;
}
diff --git a/app/assets/javascripts/admin/addon/components/file-size-input.gjs b/app/assets/javascripts/admin/addon/components/file-size-input.gjs
index 77df855b90c..b4c144d2b2f 100644
--- a/app/assets/javascripts/admin/addon/components/file-size-input.gjs
+++ b/app/assets/javascripts/admin/addon/components/file-size-input.gjs
@@ -2,9 +2,6 @@ import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { on } from "@ember/modifier";
import { action } from "@ember/object";
-import didInsert from "@ember/render-modifiers/modifiers/did-insert";
-import didUpdate from "@ember/render-modifiers/modifiers/did-update";
-import TextField from "discourse/components/text-field";
import { allowOnlyNumericInput } from "discourse/lib/utilities";
import I18n from "discourse-i18n";
import ComboBox from "select-kit/components/combo-box";
@@ -14,30 +11,34 @@ const UNIT_MB = "mb";
const UNIT_GB = "gb";
export default class FileSizeInput extends Component {
- @tracked fileSizeUnit;
- @tracked sizeValue;
- @tracked pendingSizeValue;
- @tracked pendingFileSizeUnit;
+ @tracked unit;
- constructor(owner, args) {
- super(owner, args);
- this.originalSizeKB = this.args.sizeValueKB;
- this.sizeValue = this.args.sizeValueKB;
+ constructor() {
+ super(...arguments);
- this._defaultUnit();
+ const sizeInKB = this.args.sizeValueKB;
+ if (sizeInKB >= 1024 * 1024) {
+ this.unit = UNIT_GB;
+ } else if (sizeInKB >= 1024) {
+ this.unit = UNIT_MB;
+ } else {
+ this.unit = UNIT_KB;
+ }
}
- _defaultUnit() {
- this.fileSizeUnit = UNIT_KB;
- if (this.originalSizeKB <= 1024) {
- this.onFileSizeUnitChange(UNIT_KB);
- } else if (
- this.originalSizeKB > 1024 &&
- this.originalSizeKB <= 1024 * 1024
- ) {
- this.onFileSizeUnitChange(UNIT_MB);
- } else if (this.originalSizeKB > 1024 * 1024) {
- this.onFileSizeUnitChange(UNIT_GB);
+ get number() {
+ const sizeInKB = this.args.sizeValueKB;
+ if (!sizeInKB) {
+ return;
+ }
+ if (this.unit === UNIT_KB) {
+ return sizeInKB;
+ }
+ if (this.unit === UNIT_MB) {
+ return sizeInKB / 1024;
+ }
+ if (this.unit === UNIT_GB) {
+ return sizeInKB / 1024 / 1024;
}
}
@@ -55,95 +56,69 @@ export default class FileSizeInput extends Component {
}
@action
- handleFileSizeChange(value) {
- if (value !== "") {
- this.pendingSizeValue = value;
- this._onFileSizeChange(value);
- }
- }
+ handleFileSizeChange(event) {
+ const value = parseFloat(event.target.value);
- _onFileSizeChange(newSize) {
- let fileSizeKB;
- switch (this.fileSizeUnit) {
+ if (isNaN(value)) {
+ this.args.onChangeSize();
+ return;
+ }
+
+ let sizeInKB;
+ switch (this.unit) {
case "kb":
- fileSizeKB = newSize;
+ sizeInKB = value;
break;
case "mb":
- fileSizeKB = newSize * 1024;
+ sizeInKB = value * 1024;
break;
case "gb":
- fileSizeKB = newSize * 1024 * 1024;
+ sizeInKB = value * 1024 * 1024;
break;
}
- if (fileSizeKB > this.args.max) {
- this.args.updateValidationMessage(
+
+ this.args.onChangeSize(sizeInKB);
+
+ if (sizeInKB > this.args.max) {
+ this.args.setValidationMessage(
I18n.t("file_size_input.error.size_too_large", {
- provided_file_size: I18n.toHumanSize(fileSizeKB * 1024),
+ provided_file_size: I18n.toHumanSize(sizeInKB * 1024),
max_file_size: I18n.toHumanSize(this.args.max * 1024),
})
);
- // Removes the green save checkmark button
- this.args.onChangeSize(this.originalSizeKB);
+ } else if (sizeInKB < this.args.min) {
+ this.args.setValidationMessage(
+ I18n.t("file_size_input.error.size_too_small", {
+ provided_file_size: I18n.toHumanSize(sizeInKB * 1024),
+ min_file_size: I18n.toHumanSize(this.args.min * 1024),
+ })
+ );
} else {
- this.args.onChangeSize(fileSizeKB);
- this.args.updateValidationMessage(null);
+ this.args.setValidationMessage(null);
}
}
@action
onFileSizeUnitChange(newUnit) {
- if (this.fileSizeUnit === "kb" && newUnit === "kb") {
- this.pendingSizeValue = this.sizeValue;
- }
- if (this.fileSizeUnit === "kb" && newUnit === "mb") {
- this.pendingSizeValue = this.sizeValue / 1024;
- }
- if (this.fileSizeUnit === "kb" && newUnit === "gb") {
- this.pendingSizeValue = this.sizeValue / 1024 / 1024;
- }
- if (this.fileSizeUnit === "mb" && newUnit === "kb") {
- this.pendingSizeValue = this.sizeValue * 1024;
- }
- if (this.fileSizeUnit === "mb" && newUnit === "gb") {
- this.pendingSizeValue = this.sizeValue / 1024;
- }
- if (this.fileSizeUnit === "gb" && newUnit === "mb") {
- this.pendingSizeValue = this.sizeValue * 1024;
- }
- if (this.fileSizeUnit === "gb" && newUnit === "kb") {
- this.pendingSizeValue = this.sizeValue * 1024 * 1024;
- }
- this.pendingFileSizeUnit = newUnit;
- }
-
- @action
- applySizeValueChanges() {
- this.sizeValue = this.pendingSizeValue;
- }
-
- @action
- applyUnitChanges() {
- this.fileSizeUnit = this.pendingFileSizeUnit;
+ this.unit = newUnit;
}
-
diff --git a/app/assets/javascripts/admin/addon/components/secret-value-list.hbs b/app/assets/javascripts/admin/addon/components/secret-value-list.hbs
index 67b9e460a5e..9203ebc14dd 100644
--- a/app/assets/javascripts/admin/addon/components/secret-value-list.hbs
+++ b/app/assets/javascripts/admin/addon/components/secret-value-list.hbs
@@ -40,6 +40,4 @@
@icon="plus"
class="add-value-btn btn-small"
/>
-
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/javascripts/admin/addon/components/secret-value-list.js b/app/assets/javascripts/admin/addon/components/secret-value-list.js
index ecd12a83049..1bc7f87c6d0 100644
--- a/app/assets/javascripts/admin/addon/components/secret-value-list.js
+++ b/app/assets/javascripts/admin/addon/components/secret-value-list.js
@@ -9,7 +9,6 @@ export default class SecretValueList extends Component {
inputDelimiter = null;
collection = null;
values = null;
- validationMessage = null;
didReceiveAttrs() {
super.didReceiveAttrs(...arguments);
@@ -57,16 +56,15 @@ export default class SecretValueList extends Component {
}
_checkInvalidInput(inputs) {
- this.set("validationMessage", null);
for (let input of inputs) {
if (isEmpty(input) || input.includes("|")) {
- this.set(
- "validationMessage",
+ this.setValidationMessage(
I18n.t("admin.site_settings.secret_list.invalid_input")
);
return true;
}
}
+ this.setValidationMessage(null);
}
_addValue(value, secret) {
diff --git a/app/assets/javascripts/admin/addon/components/site-setting.hbs b/app/assets/javascripts/admin/addon/components/site-setting.hbs
index bb8228fd44d..c8047733e6b 100644
--- a/app/assets/javascripts/admin/addon/components/site-setting.hbs
+++ b/app/assets/javascripts/admin/addon/components/site-setting.hbs
@@ -39,12 +39,16 @@
this.componentName
setting=this.setting
value=this.buffered.value
- validationMessage=this.validationMessage
preview=this.preview
isSecret=this.isSecret
allowAny=this.allowAny
changeValueCallback=this.changeValueCallback
+ setValidationMessage=this.setValidationMessage
}}
+
+ {{#if this.displayDescription}}
+
+ {{/if}}
{{/if}}
@@ -53,6 +57,7 @@
{{html-safe this.setting.description}}
-
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/category-list.gjs b/app/assets/javascripts/admin/addon/components/site-settings/category-list.gjs
index 01776dbfb74..d57972232a8 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/category-list.gjs
+++ b/app/assets/javascripts/admin/addon/components/site-settings/category-list.gjs
@@ -3,8 +3,6 @@ import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";
import didUpdate from "@ember/render-modifiers/modifiers/did-update";
import Category from "discourse/models/category";
-import SettingValidationMessage from "admin/components/setting-validation-message";
-import SiteSettingsDescription from "admin/components/site-settings/description";
import CategorySelector from "select-kit/components/category-selector";
export default class CategoryList extends Component {
@@ -50,9 +48,6 @@ export default class CategoryList extends Component {
@categories={{this.selectedCategories}}
@onChange={{this.onChangeSelectedCategories}}
/>
-
-
-
}
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/category.hbs b/app/assets/javascripts/admin/addon/components/site-settings/category.hbs
index bc008e28013..4b281b90d33 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/category.hbs
+++ b/app/assets/javascripts/admin/addon/components/site-settings/category.hbs
@@ -2,6 +2,4 @@
@value={{this.value}}
@onChange={{fn (mut this.value)}}
@options={{hash allowUncategorized=true none=(eq this.setting.default "")}}
-/>
-
-
\ No newline at end of file
+/>
\ No newline at end of file
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/color.hbs b/app/assets/javascripts/admin/addon/components/site-settings/color.hbs
index 4a706f2f6b3..3bbf69af09e 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/color.hbs
+++ b/app/assets/javascripts/admin/addon/components/site-settings/color.hbs
@@ -4,6 +4,4 @@
@onlyHex={{false}}
@styleSelection={{false}}
@onChangeColor={{this.onChangeColor}}
-/>
-
-
\ No newline at end of file
+/>
\ No newline at end of file
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/compact-list.hbs b/app/assets/javascripts/admin/addon/components/site-settings/compact-list.hbs
index df02a95358c..bd6989af094 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/compact-list.hbs
+++ b/app/assets/javascripts/admin/addon/components/site-settings/compact-list.hbs
@@ -5,7 +5,4 @@
@onChange={{this.onChangeListSetting}}
@onChangeChoices={{this.onChangeChoices}}
@options={{hash allowAny=this.allowAny}}
-/>
-
-
-
\ No newline at end of file
+/>
\ No newline at end of file
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/emoji-list.hbs b/app/assets/javascripts/admin/addon/components/site-settings/emoji-list.hbs
index 549b4495533..bbedad6cf9b 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/emoji-list.hbs
+++ b/app/assets/javascripts/admin/addon/components/site-settings/emoji-list.hbs
@@ -1,3 +1,5 @@
-
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/enum.hbs b/app/assets/javascripts/admin/addon/components/site-settings/enum.hbs
index a4343afe21d..a9ed4c42ddb 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/enum.hbs
+++ b/app/assets/javascripts/admin/addon/components/site-settings/enum.hbs
@@ -7,7 +7,4 @@
@options={{hash castInteger=true allowAny=this.setting.allowsNone}}
/>
-{{this.preview}}
-
-
-
\ No newline at end of file
+{{this.preview}}
\ No newline at end of file
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/file-size-restriction.gjs b/app/assets/javascripts/admin/addon/components/site-settings/file-size-restriction.gjs
index 15d356a1330..9af6840fa30 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/file-size-restriction.gjs
+++ b/app/assets/javascripts/admin/addon/components/site-settings/file-size-restriction.gjs
@@ -1,34 +1,23 @@
import Component from "@glimmer/component";
-import { tracked } from "@glimmer/tracking";
-import { fn } from "@ember/helper";
import { action } from "@ember/object";
import FileSizeInput from "admin/components/file-size-input";
-import SettingValidationMessage from "admin/components/setting-validation-message";
-import SiteSettingsDescription from "admin/components/site-settings/description";
export default class FileSizeRestriction extends Component {
- @tracked _validationMessage = this.args.validationMessage;
-
@action
- updateValidationMessage(message) {
- this._validationMessage = message;
- }
-
- get validationMessage() {
- return this._validationMessage ?? this.args.validationMessage;
+ changeSize(newValue) {
+ // Settings are stored as strings, this way the main site setting component
+ // doesn't get confused and think the value has changed from default if the
+ // admin sets it to the same number as the default.
+ this.args.changeValueCallback(newValue?.toString() ?? "");
}
-
-
-
}
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/file-types-list.gjs b/app/assets/javascripts/admin/addon/components/site-settings/file-types-list.gjs
index 7c5baf7c0e2..11fb7393ba9 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/file-types-list.gjs
+++ b/app/assets/javascripts/admin/addon/components/site-settings/file-types-list.gjs
@@ -8,8 +8,6 @@ import DButton from "discourse/components/d-button";
import i18n from "discourse-common/helpers/i18n";
import { makeArray } from "discourse-common/lib/helpers";
import I18n from "discourse-i18n";
-import SettingValidationMessage from "admin/components/setting-validation-message";
-import SiteSettingsDescription from "admin/components/site-settings/description";
import ListSetting from "select-kit/components/list-setting";
const IMAGE_TYPES = [
@@ -145,8 +143,5 @@ export default class FileTypesList extends Component {
}}
class="btn file-types-list__button document"
/>
-
-
-
}
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/group-list.hbs b/app/assets/javascripts/admin/addon/components/site-settings/group-list.hbs
index 9826bcf8e2b..d4b6a0592af 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/group-list.hbs
+++ b/app/assets/javascripts/admin/addon/components/site-settings/group-list.hbs
@@ -6,6 +6,4 @@
@nameProperty={{this.nameProperty}}
@valueProperty={{this.valueProperty}}
@onChange={{this.onChangeGroupListSetting}}
-/>
-
-
\ No newline at end of file
+/>
\ No newline at end of file
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/host-list.hbs b/app/assets/javascripts/admin/addon/components/site-settings/host-list.hbs
index 72632a82b64..b56d921cf05 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/host-list.hbs
+++ b/app/assets/javascripts/admin/addon/components/site-settings/host-list.hbs
@@ -4,7 +4,4 @@
@choices={{this.settingValue}}
@onChange={{this.onChange}}
@options={{hash allowAny=this.allowAny}}
-/>
-
-
-
\ No newline at end of file
+/>
\ No newline at end of file
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/integer.gjs b/app/assets/javascripts/admin/addon/components/site-settings/integer.gjs
index 89b82a80d4b..211c516b4e4 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/integer.gjs
+++ b/app/assets/javascripts/admin/addon/components/site-settings/integer.gjs
@@ -1,8 +1,6 @@
import Component from "@glimmer/component";
import { on } from "@ember/modifier";
import { action } from "@ember/object";
-import SettingValidationMessage from "admin/components/setting-validation-message";
-import SiteSettingDescription from "admin/components/site-settings/description";
export default class SiteSettingsInteger extends Component {
@action
@@ -37,8 +35,5 @@ export default class SiteSettingsInteger extends Component {
class="input-setting-integer"
step="1"
/>
-
-
-
}
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/list.hbs b/app/assets/javascripts/admin/addon/components/site-settings/list.hbs
index ae472fc743a..e515fad9075 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/list.hbs
+++ b/app/assets/javascripts/admin/addon/components/site-settings/list.hbs
@@ -2,6 +2,4 @@
@values={{this.value}}
@inputDelimiter="|"
@choices={{this.setting.choices}}
-/>
-
-
\ No newline at end of file
+/>
\ No newline at end of file
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/named-list.hbs b/app/assets/javascripts/admin/addon/components/site-settings/named-list.hbs
index 78c9e82b051..7569b9a1b5d 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/named-list.hbs
+++ b/app/assets/javascripts/admin/addon/components/site-settings/named-list.hbs
@@ -6,7 +6,4 @@
@valueProperty="value"
@onChange={{this.onChangeListSetting}}
@options={{hash allowAny=this.allowAny}}
-/>
-
-
-
\ No newline at end of file
+/>
\ No newline at end of file
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/secret-list.hbs b/app/assets/javascripts/admin/addon/components/site-settings/secret-list.hbs
index cd36a749185..a15329ee5d3 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/secret-list.hbs
+++ b/app/assets/javascripts/admin/addon/components/site-settings/secret-list.hbs
@@ -2,6 +2,5 @@
@setting={{this.setting}}
@values={{this.value}}
@isSecret={{this.isSecret}}
-/>
-
-
\ No newline at end of file
+ @setValidationMessage={{this.setValidationMessage}}
+/>
\ No newline at end of file
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/simple-list.hbs b/app/assets/javascripts/admin/addon/components/site-settings/simple-list.hbs
index 7b795e98310..e4262696eab 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/simple-list.hbs
+++ b/app/assets/javascripts/admin/addon/components/site-settings/simple-list.hbs
@@ -4,6 +4,4 @@
@onChange={{this.onChange}}
@choices={{this.setting.choices}}
@allowAny={{this.setting.allow_any}}
-/>
-
-
\ No newline at end of file
+/>
\ No newline at end of file
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/string.hbs b/app/assets/javascripts/admin/addon/components/site-settings/string.hbs
index d9ac8d61cc6..283bd94d52e 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/string.hbs
+++ b/app/assets/javascripts/admin/addon/components/site-settings/string.hbs
@@ -9,7 +9,4 @@
/>
{{else}}
-{{/if}}
-
-
-
\ No newline at end of file
+{{/if}}
\ No newline at end of file
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/tag-group-list.hbs b/app/assets/javascripts/admin/addon/components/site-settings/tag-group-list.hbs
index 179a328ebc8..7809b5a36e2 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/tag-group-list.hbs
+++ b/app/assets/javascripts/admin/addon/components/site-settings/tag-group-list.hbs
@@ -2,6 +2,4 @@
@tagGroups={{this.selectedTagGroups}}
@onChange={{this.onTagGroupChange}}
@options={{hash filterPlaceholder="category.required_tag_group.placeholder"}}
-/>
-
-
\ No newline at end of file
+/>
\ No newline at end of file
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/tag-list.hbs b/app/assets/javascripts/admin/addon/components/site-settings/tag-list.hbs
index 97933c52ff0..13bd33a0e4e 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/tag-list.hbs
+++ b/app/assets/javascripts/admin/addon/components/site-settings/tag-list.hbs
@@ -4,6 +4,4 @@
@everyTag={{true}}
@unlimitedTagCount={{true}}
@options={{hash allowAny=false}}
-/>
-
-
\ No newline at end of file
+/>
\ No newline at end of file
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/upload.hbs b/app/assets/javascripts/admin/addon/components/site-settings/upload.hbs
index 119af8ba5d3..cad0a33a03d 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/upload.hbs
+++ b/app/assets/javascripts/admin/addon/components/site-settings/upload.hbs
@@ -4,6 +4,4 @@
@additionalParams={{hash for_site_setting=true}}
@type="site_setting"
@id={{concat "site-setting-image-uploader-" this.setting.setting}}
-/>
-
-
\ No newline at end of file
+/>
\ No newline at end of file
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/uploaded-image-list.hbs b/app/assets/javascripts/admin/addon/components/site-settings/uploaded-image-list.hbs
index ddb191e9ee4..06bf42d1c5f 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/uploaded-image-list.hbs
+++ b/app/assets/javascripts/admin/addon/components/site-settings/uploaded-image-list.hbs
@@ -4,6 +4,4 @@
this.showUploadModal
(hash value=this.value setting=this.setting)
}}
-/>
-
-
\ No newline at end of file
+/>
\ No newline at end of file
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/url-list.hbs b/app/assets/javascripts/admin/addon/components/site-settings/url-list.hbs
index f33b0274278..54df5b9a43f 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/url-list.hbs
+++ b/app/assets/javascripts/admin/addon/components/site-settings/url-list.hbs
@@ -1,3 +1 @@
-
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/value-list.hbs b/app/assets/javascripts/admin/addon/components/site-settings/value-list.hbs
index 3ca238d7d34..47fd877a49a 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/value-list.hbs
+++ b/app/assets/javascripts/admin/addon/components/site-settings/value-list.hbs
@@ -1,3 +1 @@
-
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/javascripts/admin/addon/mixins/setting-component.js b/app/assets/javascripts/admin/addon/mixins/setting-component.js
index 87362d3e638..a55010df72b 100644
--- a/app/assets/javascripts/admin/addon/mixins/setting-component.js
+++ b/app/assets/javascripts/admin/addon/mixins/setting-component.js
@@ -104,6 +104,10 @@ export default Mixin.create({
this.element.removeEventListener("keydown", this._handleKeydown);
},
+ displayDescription: computed("componentType", function () {
+ return this.componentType !== "bool";
+ }),
+
dirty: computed("buffered.value", "setting.value", function () {
let bufferVal = this.get("buffered.value");
let settingVal = this.setting?.value;
@@ -211,6 +215,10 @@ export default Mixin.create({
}
}),
+ disableSaveButton: computed("validationMessage", function () {
+ return !!this.validationMessage;
+ }),
+
confirmChanges(settingKey) {
return new Promise((resolve) => {
// Fallback is needed in case the setting does not have a custom confirmation
@@ -324,12 +332,18 @@ export default Mixin.create({
this.set("buffered.value", value);
}),
+ setValidationMessage: action(function (message) {
+ this.set("validationMessage", message);
+ }),
+
cancel: action(function () {
this.rollbackBuffer();
+ this.set("validationMessage", null);
}),
resetDefault: action(function () {
this.set("buffered.value", this.setting.default);
+ this.set("validationMessage", null);
}),
toggleSecret: action(function () {
@@ -341,6 +355,7 @@ export default Mixin.create({
"buffered.value",
this.bufferedValues.concat(this.defaultValues).uniq().join("|")
);
+ this.set("validationMessage", null);
return false;
}),
diff --git a/app/assets/javascripts/discourse/tests/integration/components/file-size-input-test.js b/app/assets/javascripts/discourse/tests/integration/components/file-size-input-test.js
index 1305c3e9d91..2706debdb95 100644
--- a/app/assets/javascripts/discourse/tests/integration/components/file-size-input-test.js
+++ b/app/assets/javascripts/discourse/tests/integration/components/file-size-input-test.js
@@ -8,39 +8,88 @@ module("Integration | Component | file-size-input", function (hooks) {
setupRenderingTest(hooks);
test("file size unit selector kb", async function (assert) {
- this.set("value", 1024);
+ this.set("value", 1023);
this.set("max", 4096);
this.set("onChangeSize", () => {});
- this.set("updateValidationMessage", () => {});
+ this.set("setValidationMessage", () => {});
await render(hbs`
`);
- assert.dom(".file-size-input").hasValue("1024", "value is present");
+ assert.dom(".file-size-input").hasValue("1023", "value is present");
+ assert.strictEqual(
+ selectKit(".file-size-unit-selector").header().value(),
+ "kb",
+ "the default unit is kb"
+ );
+ });
+
+ test("file size unit is mb when the starting value is 1mb or more", async function (assert) {
+ this.set("value", 1024);
+ this.set("onChangeSize", () => {});
+ this.set("setValidationMessage", () => {});
+
+ await render(hbs`
+
+ `);
+
+ assert.dom(".file-size-input").hasValue("1", "value is present");
+ assert.strictEqual(
+ selectKit(".file-size-unit-selector").header().value(),
+ "mb",
+ "the default unit is mb"
+ );
+ });
+
+ test("file size unit is gb when the starting value is 1gb or more", async function (assert) {
+ this.set("value", 1024 * 1024);
+ this.set("onChangeSize", () => {});
+ this.set("setValidationMessage", () => {});
+
+ await render(hbs`
+
+ `);
+
+ assert.dom(".file-size-input").hasValue("1", "value is present");
+ assert.strictEqual(
+ selectKit(".file-size-unit-selector").header().value(),
+ "gb",
+ "the default unit is gb"
+ );
});
test("file size unit selector", async function (assert) {
this.set("value", 4096);
this.set("max", 8192);
this.set("onChangeSize", () => {});
- this.set("updateValidationMessage", () => {});
+ this.set("setValidationMessage", () => {});
await render(hbs`
`);
@@ -91,21 +140,22 @@ module("Integration | Component | file-size-input", function (hooks) {
test("file size input error message", async function (assert) {
this.set("value", 4096);
this.set("max", 8192);
+ this.set("min", 2048);
this.set("onChangeSize", () => {});
- let updateValidationMessage = (message) => {
+ let setValidationMessage = (message) => {
this.set("message", message);
};
- this.set("updateValidationMessage", updateValidationMessage);
+ this.set("setValidationMessage", setValidationMessage);
await render(hbs`
`);
@@ -124,5 +174,13 @@ module("Integration | Component | file-size-input", function (hooks) {
null,
"The message is cleared when the input is less than the max"
);
+
+ await fillIn(".file-size-input", 1);
+
+ assert.strictEqual(
+ this.message,
+ "1 MB is smaller than the min allowed 2 MB",
+ "A message is showed when the input is smaller than the min"
+ );
});
});
diff --git a/app/assets/javascripts/discourse/tests/integration/components/secret-value-list-test.js b/app/assets/javascripts/discourse/tests/integration/components/secret-value-list-test.js
index cc70c9cc3ee..3923a0fa34d 100644
--- a/app/assets/javascripts/discourse/tests/integration/components/secret-value-list-test.js
+++ b/app/assets/javascripts/discourse/tests/integration/components/secret-value-list-test.js
@@ -9,7 +9,14 @@ module("Integration | Component | secret-value-list", function (hooks) {
setupRenderingTest(hooks);
test("adding a value", async function (assert) {
- await render(hbs``);
+ this.set("setValidationMessage", () => {});
+
+ await render(hbs`
+
+ `);
this.set("values", "firstKey|FirstValue\nsecondKey|secondValue");
@@ -50,7 +57,17 @@ module("Integration | Component | secret-value-list", function (hooks) {
});
test("adding an invalid value", async function (assert) {
- await render(hbs``);
+ let setValidationMessage = (message) => {
+ this.set("message", message);
+ };
+ this.set("setValidationMessage", setValidationMessage);
+
+ await render(hbs`
+
+ `);
await fillIn(".new-value-input.key", "someString");
await fillIn(".new-value-input.secret", "keyWithAPipe|Hidden");
@@ -67,16 +84,22 @@ module("Integration | Component | secret-value-list", function (hooks) {
"it doesn't add the value to the list of values"
);
- assert.ok(
- query(".validation-error").innerText.includes(
- I18n.t("admin.site_settings.secret_list.invalid_input")
- ),
+ assert.strictEqual(
+ this.message,
+ I18n.t("admin.site_settings.secret_list.invalid_input"),
"it shows validation error"
);
});
test("changing a value", async function (assert) {
- await render(hbs``);
+ this.set("setValidationMessage", () => {});
+
+ await render(hbs`
+
+ `);
this.set("values", "firstKey|FirstValue\nsecondKey|secondValue");
@@ -109,7 +132,14 @@ module("Integration | Component | secret-value-list", function (hooks) {
});
test("removing a value", async function (assert) {
- await render(hbs``);
+ this.set("setValidationMessage", () => {});
+
+ await render(hbs`
+
+ `);
this.set("values", "firstKey|FirstValue\nsecondKey|secondValue");
diff --git a/app/assets/javascripts/discourse/tests/integration/components/site-setting-test.js b/app/assets/javascripts/discourse/tests/integration/components/site-setting-test.js
index 48e9286c82a..3b757c733aa 100644
--- a/app/assets/javascripts/discourse/tests/integration/components/site-setting-test.js
+++ b/app/assets/javascripts/discourse/tests/integration/components/site-setting-test.js
@@ -4,6 +4,7 @@ import { module, skip, test } from "qunit";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import pretender, { response } from "discourse/tests/helpers/create-pretender";
import { query } from "discourse/tests/helpers/qunit-helpers";
+import I18n from "discourse-i18n";
module("Integration | Component | site-setting", function (hooks) {
setupRenderingTest(hooks);
@@ -118,3 +119,174 @@ module("Integration | Component | site-setting", function (hooks) {
.hasNoClass("overridden");
});
});
+
+module(
+ "Integration | Component | site-setting | file_size_restriction type",
+ function (hooks) {
+ setupRenderingTest(hooks);
+
+ test("shows the reset button when the value has been changed from the default", async function (assert) {
+ this.set("setting", {
+ setting: "max_image_size_kb",
+ value: "2048",
+ default: "1024",
+ min: 512,
+ max: 4096,
+ type: "file_size_restriction",
+ });
+
+ await render(hbs``);
+ assert.dom(".setting-controls__undo").exists("reset button is shown");
+ });
+
+ test("doesn't show the reset button when the value is the same as the default", async function (assert) {
+ this.set("setting", {
+ setting: "max_image_size_kb",
+ value: "1024",
+ default: "1024",
+ min: 512,
+ max: 4096,
+ type: "file_size_restriction",
+ });
+
+ await render(hbs``);
+ assert
+ .dom(".setting-controls__undo")
+ .doesNotExist("reset button is not shown");
+ });
+
+ test("shows validation error when the value exceeds the max limit", async function (assert) {
+ this.set("setting", {
+ setting: "max_image_size_kb",
+ value: "1024",
+ default: "1024",
+ min: 512,
+ max: 4096,
+ type: "file_size_restriction",
+ });
+
+ await render(hbs``);
+ await fillIn(".file-size-input", "5000");
+
+ assert.dom(".validation-error").hasText(
+ I18n.t("file_size_input.error.size_too_large", {
+ provided_file_size: "4.9 GB",
+ max_file_size: "4 MB",
+ }),
+ "validation error message is shown"
+ );
+ assert.dom(".setting-controls__ok").hasAttribute("disabled");
+ assert.dom(".setting-controls__cancel").doesNotHaveAttribute("disabled");
+ });
+
+ test("shows validation error when the value is below the min limit", async function (assert) {
+ this.set("setting", {
+ setting: "max_image_size_kb",
+ value: "1000",
+ default: "1024",
+ min: 512,
+ max: 4096,
+ type: "file_size_restriction",
+ });
+
+ await render(hbs``);
+ await fillIn(".file-size-input", "100");
+
+ assert.dom(".validation-error").hasText(
+ I18n.t("file_size_input.error.size_too_small", {
+ provided_file_size: "100 KB",
+ min_file_size: "512 KB",
+ }),
+ "validation error message is shown"
+ );
+ assert.dom(".setting-controls__ok").hasAttribute("disabled");
+ assert.dom(".setting-controls__cancel").doesNotHaveAttribute("disabled");
+ });
+
+ test("cancelling pending changes resets the value and removes validation error", async function (assert) {
+ this.set("setting", {
+ setting: "max_image_size_kb",
+ value: "1000",
+ default: "1024",
+ min: 512,
+ max: 4096,
+ type: "file_size_restriction",
+ });
+
+ await render(hbs``);
+
+ await fillIn(".file-size-input", "100");
+ assert.dom(".validation-error").hasNoClass("hidden");
+
+ await click(".setting-controls__cancel");
+ assert
+ .dom(".file-size-input")
+ .hasValue("1000", "the value resets to the saved value");
+ assert.dom(".validation-error").hasClass("hidden");
+ });
+
+ test("resetting to the default value changes the content of input field", async function (assert) {
+ this.set("setting", {
+ setting: "max_image_size_kb",
+ value: "1000",
+ default: "1024",
+ min: 512,
+ max: 4096,
+ type: "file_size_restriction",
+ });
+
+ await render(hbs``);
+ assert
+ .dom(".file-size-input")
+ .hasValue("1000", "the input field contains the custom value");
+
+ await click(".setting-controls__undo");
+ assert
+ .dom(".file-size-input")
+ .hasValue("1024", "the input field now contains the default value");
+
+ assert
+ .dom(".setting-controls__undo")
+ .doesNotExist("the reset button is not shown");
+ assert.dom(".setting-controls__ok").exists("the save button is shown");
+ assert
+ .dom(".setting-controls__cancel")
+ .exists("the cancel button is shown");
+ });
+
+ test("clearing the input field keeps the cancel button and the validation error shown", async function (assert) {
+ this.set("setting", {
+ setting: "max_image_size_kb",
+ value: "1000",
+ default: "1024",
+ min: 512,
+ max: 4096,
+ type: "file_size_restriction",
+ });
+
+ await render(hbs``);
+
+ await fillIn(".file-size-input", "100");
+ assert.dom(".validation-error").hasNoClass("hidden");
+
+ await fillIn(".file-size-input", "");
+ assert.dom(".validation-error").hasNoClass("hidden");
+ assert.dom(".setting-controls__ok").exists("the save button is shown");
+ assert.dom(".setting-controls__ok").hasAttribute("disabled");
+ assert
+ .dom(".setting-controls__cancel")
+ .exists("the cancel button is shown");
+ assert.dom(".setting-controls__cancel").doesNotHaveAttribute("disabled");
+
+ await click(".setting-controls__cancel");
+ assert.dom(".file-size-input").hasValue("1000");
+ assert.dom(".validation-error").hasClass("hidden");
+ assert
+ .dom(".setting-controls__ok")
+ .doesNotExist("the save button is not shown");
+ assert
+ .dom(".setting-controls__cancel")
+ .doesNotExist("the cancel button is shown");
+ });
+ }
+);
diff --git a/app/assets/stylesheets/common/components/file-size-input.scss b/app/assets/stylesheets/common/components/file-size-input.scss
index 00cb90587f4..2cbcaa362b9 100644
--- a/app/assets/stylesheets/common/components/file-size-input.scss
+++ b/app/assets/stylesheets/common/components/file-size-input.scss
@@ -3,6 +3,7 @@
.file-size-input {
flex: 1;
+ margin-bottom: 0;
}
.file-size-unit-selector {
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 082c95a2e33..cccdd1d6824 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -2525,6 +2525,7 @@ en:
file_size_input:
error:
size_too_large: "%{provided_file_size} is greater than the max allowed %{max_file_size}"
+ size_too_small: "%{provided_file_size} is smaller than the min allowed %{min_file_size}"
emoji_picker:
filter_placeholder: Search for emoji