mirror of
https://github.com/discourse/discourse.git
synced 2025-02-06 03:18:23 +00:00
FIX: Make cancel and reset buttons work for file_size_restriction
settings (#28347)
This commit fixes a number of bugs in `file_size_restriction` settings and does a little of refactoring to reduce duplicated code in site setting types (the refactoring is necessary to fix one of the bugs). The bugs in `file_size_restriction` settings that are fixed in this commit: 1. Save/cancel buttons next to a `file_size_restriction` setting are shown upon navigating to the settings page without changes being made to the setting 2. Cancel button that discards changes made to the setting doesn't work 3. Reset button that resets the setting to its default doesn't work 4. Validation error message isn't cleared when resetting/cancelling changes To repro those bugs, navigate to `/admin/site_settings/category/files` and observe the top 2 settings in the page (`max image size kb` and `max attachment size kb`). Internal topic: t/134726.
This commit is contained in:
parent
b545576b3c
commit
a92cf019db
@ -57,5 +57,3 @@
|
|||||||
@emojiSelected={{this.emojiSelected}}
|
@emojiSelected={{this.emojiSelected}}
|
||||||
@onEmojiPickerClose={{this.closeEmojiPicker}}
|
@onEmojiPickerClose={{this.closeEmojiPicker}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
|
@ -10,7 +10,6 @@ import I18n from "discourse-i18n";
|
|||||||
@classNameBindings(":value-list", ":emoji-list")
|
@classNameBindings(":value-list", ":emoji-list")
|
||||||
export default class EmojiValueList extends Component {
|
export default class EmojiValueList extends Component {
|
||||||
values = null;
|
values = null;
|
||||||
validationMessage = null;
|
|
||||||
emojiPickerIsActive = false;
|
emojiPickerIsActive = false;
|
||||||
isEditorFocused = false;
|
isEditorFocused = false;
|
||||||
|
|
||||||
@ -137,16 +136,14 @@ export default class EmojiValueList extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_validateInput(input) {
|
_validateInput(input) {
|
||||||
this.set("validationMessage", null);
|
|
||||||
|
|
||||||
if (!emojiUrlFor(input)) {
|
if (!emojiUrlFor(input)) {
|
||||||
this.set(
|
this.setValidationMessage(
|
||||||
"validationMessage",
|
|
||||||
I18n.t("admin.site_settings.emoji_list.invalid_input")
|
I18n.t("admin.site_settings.emoji_list.invalid_input")
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.setValidationMessage(null);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,9 +2,6 @@ import Component from "@glimmer/component";
|
|||||||
import { tracked } from "@glimmer/tracking";
|
import { tracked } from "@glimmer/tracking";
|
||||||
import { on } from "@ember/modifier";
|
import { on } from "@ember/modifier";
|
||||||
import { action } from "@ember/object";
|
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 { allowOnlyNumericInput } from "discourse/lib/utilities";
|
||||||
import I18n from "discourse-i18n";
|
import I18n from "discourse-i18n";
|
||||||
import ComboBox from "select-kit/components/combo-box";
|
import ComboBox from "select-kit/components/combo-box";
|
||||||
@ -14,30 +11,34 @@ const UNIT_MB = "mb";
|
|||||||
const UNIT_GB = "gb";
|
const UNIT_GB = "gb";
|
||||||
|
|
||||||
export default class FileSizeInput extends Component {
|
export default class FileSizeInput extends Component {
|
||||||
@tracked fileSizeUnit;
|
@tracked unit;
|
||||||
@tracked sizeValue;
|
|
||||||
@tracked pendingSizeValue;
|
|
||||||
@tracked pendingFileSizeUnit;
|
|
||||||
|
|
||||||
constructor(owner, args) {
|
constructor() {
|
||||||
super(owner, args);
|
super(...arguments);
|
||||||
this.originalSizeKB = this.args.sizeValueKB;
|
|
||||||
this.sizeValue = this.args.sizeValueKB;
|
|
||||||
|
|
||||||
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() {
|
get number() {
|
||||||
this.fileSizeUnit = UNIT_KB;
|
const sizeInKB = this.args.sizeValueKB;
|
||||||
if (this.originalSizeKB <= 1024) {
|
if (!sizeInKB) {
|
||||||
this.onFileSizeUnitChange(UNIT_KB);
|
return;
|
||||||
} else if (
|
}
|
||||||
this.originalSizeKB > 1024 &&
|
if (this.unit === UNIT_KB) {
|
||||||
this.originalSizeKB <= 1024 * 1024
|
return sizeInKB;
|
||||||
) {
|
}
|
||||||
this.onFileSizeUnitChange(UNIT_MB);
|
if (this.unit === UNIT_MB) {
|
||||||
} else if (this.originalSizeKB > 1024 * 1024) {
|
return sizeInKB / 1024;
|
||||||
this.onFileSizeUnitChange(UNIT_GB);
|
}
|
||||||
|
if (this.unit === UNIT_GB) {
|
||||||
|
return sizeInKB / 1024 / 1024;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,95 +56,69 @@ export default class FileSizeInput extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
handleFileSizeChange(value) {
|
handleFileSizeChange(event) {
|
||||||
if (value !== "") {
|
const value = parseFloat(event.target.value);
|
||||||
this.pendingSizeValue = value;
|
|
||||||
this._onFileSizeChange(value);
|
if (isNaN(value)) {
|
||||||
}
|
this.args.onChangeSize();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_onFileSizeChange(newSize) {
|
let sizeInKB;
|
||||||
let fileSizeKB;
|
switch (this.unit) {
|
||||||
switch (this.fileSizeUnit) {
|
|
||||||
case "kb":
|
case "kb":
|
||||||
fileSizeKB = newSize;
|
sizeInKB = value;
|
||||||
break;
|
break;
|
||||||
case "mb":
|
case "mb":
|
||||||
fileSizeKB = newSize * 1024;
|
sizeInKB = value * 1024;
|
||||||
break;
|
break;
|
||||||
case "gb":
|
case "gb":
|
||||||
fileSizeKB = newSize * 1024 * 1024;
|
sizeInKB = value * 1024 * 1024;
|
||||||
break;
|
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", {
|
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),
|
max_file_size: I18n.toHumanSize(this.args.max * 1024),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
// Removes the green save checkmark button
|
} else if (sizeInKB < this.args.min) {
|
||||||
this.args.onChangeSize(this.originalSizeKB);
|
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 {
|
} else {
|
||||||
this.args.onChangeSize(fileSizeKB);
|
this.args.setValidationMessage(null);
|
||||||
this.args.updateValidationMessage(null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
onFileSizeUnitChange(newUnit) {
|
onFileSizeUnitChange(newUnit) {
|
||||||
if (this.fileSizeUnit === "kb" && newUnit === "kb") {
|
this.unit = newUnit;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="file-size-picker">
|
<div class="file-size-picker">
|
||||||
<TextField
|
<input
|
||||||
class="file-size-input"
|
class="file-size-input"
|
||||||
@value={{this.sizeValue}}
|
value={{this.number}}
|
||||||
@onChange={{this.handleFileSizeChange}}
|
type="number"
|
||||||
|
step="any"
|
||||||
|
{{on "input" this.handleFileSizeChange}}
|
||||||
{{on "keydown" this.keyDown}}
|
{{on "keydown" this.keyDown}}
|
||||||
{{didInsert this.applySizeValueChanges}}
|
|
||||||
{{didUpdate this.applySizeValueChanges this.pendingSizeValue}}
|
|
||||||
/>
|
/>
|
||||||
<ComboBox
|
<ComboBox
|
||||||
class="file-size-unit-selector"
|
class="file-size-unit-selector"
|
||||||
@valueProperty="value"
|
@valueProperty="value"
|
||||||
@content={{this.dropdownOptions}}
|
@content={{this.dropdownOptions}}
|
||||||
@value={{this.fileSizeUnit}}
|
@value={{this.unit}}
|
||||||
@onChange={{this.onFileSizeUnitChange}}
|
@onChange={{this.onFileSizeUnitChange}}
|
||||||
{{didInsert this.applyUnitChanges}}
|
|
||||||
{{didUpdate this.applyUnitChanges this.pendingFileSizeUnit}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -41,5 +41,3 @@
|
|||||||
class="add-value-btn btn-small"
|
class="add-value-btn btn-small"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
|
@ -9,7 +9,6 @@ export default class SecretValueList extends Component {
|
|||||||
inputDelimiter = null;
|
inputDelimiter = null;
|
||||||
collection = null;
|
collection = null;
|
||||||
values = null;
|
values = null;
|
||||||
validationMessage = null;
|
|
||||||
|
|
||||||
didReceiveAttrs() {
|
didReceiveAttrs() {
|
||||||
super.didReceiveAttrs(...arguments);
|
super.didReceiveAttrs(...arguments);
|
||||||
@ -57,16 +56,15 @@ export default class SecretValueList extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_checkInvalidInput(inputs) {
|
_checkInvalidInput(inputs) {
|
||||||
this.set("validationMessage", null);
|
|
||||||
for (let input of inputs) {
|
for (let input of inputs) {
|
||||||
if (isEmpty(input) || input.includes("|")) {
|
if (isEmpty(input) || input.includes("|")) {
|
||||||
this.set(
|
this.setValidationMessage(
|
||||||
"validationMessage",
|
|
||||||
I18n.t("admin.site_settings.secret_list.invalid_input")
|
I18n.t("admin.site_settings.secret_list.invalid_input")
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.setValidationMessage(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
_addValue(value, secret) {
|
_addValue(value, secret) {
|
||||||
|
@ -39,12 +39,16 @@
|
|||||||
this.componentName
|
this.componentName
|
||||||
setting=this.setting
|
setting=this.setting
|
||||||
value=this.buffered.value
|
value=this.buffered.value
|
||||||
validationMessage=this.validationMessage
|
|
||||||
preview=this.preview
|
preview=this.preview
|
||||||
isSecret=this.isSecret
|
isSecret=this.isSecret
|
||||||
allowAny=this.allowAny
|
allowAny=this.allowAny
|
||||||
changeValueCallback=this.changeValueCallback
|
changeValueCallback=this.changeValueCallback
|
||||||
|
setValidationMessage=this.setValidationMessage
|
||||||
}}
|
}}
|
||||||
|
<SettingValidationMessage @message={{this.validationMessage}} />
|
||||||
|
{{#if this.displayDescription}}
|
||||||
|
<SiteSettings::Description @description={{this.setting.description}} />
|
||||||
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -53,6 +57,7 @@
|
|||||||
<DButton
|
<DButton
|
||||||
@action={{this.update}}
|
@action={{this.update}}
|
||||||
@icon="check"
|
@icon="check"
|
||||||
|
@disabled={{this.disableSaveButton}}
|
||||||
class="ok setting-controls__ok"
|
class="ok setting-controls__ok"
|
||||||
/>
|
/>
|
||||||
<DButton
|
<DButton
|
||||||
@ -71,7 +76,7 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<DButton
|
<DButton
|
||||||
class="btn-default undo"
|
class="btn-default undo setting-controls__undo"
|
||||||
@action={{this.resetDefault}}
|
@action={{this.resetDefault}}
|
||||||
@icon="undo"
|
@icon="undo"
|
||||||
@label="admin.settings.reset"
|
@label="admin.settings.reset"
|
||||||
|
@ -2,5 +2,3 @@
|
|||||||
<Input @type="checkbox" @checked={{this.enabled}} />
|
<Input @type="checkbox" @checked={{this.enabled}} />
|
||||||
<span>{{html-safe this.setting.description}}</span>
|
<span>{{html-safe this.setting.description}}</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
|
@ -3,8 +3,6 @@ import { tracked } from "@glimmer/tracking";
|
|||||||
import { action } from "@ember/object";
|
import { action } from "@ember/object";
|
||||||
import didUpdate from "@ember/render-modifiers/modifiers/did-update";
|
import didUpdate from "@ember/render-modifiers/modifiers/did-update";
|
||||||
import Category from "discourse/models/category";
|
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";
|
import CategorySelector from "select-kit/components/category-selector";
|
||||||
|
|
||||||
export default class CategoryList extends Component {
|
export default class CategoryList extends Component {
|
||||||
@ -50,9 +48,6 @@ export default class CategoryList extends Component {
|
|||||||
@categories={{this.selectedCategories}}
|
@categories={{this.selectedCategories}}
|
||||||
@onChange={{this.onChangeSelectedCategories}}
|
@onChange={{this.onChangeSelectedCategories}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SiteSettingsDescription @description={{@setting.description}} />
|
|
||||||
<SettingValidationMessage @message={{@validationMessage}} />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
}
|
}
|
||||||
|
@ -3,5 +3,3 @@
|
|||||||
@onChange={{fn (mut this.value)}}
|
@onChange={{fn (mut this.value)}}
|
||||||
@options={{hash allowUncategorized=true none=(eq this.setting.default "")}}
|
@options={{hash allowUncategorized=true none=(eq this.setting.default "")}}
|
||||||
/>
|
/>
|
||||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
|
||||||
<SiteSettings::Description @description={{this.setting.description}} />
|
|
@ -5,5 +5,3 @@
|
|||||||
@styleSelection={{false}}
|
@styleSelection={{false}}
|
||||||
@onChangeColor={{this.onChangeColor}}
|
@onChangeColor={{this.onChangeColor}}
|
||||||
/>
|
/>
|
||||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
|
||||||
<SiteSettings::Description @description={{this.setting.description}} />
|
|
@ -6,6 +6,3 @@
|
|||||||
@onChangeChoices={{this.onChangeChoices}}
|
@onChangeChoices={{this.onChangeChoices}}
|
||||||
@options={{hash allowAny=this.allowAny}}
|
@options={{hash allowAny=this.allowAny}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
|
||||||
<SiteSettings::Description @description={{this.setting.description}} />
|
|
@ -1,3 +1,5 @@
|
|||||||
<EmojiValueList @setting={{this.setting}} @values={{this.value}} />
|
<EmojiValueList
|
||||||
<SiteSettings::Description @description={{this.setting.description}} />
|
@setting={{this.setting}}
|
||||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
@values={{this.value}}
|
||||||
|
@setValidationMessage={{this.setValidationMessage}}
|
||||||
|
/>
|
@ -8,6 +8,3 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
{{this.preview}}
|
{{this.preview}}
|
||||||
|
|
||||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
|
||||||
<SiteSettings::Description @description={{this.setting.description}} />
|
|
@ -1,34 +1,23 @@
|
|||||||
import Component from "@glimmer/component";
|
import Component from "@glimmer/component";
|
||||||
import { tracked } from "@glimmer/tracking";
|
|
||||||
import { fn } from "@ember/helper";
|
|
||||||
import { action } from "@ember/object";
|
import { action } from "@ember/object";
|
||||||
import FileSizeInput from "admin/components/file-size-input";
|
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 {
|
export default class FileSizeRestriction extends Component {
|
||||||
@tracked _validationMessage = this.args.validationMessage;
|
|
||||||
|
|
||||||
@action
|
@action
|
||||||
updateValidationMessage(message) {
|
changeSize(newValue) {
|
||||||
this._validationMessage = message;
|
// 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.
|
||||||
get validationMessage() {
|
this.args.changeValueCallback(newValue?.toString() ?? "");
|
||||||
return this._validationMessage ?? this.args.validationMessage;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<FileSizeInput
|
<FileSizeInput
|
||||||
@sizeValueKB={{@value}}
|
@sizeValueKB={{@value}}
|
||||||
@onChangeSize={{fn (mut @value)}}
|
@onChangeSize={{this.changeSize}}
|
||||||
@updateValidationMessage={{this.updateValidationMessage}}
|
@max={{@setting.max}}
|
||||||
@min={{if @setting.min @setting.min null}}
|
@min={{@setting.min}}
|
||||||
@max={{if @setting.max @setting.max null}}
|
@setValidationMessage={{@setValidationMessage}}
|
||||||
@message={{this.validationMessage}}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
|
||||||
<SiteSettingsDescription @description={{@setting.description}} />
|
|
||||||
</template>
|
</template>
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,6 @@ import DButton from "discourse/components/d-button";
|
|||||||
import i18n from "discourse-common/helpers/i18n";
|
import i18n from "discourse-common/helpers/i18n";
|
||||||
import { makeArray } from "discourse-common/lib/helpers";
|
import { makeArray } from "discourse-common/lib/helpers";
|
||||||
import I18n from "discourse-i18n";
|
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";
|
import ListSetting from "select-kit/components/list-setting";
|
||||||
|
|
||||||
const IMAGE_TYPES = [
|
const IMAGE_TYPES = [
|
||||||
@ -145,8 +143,5 @@ export default class FileTypesList extends Component {
|
|||||||
}}
|
}}
|
||||||
class="btn file-types-list__button document"
|
class="btn file-types-list__button document"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SettingValidationMessage @message={{@validationMessage}} />
|
|
||||||
<SiteSettingsDescription @description={{@setting.description}} />
|
|
||||||
</template>
|
</template>
|
||||||
}
|
}
|
||||||
|
@ -7,5 +7,3 @@
|
|||||||
@valueProperty={{this.valueProperty}}
|
@valueProperty={{this.valueProperty}}
|
||||||
@onChange={{this.onChangeGroupListSetting}}
|
@onChange={{this.onChangeGroupListSetting}}
|
||||||
/>
|
/>
|
||||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
|
||||||
<SiteSettings::Description @description={{this.setting.description}} />
|
|
@ -5,6 +5,3 @@
|
|||||||
@onChange={{this.onChange}}
|
@onChange={{this.onChange}}
|
||||||
@options={{hash allowAny=this.allowAny}}
|
@options={{hash allowAny=this.allowAny}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
|
||||||
<SiteSettings::Description @description={{this.setting.description}} />
|
|
@ -1,8 +1,6 @@
|
|||||||
import Component from "@glimmer/component";
|
import Component from "@glimmer/component";
|
||||||
import { on } from "@ember/modifier";
|
import { on } from "@ember/modifier";
|
||||||
import { action } from "@ember/object";
|
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 {
|
export default class SiteSettingsInteger extends Component {
|
||||||
@action
|
@action
|
||||||
@ -37,8 +35,5 @@ export default class SiteSettingsInteger extends Component {
|
|||||||
class="input-setting-integer"
|
class="input-setting-integer"
|
||||||
step="1"
|
step="1"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SettingValidationMessage @message={{@validationMessage}} />
|
|
||||||
<SiteSettingDescription @description={{@setting.description}} />
|
|
||||||
</template>
|
</template>
|
||||||
}
|
}
|
||||||
|
@ -3,5 +3,3 @@
|
|||||||
@inputDelimiter="|"
|
@inputDelimiter="|"
|
||||||
@choices={{this.setting.choices}}
|
@choices={{this.setting.choices}}
|
||||||
/>
|
/>
|
||||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
|
||||||
<SiteSettings::Description @description={{this.setting.description}} />
|
|
@ -7,6 +7,3 @@
|
|||||||
@onChange={{this.onChangeListSetting}}
|
@onChange={{this.onChangeListSetting}}
|
||||||
@options={{hash allowAny=this.allowAny}}
|
@options={{hash allowAny=this.allowAny}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
|
||||||
<SiteSettings::Description @description={{this.setting.description}} />
|
|
@ -2,6 +2,5 @@
|
|||||||
@setting={{this.setting}}
|
@setting={{this.setting}}
|
||||||
@values={{this.value}}
|
@values={{this.value}}
|
||||||
@isSecret={{this.isSecret}}
|
@isSecret={{this.isSecret}}
|
||||||
|
@setValidationMessage={{this.setValidationMessage}}
|
||||||
/>
|
/>
|
||||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
|
||||||
<SiteSettings::Description @description={{this.setting.description}} />
|
|
@ -5,5 +5,3 @@
|
|||||||
@choices={{this.setting.choices}}
|
@choices={{this.setting.choices}}
|
||||||
@allowAny={{this.setting.allow_any}}
|
@allowAny={{this.setting.allow_any}}
|
||||||
/>
|
/>
|
||||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
|
||||||
<SiteSettings::Description @description={{this.setting.description}} />
|
|
@ -10,6 +10,3 @@
|
|||||||
{{else}}
|
{{else}}
|
||||||
<TextField @value={{this.value}} @classNames="input-setting-string" />
|
<TextField @value={{this.value}} @classNames="input-setting-string" />
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
|
||||||
<SiteSettings::Description @description={{this.setting.description}} />
|
|
@ -3,5 +3,3 @@
|
|||||||
@onChange={{this.onTagGroupChange}}
|
@onChange={{this.onTagGroupChange}}
|
||||||
@options={{hash filterPlaceholder="category.required_tag_group.placeholder"}}
|
@options={{hash filterPlaceholder="category.required_tag_group.placeholder"}}
|
||||||
/>
|
/>
|
||||||
<SiteSettings::Description @description={{this.setting.description}} />
|
|
||||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
|
@ -5,5 +5,3 @@
|
|||||||
@unlimitedTagCount={{true}}
|
@unlimitedTagCount={{true}}
|
||||||
@options={{hash allowAny=false}}
|
@options={{hash allowAny=false}}
|
||||||
/>
|
/>
|
||||||
<SiteSettings::Description @description={{this.setting.description}} />
|
|
||||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
|
@ -5,5 +5,3 @@
|
|||||||
@type="site_setting"
|
@type="site_setting"
|
||||||
@id={{concat "site-setting-image-uploader-" this.setting.setting}}
|
@id={{concat "site-setting-image-uploader-" this.setting.setting}}
|
||||||
/>
|
/>
|
||||||
<SiteSettings::Description @description={{this.setting.description}} />
|
|
||||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
|
@ -5,5 +5,3 @@
|
|||||||
(hash value=this.value setting=this.setting)
|
(hash value=this.value setting=this.setting)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<SiteSettings::Description @description={{this.setting.description}} />
|
|
||||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
|
@ -1,3 +1 @@
|
|||||||
<ValueList @values={{this.value}} @addKey="admin.site_settings.add_url" />
|
<ValueList @values={{this.value}} @addKey="admin.site_settings.add_url" />
|
||||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
|
||||||
<SiteSettings::Description @description={{this.setting.description}} />
|
|
@ -1,3 +1 @@
|
|||||||
<ValueList @values={{this.value}} />
|
<ValueList @values={{this.value}} />
|
||||||
<SettingValidationMessage @message={{this.validationMessage}} />
|
|
||||||
<SiteSettings::Description @description={{this.setting.description}} />
|
|
@ -104,6 +104,10 @@ export default Mixin.create({
|
|||||||
this.element.removeEventListener("keydown", this._handleKeydown);
|
this.element.removeEventListener("keydown", this._handleKeydown);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
displayDescription: computed("componentType", function () {
|
||||||
|
return this.componentType !== "bool";
|
||||||
|
}),
|
||||||
|
|
||||||
dirty: computed("buffered.value", "setting.value", function () {
|
dirty: computed("buffered.value", "setting.value", function () {
|
||||||
let bufferVal = this.get("buffered.value");
|
let bufferVal = this.get("buffered.value");
|
||||||
let settingVal = this.setting?.value;
|
let settingVal = this.setting?.value;
|
||||||
@ -211,6 +215,10 @@ export default Mixin.create({
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
disableSaveButton: computed("validationMessage", function () {
|
||||||
|
return !!this.validationMessage;
|
||||||
|
}),
|
||||||
|
|
||||||
confirmChanges(settingKey) {
|
confirmChanges(settingKey) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
// Fallback is needed in case the setting does not have a custom confirmation
|
// 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);
|
this.set("buffered.value", value);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
setValidationMessage: action(function (message) {
|
||||||
|
this.set("validationMessage", message);
|
||||||
|
}),
|
||||||
|
|
||||||
cancel: action(function () {
|
cancel: action(function () {
|
||||||
this.rollbackBuffer();
|
this.rollbackBuffer();
|
||||||
|
this.set("validationMessage", null);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
resetDefault: action(function () {
|
resetDefault: action(function () {
|
||||||
this.set("buffered.value", this.setting.default);
|
this.set("buffered.value", this.setting.default);
|
||||||
|
this.set("validationMessage", null);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
toggleSecret: action(function () {
|
toggleSecret: action(function () {
|
||||||
@ -341,6 +355,7 @@ export default Mixin.create({
|
|||||||
"buffered.value",
|
"buffered.value",
|
||||||
this.bufferedValues.concat(this.defaultValues).uniq().join("|")
|
this.bufferedValues.concat(this.defaultValues).uniq().join("|")
|
||||||
);
|
);
|
||||||
|
this.set("validationMessage", null);
|
||||||
return false;
|
return false;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
@ -8,39 +8,88 @@ module("Integration | Component | file-size-input", function (hooks) {
|
|||||||
setupRenderingTest(hooks);
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
test("file size unit selector kb", async function (assert) {
|
test("file size unit selector kb", async function (assert) {
|
||||||
this.set("value", 1024);
|
this.set("value", 1023);
|
||||||
this.set("max", 4096);
|
this.set("max", 4096);
|
||||||
this.set("onChangeSize", () => {});
|
this.set("onChangeSize", () => {});
|
||||||
this.set("updateValidationMessage", () => {});
|
this.set("setValidationMessage", () => {});
|
||||||
|
|
||||||
await render(hbs`
|
await render(hbs`
|
||||||
<FileSizeInput
|
<FileSizeInput
|
||||||
@sizeValueKB={{readonly this.value}}
|
@sizeValueKB={{readonly this.value}}
|
||||||
class="file-size-input-test"
|
class="file-size-input-test"
|
||||||
@onChangeSize={{this.onChangeSize}}
|
@onChangeSize={{this.onChangeSize}}
|
||||||
@updateValidationMessage={{this.updateValidationMessage}}
|
@setValidationMessage={{this.setValidationMessage}}
|
||||||
@max=4096
|
@max=4096
|
||||||
@message=""
|
|
||||||
/>
|
/>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
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`
|
||||||
|
<FileSizeInput
|
||||||
|
@sizeValueKB={{readonly this.value}}
|
||||||
|
class="file-size-input-test"
|
||||||
|
@onChangeSize={{this.onChangeSize}}
|
||||||
|
@setValidationMessage={{this.setValidationMessage}}
|
||||||
|
@max=4096
|
||||||
|
/>
|
||||||
|
`);
|
||||||
|
|
||||||
|
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`
|
||||||
|
<FileSizeInput
|
||||||
|
@sizeValueKB={{readonly this.value}}
|
||||||
|
class="file-size-input-test"
|
||||||
|
@onChangeSize={{this.onChangeSize}}
|
||||||
|
@setValidationMessage={{this.setValidationMessage}}
|
||||||
|
@max=4096
|
||||||
|
/>
|
||||||
|
`);
|
||||||
|
|
||||||
|
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) {
|
test("file size unit selector", async function (assert) {
|
||||||
this.set("value", 4096);
|
this.set("value", 4096);
|
||||||
this.set("max", 8192);
|
this.set("max", 8192);
|
||||||
this.set("onChangeSize", () => {});
|
this.set("onChangeSize", () => {});
|
||||||
this.set("updateValidationMessage", () => {});
|
this.set("setValidationMessage", () => {});
|
||||||
|
|
||||||
await render(hbs`
|
await render(hbs`
|
||||||
<FileSizeInput
|
<FileSizeInput
|
||||||
@sizeValueKB={{readonly this.value}}
|
@sizeValueKB={{readonly this.value}}
|
||||||
class="file-size-input-test"
|
class="file-size-input-test"
|
||||||
@onChangeSize={{this.onChangeSize}}
|
@onChangeSize={{this.onChangeSize}}
|
||||||
@updateValidationMessage={{this.updateValidationMessage}}
|
@setValidationMessage={{this.setValidationMessage}}
|
||||||
@max=4096
|
@max=4096
|
||||||
@message=""
|
|
||||||
/>
|
/>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
@ -91,21 +140,22 @@ module("Integration | Component | file-size-input", function (hooks) {
|
|||||||
test("file size input error message", async function (assert) {
|
test("file size input error message", async function (assert) {
|
||||||
this.set("value", 4096);
|
this.set("value", 4096);
|
||||||
this.set("max", 8192);
|
this.set("max", 8192);
|
||||||
|
this.set("min", 2048);
|
||||||
this.set("onChangeSize", () => {});
|
this.set("onChangeSize", () => {});
|
||||||
|
|
||||||
let updateValidationMessage = (message) => {
|
let setValidationMessage = (message) => {
|
||||||
this.set("message", message);
|
this.set("message", message);
|
||||||
};
|
};
|
||||||
this.set("updateValidationMessage", updateValidationMessage);
|
this.set("setValidationMessage", setValidationMessage);
|
||||||
|
|
||||||
await render(hbs`
|
await render(hbs`
|
||||||
<FileSizeInput
|
<FileSizeInput
|
||||||
@sizeValueKB={{readonly this.value}}
|
@sizeValueKB={{readonly this.value}}
|
||||||
class="file-size-input-test"
|
class="file-size-input-test"
|
||||||
@onChangeSize={{this.onChangeSize}}
|
@onChangeSize={{this.onChangeSize}}
|
||||||
@updateValidationMessage={{this.updateValidationMessage}}
|
@setValidationMessage={{this.setValidationMessage}}
|
||||||
@max={{this.max}}
|
@max={{this.max}}
|
||||||
@message={{this.message}}
|
@min={{this.min}}
|
||||||
/>
|
/>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
@ -124,5 +174,13 @@ module("Integration | Component | file-size-input", function (hooks) {
|
|||||||
null,
|
null,
|
||||||
"The message is cleared when the input is less than the max"
|
"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"
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -9,7 +9,14 @@ module("Integration | Component | secret-value-list", function (hooks) {
|
|||||||
setupRenderingTest(hooks);
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
test("adding a value", async function (assert) {
|
test("adding a value", async function (assert) {
|
||||||
await render(hbs`<SecretValueList @values={{this.values}} />`);
|
this.set("setValidationMessage", () => {});
|
||||||
|
|
||||||
|
await render(hbs`
|
||||||
|
<SecretValueList
|
||||||
|
@values={{this.values}}
|
||||||
|
@setValidationMessage={{this.setValidationMessage}}
|
||||||
|
/>
|
||||||
|
`);
|
||||||
|
|
||||||
this.set("values", "firstKey|FirstValue\nsecondKey|secondValue");
|
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) {
|
test("adding an invalid value", async function (assert) {
|
||||||
await render(hbs`<SecretValueList @values={{this.values}} />`);
|
let setValidationMessage = (message) => {
|
||||||
|
this.set("message", message);
|
||||||
|
};
|
||||||
|
this.set("setValidationMessage", setValidationMessage);
|
||||||
|
|
||||||
|
await render(hbs`
|
||||||
|
<SecretValueList
|
||||||
|
@values={{this.values}}
|
||||||
|
@setValidationMessage={{this.setValidationMessage}}
|
||||||
|
/>
|
||||||
|
`);
|
||||||
|
|
||||||
await fillIn(".new-value-input.key", "someString");
|
await fillIn(".new-value-input.key", "someString");
|
||||||
await fillIn(".new-value-input.secret", "keyWithAPipe|Hidden");
|
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"
|
"it doesn't add the value to the list of values"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.ok(
|
assert.strictEqual(
|
||||||
query(".validation-error").innerText.includes(
|
this.message,
|
||||||
I18n.t("admin.site_settings.secret_list.invalid_input")
|
I18n.t("admin.site_settings.secret_list.invalid_input"),
|
||||||
),
|
|
||||||
"it shows validation error"
|
"it shows validation error"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("changing a value", async function (assert) {
|
test("changing a value", async function (assert) {
|
||||||
await render(hbs`<SecretValueList @values={{this.values}} />`);
|
this.set("setValidationMessage", () => {});
|
||||||
|
|
||||||
|
await render(hbs`
|
||||||
|
<SecretValueList
|
||||||
|
@values={{this.values}}
|
||||||
|
@setValidationMessage={{this.setValidationMessage}}
|
||||||
|
/>
|
||||||
|
`);
|
||||||
|
|
||||||
this.set("values", "firstKey|FirstValue\nsecondKey|secondValue");
|
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) {
|
test("removing a value", async function (assert) {
|
||||||
await render(hbs`<SecretValueList @values={{this.values}} />`);
|
this.set("setValidationMessage", () => {});
|
||||||
|
|
||||||
|
await render(hbs`
|
||||||
|
<SecretValueList
|
||||||
|
@values={{this.values}}
|
||||||
|
@setValidationMessage={{this.setValidationMessage}}
|
||||||
|
/>
|
||||||
|
`);
|
||||||
|
|
||||||
this.set("values", "firstKey|FirstValue\nsecondKey|secondValue");
|
this.set("values", "firstKey|FirstValue\nsecondKey|secondValue");
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import { module, skip, test } from "qunit";
|
|||||||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||||
import pretender, { response } from "discourse/tests/helpers/create-pretender";
|
import pretender, { response } from "discourse/tests/helpers/create-pretender";
|
||||||
import { query } from "discourse/tests/helpers/qunit-helpers";
|
import { query } from "discourse/tests/helpers/qunit-helpers";
|
||||||
|
import I18n from "discourse-i18n";
|
||||||
|
|
||||||
module("Integration | Component | site-setting", function (hooks) {
|
module("Integration | Component | site-setting", function (hooks) {
|
||||||
setupRenderingTest(hooks);
|
setupRenderingTest(hooks);
|
||||||
@ -118,3 +119,174 @@ module("Integration | Component | site-setting", function (hooks) {
|
|||||||
.hasNoClass("overridden");
|
.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`<SiteSetting @setting={{this.setting}} />`);
|
||||||
|
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`<SiteSetting @setting={{this.setting}} />`);
|
||||||
|
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`<SiteSetting @setting={{this.setting}} />`);
|
||||||
|
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`<SiteSetting @setting={{this.setting}} />`);
|
||||||
|
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`<SiteSetting @setting={{this.setting}} />`);
|
||||||
|
|
||||||
|
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`<SiteSetting @setting={{this.setting}} />`);
|
||||||
|
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`<SiteSetting @setting={{this.setting}} />`);
|
||||||
|
|
||||||
|
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");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
.file-size-input {
|
.file-size-input {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-size-unit-selector {
|
.file-size-unit-selector {
|
||||||
|
@ -2525,6 +2525,7 @@ en:
|
|||||||
file_size_input:
|
file_size_input:
|
||||||
error:
|
error:
|
||||||
size_too_large: "%{provided_file_size} is greater than the max allowed %{max_file_size}"
|
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:
|
emoji_picker:
|
||||||
filter_placeholder: Search for emoji
|
filter_placeholder: Search for emoji
|
||||||
|
Loading…
x
Reference in New Issue
Block a user