DEV: Convert admin component definitions to native class syntax (#20311)

This conversion was achieved using the ember-native-class-codemod, plus a handful of manual fixes/tweaks
This commit is contained in:
David Taylor 2023-02-23 15:32:53 +00:00 committed by GitHub
parent a0ca10fa17
commit a433b30650
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
88 changed files with 1227 additions and 1141 deletions

View File

@ -1,31 +1,33 @@
import { action } from "@ember/object";
import { classNames } from "@ember-decorators/component";
import { on } from "@ember-decorators/object";
import Component from "@ember/component"; import Component from "@ember/component";
import getURL from "discourse-common/lib/get-url"; import getURL from "discourse-common/lib/get-url";
import loadScript from "discourse/lib/load-script"; import loadScript from "discourse/lib/load-script";
import I18n from "I18n"; import I18n from "I18n";
import { bind, observes } from "discourse-common/utils/decorators"; import { bind, observes } from "discourse-common/utils/decorators";
import { on } from "@ember/object/evented";
const COLOR_VARS_REGEX = const COLOR_VARS_REGEX =
/\$(primary|secondary|tertiary|quaternary|header_background|header_primary|highlight|danger|success|love)(\s|;|-(low|medium|high))/g; /\$(primary|secondary|tertiary|quaternary|header_background|header_primary|highlight|danger|success|love)(\s|;|-(low|medium|high))/g;
export default Component.extend({ @classNames("ace-wrapper")
mode: "css", export default class AceEditor extends Component {
classNames: ["ace-wrapper"], mode = "css";
_editor: null, disabled = false;
_skipContentChangeEvent: null, htmlPlaceholder = false;
disabled: false, _editor = null;
htmlPlaceholder: false, _skipContentChangeEvent = null;
@observes("editorId") @observes("editorId")
editorIdChanged() { editorIdChanged() {
if (this.autofocus) { if (this.autofocus) {
this.send("focus"); this.send("focus");
} }
}, }
didRender() { didRender() {
this._skipContentChangeEvent = false; this._skipContentChangeEvent = false;
}, }
@observes("content") @observes("content")
contentChanged() { contentChanged() {
@ -33,14 +35,14 @@ export default Component.extend({
if (this._editor && !this._skipContentChangeEvent) { if (this._editor && !this._skipContentChangeEvent) {
this._editor.getSession().setValue(content); this._editor.getSession().setValue(content);
} }
}, }
@observes("mode") @observes("mode")
modeChanged() { modeChanged() {
if (this._editor && !this._skipContentChangeEvent) { if (this._editor && !this._skipContentChangeEvent) {
this._editor.getSession().setMode("ace/mode/" + this.mode); this._editor.getSession().setMode("ace/mode/" + this.mode);
} }
}, }
@observes("placeholder") @observes("placeholder")
placeholderChanged() { placeholderChanged() {
@ -49,12 +51,12 @@ export default Component.extend({
placeholder: this.placeholder, placeholder: this.placeholder,
}); });
} }
}, }
@observes("disabled") @observes("disabled")
disabledStateChanged() { disabledStateChanged() {
this.changeDisabledState(); this.changeDisabledState();
}, }
changeDisabledState() { changeDisabledState() {
const editor = this._editor; const editor = this._editor;
@ -67,9 +69,10 @@ export default Component.extend({
}); });
editor.container.parentNode.setAttribute("data-disabled", disabled); editor.container.parentNode.setAttribute("data-disabled", disabled);
} }
}, }
_destroyEditor: on("willDestroyElement", function () { @on("willDestroyElement")
_destroyEditor() {
if (this._editor) { if (this._editor) {
this._editor.destroy(); this._editor.destroy();
this._editor = null; this._editor = null;
@ -80,16 +83,16 @@ export default Component.extend({
} }
$(window).off("ace:resize"); $(window).off("ace:resize");
}), }
resize() { resize() {
if (this._editor) { if (this._editor) {
this._editor.resize(); this._editor.resize();
} }
}, }
didInsertElement() { didInsertElement() {
this._super(...arguments); super.didInsertElement(...arguments);
loadScript("/javascripts/ace/ace.js").then(() => { loadScript("/javascripts/ace/ace.js").then(() => {
window.ace.require(["ace/ace"], (loadedAce) => { window.ace.require(["ace/ace"], (loadedAce) => {
loadedAce.config.set("loadWorkerFromBlob", false); loadedAce.config.set("loadWorkerFromBlob", false);
@ -153,13 +156,13 @@ export default Component.extend({
this._darkModeListener.addListener(this.setAceTheme); this._darkModeListener.addListener(this.setAceTheme);
}); });
}); });
}, }
willDestroyElement() { willDestroyElement() {
if (this._darkModeListener) { if (this._darkModeListener) {
this._darkModeListener.removeListener(this.setAceTheme); this._darkModeListener.removeListener(this.setAceTheme);
} }
}, }
@bind @bind
setAceTheme() { setAceTheme() {
@ -170,7 +173,7 @@ export default Component.extend({
this._editor.setTheme( this._editor.setTheme(
`ace/theme/${schemeType === "dark" ? "chaos" : "chrome"}` `ace/theme/${schemeType === "dark" ? "chaos" : "chrome"}`
); );
}, }
warnSCSSDeprecations() { warnSCSSDeprecations() {
if ( if (
@ -202,16 +205,15 @@ export default Component.extend({
? I18n.t("admin.customize.theme.scss_color_variables_warning") ? I18n.t("admin.customize.theme.scss_color_variables_warning")
: false : false
); );
}, }
actions: { @action
focus() { focus() {
if (this._editor) { if (this._editor) {
this._editor.focus(); this._editor.focus();
this._editor.navigateFileEnd(); this._editor.navigateFileEnd();
} }
}, }
},
_overridePlaceholder(loadedAce) { _overridePlaceholder(loadedAce) {
const originalPlaceholderSetter = const originalPlaceholderSetter =
@ -239,5 +241,5 @@ export default Component.extend({
this.$updatePlaceholder(); this.$updatePlaceholder();
}; };
}, }
}); }

View File

@ -1,28 +1,26 @@
import { classNames } from "@ember-decorators/component";
import { observes, on } from "discourse-common/utils/decorators"; import { observes, on } from "discourse-common/utils/decorators";
import Component from "@ember/component"; import Component from "@ember/component";
import I18n from "I18n"; import I18n from "I18n";
import discourseDebounce from "discourse-common/lib/debounce"; import discourseDebounce from "discourse-common/lib/debounce";
import { scheduleOnce } from "@ember/runloop"; import { scheduleOnce } from "@ember/runloop";
export default Component.extend({ @classNames("admin-backups-logs")
classNames: ["admin-backups-logs"], export default class AdminBackupsLogs extends Component {
showLoadingSpinner: false, showLoadingSpinner = false;
hasFormattedLogs: false, hasFormattedLogs = false;
noLogsMessage: I18n.t("admin.backups.logs.none"), noLogsMessage = I18n.t("admin.backups.logs.none");
formattedLogs = "";
init() { index = 0;
this._super(...arguments);
this._reset();
},
_reset() { _reset() {
this.setProperties({ formattedLogs: "", index: 0 }); this.setProperties({ formattedLogs: "", index: 0 });
}, }
_scrollDown() { _scrollDown() {
const div = this.element; const div = this.element;
div.scrollTop = div.scrollHeight; div.scrollTop = div.scrollHeight;
}, }
@on("init") @on("init")
@observes("logs.[]") @observes("logs.[]")
@ -31,7 +29,7 @@ export default Component.extend({
this._reset(); // reset the cached logs whenever the model is reset this._reset(); // reset the cached logs whenever the model is reset
this.renderLogs(); this.renderLogs();
} }
}, }
_updateFormattedLogsFunc() { _updateFormattedLogsFunc() {
const logs = this.logs; const logs = this.logs;
@ -55,13 +53,13 @@ export default Component.extend({
this.renderLogs(); this.renderLogs();
scheduleOnce("afterRender", this, this._scrollDown); scheduleOnce("afterRender", this, this._scrollDown);
}, }
@on("init") @on("init")
@observes("logs.[]") @observes("logs.[]")
_updateFormattedLogs() { _updateFormattedLogs() {
discourseDebounce(this, this._updateFormattedLogsFunc, 150); discourseDebounce(this, this._updateFormattedLogsFunc, 150);
}, }
renderLogs() { renderLogs() {
const formattedLogs = this.formattedLogs; const formattedLogs = this.formattedLogs;
@ -76,5 +74,5 @@ export default Component.extend({
} else { } else {
this.set("showLoadingSpinner", false); this.set("showLoadingSpinner", false);
} }
}, }
}); }

View File

@ -1,28 +1,22 @@
import { tagName } from "@ember-decorators/component";
import Component from "@ember/component"; import Component from "@ember/component";
import { action } from "@ember/object"; import { action } from "@ember/object";
export default Component.extend({ @tagName("")
tagName: "", export default class AdminEditableField extends Component {
buffer = "";
buffer: "", editing = false;
editing: false,
init() {
this._super(...arguments);
this.set("editing", false);
},
@action @action
edit(event) { edit(event) {
event?.preventDefault(); event?.preventDefault();
this.set("buffer", this.value); this.set("buffer", this.value);
this.toggleProperty("editing"); this.toggleProperty("editing");
}, }
actions: { @action
save() { save() {
// Action has to toggle 'editing' property. // Action has to toggle 'editing' property.
this.action(this.buffer); this.action(this.buffer);
}, }
}, }
});

View File

@ -1,4 +1,5 @@
import { classNames } from "@ember-decorators/component";
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({
classNames: ["row"], @classNames("row")
}); export default class AdminFormRow extends Component {}

View File

@ -1,9 +1,10 @@
import { tagName } from "@ember-decorators/component";
import Component from "@ember/component"; import Component from "@ember/component";
import loadScript from "discourse/lib/load-script"; import loadScript from "discourse/lib/load-script";
export default Component.extend({ @tagName("canvas")
tagName: "canvas", export default class AdminGraph extends Component {
type: "line", type = "line";
refreshChart() { refreshChart() {
const ctx = this.element.getContext("2d"); const ctx = this.element.getContext("2d");
@ -49,11 +50,11 @@ export default Component.extend({
}; };
this._chart = new window.Chart(ctx, config); this._chart = new window.Chart(ctx, config);
}, }
didInsertElement() { didInsertElement() {
loadScript("/javascripts/Chart.min.js").then(() => loadScript("/javascripts/Chart.min.js").then(() =>
this.refreshChart.apply(this) this.refreshChart.apply(this)
); );
}, }
}); }

View File

@ -1,4 +1,5 @@
import { tagName } from "@ember-decorators/component";
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({
tagName: "", @tagName("")
}); export default class AdminNav extends Component {}

View File

@ -1,16 +1,16 @@
import { classNames } from "@ember-decorators/component";
import Component from "@ember/component"; import Component from "@ember/component";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend({ @classNames("penalty-history")
classNames: ["penalty-history"], export default class AdminPenaltyHistory extends Component {
@discourseComputed("user.penalty_counts.suspended") @discourseComputed("user.penalty_counts.suspended")
suspendedCountClass(count) { suspendedCountClass(count) {
if (count > 0) { if (count > 0) {
return "danger"; return "danger";
} }
return ""; return "";
}, }
@discourseComputed("user.penalty_counts.silenced") @discourseComputed("user.penalty_counts.silenced")
silencedCountClass(count) { silencedCountClass(count) {
@ -18,5 +18,5 @@ export default Component.extend({
return "danger"; return "danger";
} }
return ""; return "";
}, }
}); }

View File

@ -1,5 +1,6 @@
import Component from "@ember/component"; import { action } from "@ember/object";
import { equal } from "@ember/object/computed"; import { equal } from "@ember/object/computed";
import Component from "@ember/component";
import discourseComputed, { import discourseComputed, {
afterRender, afterRender,
} from "discourse-common/utils/decorators"; } from "discourse-common/utils/decorators";
@ -7,21 +8,20 @@ import I18n from "I18n";
const ACTIONS = ["delete", "delete_replies", "edit", "none"]; const ACTIONS = ["delete", "delete_replies", "edit", "none"];
export default Component.extend({ export default class AdminPenaltyPostAction extends Component {
postId: null, postId = null;
postAction: null, postAction = null;
postEdit: null, postEdit = null;
@equal("postAction", "edit") editing;
@discourseComputed @discourseComputed
penaltyActions() { penaltyActions() {
return ACTIONS.map((id) => { return ACTIONS.map((id) => {
return { id, name: I18n.t(`admin.user.penalty_post_${id}`) }; return { id, name: I18n.t(`admin.user.penalty_post_${id}`) };
}); });
}, }
editing: equal("postAction", "edit"), @action
actions: {
penaltyChanged(postAction) { penaltyChanged(postAction) {
this.set("postAction", postAction); this.set("postAction", postAction);
@ -29,8 +29,7 @@ export default Component.extend({
if (postAction === "edit") { if (postAction === "edit") {
this._focusEditTextarea(); this._focusEditTextarea();
} }
}, }
},
@afterRender @afterRender
_focusEditTextarea() { _focusEditTextarea() {
@ -38,5 +37,5 @@ export default Component.extend({
const body = elem.closest(".modal-body"); const body = elem.closest(".modal-body");
body.scrollTo(0, body.clientHeight); body.scrollTo(0, body.clientHeight);
elem.querySelector(".post-editor").focus(); elem.querySelector(".post-editor").focus();
}, }
}); }

View File

@ -1,43 +1,46 @@
import { tagName } from "@ember-decorators/component";
import { equal } from "@ember/object/computed";
import Component from "@ember/component"; import Component from "@ember/component";
import { action } from "@ember/object"; import { action } from "@ember/object";
import { equal } from "@ember/object/computed";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import I18n from "I18n"; import I18n from "I18n";
const CUSTOM_REASON_KEY = "custom"; const CUSTOM_REASON_KEY = "custom";
export default Component.extend({ @tagName("")
tagName: "", export default class AdminPenaltyReason extends Component {
selectedReason: CUSTOM_REASON_KEY, selectedReason = CUSTOM_REASON_KEY;
customReason: "", customReason = "";
reasonKeys: [
reasonKeys = [
"not_listening_to_staff", "not_listening_to_staff",
"consuming_staff_time", "consuming_staff_time",
"combative", "combative",
"in_wrong_place", "in_wrong_place",
"no_constructive_purpose", "no_constructive_purpose",
CUSTOM_REASON_KEY, CUSTOM_REASON_KEY,
], ];
isCustomReason: equal("selectedReason", CUSTOM_REASON_KEY),
@equal("selectedReason", CUSTOM_REASON_KEY) isCustomReason;
@discourseComputed("reasonKeys") @discourseComputed("reasonKeys")
reasons(keys) { reasons(keys) {
return keys.map((key) => { return keys.map((key) => {
return { id: key, name: I18n.t(`admin.user.suspend_reasons.${key}`) }; return { id: key, name: I18n.t(`admin.user.suspend_reasons.${key}`) };
}); });
}, }
@action @action
setSelectedReason(value) { setSelectedReason(value) {
this.set("selectedReason", value); this.set("selectedReason", value);
this.setReason(); this.setReason();
}, }
@action @action
setCustomReason(value) { setCustomReason(value) {
this.set("customReason", value); this.set("customReason", value);
this.setReason(); this.setReason();
}, }
setReason() { setReason() {
if (this.isCustomReason) { if (this.isCustomReason) {
@ -48,5 +51,5 @@ export default Component.extend({
I18n.t(`admin.user.suspend_reasons.${this.selectedReason}`) I18n.t(`admin.user.suspend_reasons.${this.selectedReason}`)
); );
} }
}, }
}); }

View File

@ -1,10 +1,10 @@
import { tagName } from "@ember-decorators/component";
import Component from "@ember/component"; import Component from "@ember/component";
import { action } from "@ember/object"; import { action } from "@ember/object";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend({ @tagName("")
tagName: "", export default class AdminPenaltySimilarUsers extends Component {
@discourseComputed("penaltyType") @discourseComputed("penaltyType")
penaltyField(penaltyType) { penaltyField(penaltyType) {
if (penaltyType === "suspend") { if (penaltyType === "suspend") {
@ -12,7 +12,7 @@ export default Component.extend({
} else if (penaltyType === "silence") { } else if (penaltyType === "silence") {
return "can_be_silenced"; return "can_be_silenced";
} }
}, }
@action @action
selectUserId(userId, event) { selectUserId(userId, event) {
@ -25,5 +25,5 @@ export default Component.extend({
} else { } else {
this.selectedUserIds.removeObject(userId); this.selectedUserIds.removeObject(userId);
} }
}, }
}); }

View File

@ -1,3 +1,4 @@
import { classNames } from "@ember-decorators/component";
import Report from "admin/models/report"; import Report from "admin/models/report";
import Component from "@ember/component"; import Component from "@ember/component";
import discourseDebounce from "discourse-common/lib/debounce"; import discourseDebounce from "discourse-common/lib/debounce";
@ -7,31 +8,31 @@ import { number } from "discourse/lib/formatter";
import { schedule } from "@ember/runloop"; import { schedule } from "@ember/runloop";
import { bind } from "discourse-common/utils/decorators"; import { bind } from "discourse-common/utils/decorators";
export default Component.extend({ @classNames("admin-report-chart")
classNames: ["admin-report-chart"], export default class AdminReportChart extends Component {
limit: 8, limit = 8;
total: 0, total = 0;
options: null, options = null;
didInsertElement() { didInsertElement() {
this._super(...arguments); super.didInsertElement(...arguments);
window.addEventListener("resize", this._resizeHandler); window.addEventListener("resize", this._resizeHandler);
}, }
willDestroyElement() { willDestroyElement() {
this._super(...arguments); super.willDestroyElement(...arguments);
window.removeEventListener("resize", this._resizeHandler); window.removeEventListener("resize", this._resizeHandler);
this._resetChart(); this._resetChart();
}, }
didReceiveAttrs() { didReceiveAttrs() {
this._super(...arguments); super.didReceiveAttrs(...arguments);
discourseDebounce(this, this._scheduleChartRendering, 100); discourseDebounce(this, this._scheduleChartRendering, 100);
}, }
_scheduleChartRendering() { _scheduleChartRendering() {
schedule("afterRender", () => { schedule("afterRender", () => {
@ -40,7 +41,7 @@ export default Component.extend({
this.element && this.element.querySelector(".chart-canvas") this.element && this.element.querySelector(".chart-canvas")
); );
}); });
}, }
_renderChart(model, chartCanvas) { _renderChart(model, chartCanvas) {
if (!chartCanvas) { if (!chartCanvas) {
@ -99,7 +100,7 @@ export default Component.extend({
this._buildChartConfig(data, this.options) this._buildChartConfig(data, this.options)
); );
}); });
}, }
_buildChartConfig(data, options) { _buildChartConfig(data, options) {
return { return {
@ -161,21 +162,21 @@ export default Component.extend({
}, },
}, },
}; };
}, }
_resetChart() { _resetChart() {
if (this._chart) { if (this._chart) {
this._chart.destroy(); this._chart.destroy();
this._chart = null; this._chart = null;
} }
}, }
_applyChartGrouping(model, data, options) { _applyChartGrouping(model, data, options) {
return Report.collapse(model, data, options.chartGrouping); return Report.collapse(model, data, options.chartGrouping);
}, }
@bind @bind
_resizeHandler() { _resizeHandler() {
discourseDebounce(this, this._scheduleChartRendering, 500); discourseDebounce(this, this._scheduleChartRendering, 500);
}, }
}); }

View File

@ -1,6 +1,6 @@
import { attributeBindings, classNames } from "@ember-decorators/component";
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({
classNames: ["admin-report-counters"],
attributeBindings: ["model.description:title"], @classNames("admin-report-counters")
}); @attributeBindings("model.description:title")
export default class AdminReportCounters extends Component {}

View File

@ -1,11 +1,12 @@
import Component from "@ember/component"; import { classNameBindings, tagName } from "@ember-decorators/component";
import { match } from "@ember/object/computed"; import { match } from "@ember/object/computed";
export default Component.extend({ import Component from "@ember/component";
allTime: true,
tagName: "tr", @tagName("tr")
reverseColors: match( @classNameBindings("reverseColors")
"report.type", export default class AdminReportCounts extends Component {
/^(time_to_first_response|topics_with_no_response)$/ allTime = true;
),
classNameBindings: ["reverseColors"], @match("report.type", /^(time_to_first_response|topics_with_no_response)$/)
}); reverseColors;
}

View File

@ -1,4 +1,5 @@
import { classNames } from "@ember-decorators/component";
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({
classNames: ["admin-report-inline-table"], @classNames("admin-report-inline-table")
}); export default class AdminReportInlineTable extends Component {}

View File

@ -1,4 +1,5 @@
import { tagName } from "@ember-decorators/component";
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({
tagName: "tr", @tagName("tr")
}); export default class AdminReportPerDayCounts extends Component {}

View File

@ -1,3 +1,4 @@
import { classNames } from "@ember-decorators/component";
import Report from "admin/models/report"; import Report from "admin/models/report";
import Component from "@ember/component"; import Component from "@ember/component";
import discourseDebounce from "discourse-common/lib/debounce"; import discourseDebounce from "discourse-common/lib/debounce";
@ -7,32 +8,31 @@ import { number } from "discourse/lib/formatter";
import { schedule } from "@ember/runloop"; import { schedule } from "@ember/runloop";
import { bind } from "discourse-common/utils/decorators"; import { bind } from "discourse-common/utils/decorators";
export default Component.extend({ @classNames("admin-report-chart", "admin-report-stacked-chart")
classNames: ["admin-report-chart", "admin-report-stacked-chart"], export default class AdminReportStackedChart extends Component {
didInsertElement() { didInsertElement() {
this._super(...arguments); super.didInsertElement(...arguments);
window.addEventListener("resize", this._resizeHandler); window.addEventListener("resize", this._resizeHandler);
}, }
willDestroyElement() { willDestroyElement() {
this._super(...arguments); super.willDestroyElement(...arguments);
window.removeEventListener("resize", this._resizeHandler); window.removeEventListener("resize", this._resizeHandler);
this._resetChart(); this._resetChart();
}, }
didReceiveAttrs() { didReceiveAttrs() {
this._super(...arguments); super.didReceiveAttrs(...arguments);
discourseDebounce(this, this._scheduleChartRendering, 100); discourseDebounce(this, this._scheduleChartRendering, 100);
}, }
@bind @bind
_resizeHandler() { _resizeHandler() {
discourseDebounce(this, this._scheduleChartRendering, 500); discourseDebounce(this, this._scheduleChartRendering, 500);
}, }
_scheduleChartRendering() { _scheduleChartRendering() {
schedule("afterRender", () => { schedule("afterRender", () => {
@ -45,7 +45,7 @@ export default Component.extend({
this.element.querySelector(".chart-canvas") this.element.querySelector(".chart-canvas")
); );
}); });
}, }
_renderChart(model, chartCanvas) { _renderChart(model, chartCanvas) {
if (!chartCanvas) { if (!chartCanvas) {
@ -79,7 +79,7 @@ export default Component.extend({
this._chart = new window.Chart(context, this._buildChartConfig(data)); this._chart = new window.Chart(context, this._buildChartConfig(data));
}); });
}, }
_buildChartConfig(data) { _buildChartConfig(data) {
return { return {
@ -150,10 +150,10 @@ export default Component.extend({
}, },
}, },
}; };
}, }
_resetChart() { _resetChart() {
this._chart?.destroy(); this._chart?.destroy();
this._chart = null; this._chart = null;
}, }
}); }

View File

@ -1,43 +1,45 @@
import { classNames } from "@ember-decorators/component";
import { alias } from "@ember/object/computed";
import Component from "@ember/component"; import Component from "@ember/component";
import I18n from "I18n"; import I18n from "I18n";
import { alias } from "@ember/object/computed";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { setting } from "discourse/lib/computed"; import { setting } from "discourse/lib/computed";
export default Component.extend({ @classNames("admin-report-storage-stats")
classNames: ["admin-report-storage-stats"], export default class AdminReportStorageStats extends Component {
@setting("backup_location") backupLocation;
backupLocation: setting("backup_location"), @alias("model.data.backups") backupStats;
backupStats: alias("model.data.backups"),
uploadStats: alias("model.data.uploads"), @alias("model.data.uploads") uploadStats;
@discourseComputed("backupStats") @discourseComputed("backupStats")
showBackupStats(stats) { showBackupStats(stats) {
return stats && this.currentUser.admin; return stats && this.currentUser.admin;
}, }
@discourseComputed("backupLocation") @discourseComputed("backupLocation")
backupLocationName(backupLocation) { backupLocationName(backupLocation) {
return I18n.t(`admin.backups.location.${backupLocation}`); return I18n.t(`admin.backups.location.${backupLocation}`);
}, }
@discourseComputed("backupStats.used_bytes") @discourseComputed("backupStats.used_bytes")
usedBackupSpace(bytes) { usedBackupSpace(bytes) {
return I18n.toHumanSize(bytes); return I18n.toHumanSize(bytes);
}, }
@discourseComputed("backupStats.free_bytes") @discourseComputed("backupStats.free_bytes")
freeBackupSpace(bytes) { freeBackupSpace(bytes) {
return I18n.toHumanSize(bytes); return I18n.toHumanSize(bytes);
}, }
@discourseComputed("uploadStats.used_bytes") @discourseComputed("uploadStats.used_bytes")
usedUploadSpace(bytes) { usedUploadSpace(bytes) {
return I18n.toHumanSize(bytes); return I18n.toHumanSize(bytes);
}, }
@discourseComputed("uploadStats.free_bytes") @discourseComputed("uploadStats.free_bytes")
freeUploadSpace(bytes) { freeUploadSpace(bytes) {
return I18n.toHumanSize(bytes); return I18n.toHumanSize(bytes);
}, }
}); }

View File

@ -1,21 +1,27 @@
import Component from "@ember/component"; import {
attributeBindings,
classNameBindings,
classNames,
tagName,
} from "@ember-decorators/component";
import { alias } from "@ember/object/computed"; import { alias } from "@ember/object/computed";
import Component from "@ember/component";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend({ @tagName("td")
tagName: "td", @classNames("admin-report-table-cell")
classNames: ["admin-report-table-cell"], @classNameBindings("type", "property")
classNameBindings: ["type", "property"], @attributeBindings("value:title")
attributeBindings: ["value:title"], export default class AdminReportTableCell extends Component {
options: null, options = null;
@alias("label.type") type;
@alias("label.mainProperty") property;
@alias("computedLabel.formattedValue") formattedValue;
@alias("computedLabel.value") value;
@discourseComputed("label", "data", "options") @discourseComputed("label", "data", "options")
computedLabel(label, data, options) { computedLabel(label, data, options) {
return label.compute(data, options || {}); return label.compute(data, options || {});
}, }
}
type: alias("label.type"),
property: alias("label.mainProperty"),
formattedValue: alias("computedLabel.formattedValue"),
value: alias("computedLabel.value"),
});

View File

@ -1,19 +1,24 @@
import {
attributeBindings,
classNameBindings,
classNames,
tagName,
} from "@ember-decorators/component";
import Component from "@ember/component"; import Component from "@ember/component";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend({ @tagName("th")
tagName: "th", @classNames("admin-report-table-header")
classNames: ["admin-report-table-header"], @classNameBindings("label.mainProperty", "label.type", "isCurrentSort")
classNameBindings: ["label.mainProperty", "label.type", "isCurrentSort"], @attributeBindings("label.title:title")
attributeBindings: ["label.title:title"], export default class AdminReportTableHeader extends Component {
@discourseComputed("currentSortLabel.sortProperty", "label.sortProperty") @discourseComputed("currentSortLabel.sortProperty", "label.sortProperty")
isCurrentSort(currentSortField, labelSortField) { isCurrentSort(currentSortField, labelSortField) {
return currentSortField === labelSortField; return currentSortField === labelSortField;
}, }
@discourseComputed("currentSortDirection") @discourseComputed("currentSortDirection")
sortIcon(currentSortDirection) { sortIcon(currentSortDirection) {
return currentSortDirection === 1 ? "caret-up" : "caret-down"; return currentSortDirection === 1 ? "caret-up" : "caret-down";
}, }
}); }

View File

@ -1,6 +1,8 @@
import { classNames, tagName } from "@ember-decorators/component";
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({
tagName: "tr", @tagName("tr")
classNames: ["admin-report-table-row"], @classNames("admin-report-table-row")
options: null, export default class AdminReportTableRow extends Component {
}); options = null;
}

View File

@ -1,22 +1,26 @@
import Component from "@ember/component"; import { action } from "@ember/object";
import { classNameBindings, classNames } from "@ember-decorators/component";
import { alias } from "@ember/object/computed"; import { alias } from "@ember/object/computed";
import Component from "@ember/component";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { makeArray } from "discourse-common/lib/helpers"; import { makeArray } from "discourse-common/lib/helpers";
const PAGES_LIMIT = 8; const PAGES_LIMIT = 8;
export default Component.extend({ @classNameBindings("sortable", "twoColumns")
classNameBindings: ["sortable", "twoColumns"], @classNames("admin-report-table")
classNames: ["admin-report-table"], export default class AdminReportTable extends Component {
sortable: false, sortable = false;
sortDirection: 1, sortDirection = 1;
perPage: alias("options.perPage"),
page: 0, @alias("options.perPage") perPage;
page = 0;
@discourseComputed("model.computedLabels.length") @discourseComputed("model.computedLabels.length")
twoColumns(labelsLength) { twoColumns(labelsLength) {
return labelsLength === 2; return labelsLength === 2;
}, }
@discourseComputed( @discourseComputed(
"totalsForSample", "totalsForSample",
@ -31,12 +35,12 @@ export default Component.extend({
.reduce((s, v) => s + v, 0); .reduce((s, v) => s + v, 0);
return sum >= 1 && total && datesFiltering; return sum >= 1 && total && datesFiltering;
}, }
@discourseComputed("model.total", "options.total", "twoColumns") @discourseComputed("model.total", "options.total", "twoColumns")
showTotal(reportTotal, total, twoColumns) { showTotal(reportTotal, total, twoColumns) {
return reportTotal && total && twoColumns; return reportTotal && total && twoColumns;
}, }
@discourseComputed( @discourseComputed(
"model.{average,data}", "model.{average,data}",
@ -50,17 +54,17 @@ export default Component.extend({
sampleTotalValue && sampleTotalValue &&
hasTwoColumns hasTwoColumns
); );
}, }
@discourseComputed("totalsForSample.1.value", "model.data.length") @discourseComputed("totalsForSample.1.value", "model.data.length")
averageForSample(totals, count) { averageForSample(totals, count) {
return (totals / count).toFixed(0); return (totals / count).toFixed(0);
}, }
@discourseComputed("model.data.length") @discourseComputed("model.data.length")
showSortingUI(dataLength) { showSortingUI(dataLength) {
return dataLength >= 5; return dataLength >= 5;
}, }
@discourseComputed("totalsForSampleRow", "model.computedLabels") @discourseComputed("totalsForSampleRow", "model.computedLabels")
totalsForSample(row, labels) { totalsForSample(row, labels) {
@ -70,7 +74,7 @@ export default Component.extend({
computedLabel.property = label.mainProperty; computedLabel.property = label.mainProperty;
return computedLabel; return computedLabel;
}); });
}, }
@discourseComputed("model.data", "model.computedLabels") @discourseComputed("model.data", "model.computedLabels")
totalsForSampleRow(rows, labels) { totalsForSampleRow(rows, labels) {
@ -98,7 +102,7 @@ export default Component.extend({
}); });
return totalsRow; return totalsRow;
}, }
@discourseComputed("sortLabel", "sortDirection", "model.data.[]") @discourseComputed("sortLabel", "sortDirection", "model.data.[]")
sortedData(sortLabel, sortDirection, data) { sortedData(sortLabel, sortDirection, data) {
@ -118,7 +122,7 @@ export default Component.extend({
} }
return data; return data;
}, }
@discourseComputed("sortedData.[]", "perPage", "page") @discourseComputed("sortedData.[]", "perPage", "page")
paginatedData(data, perPage, page) { paginatedData(data, perPage, page) {
@ -128,7 +132,7 @@ export default Component.extend({
} }
return data; return data;
}, }
@discourseComputed("model.data", "perPage", "page") @discourseComputed("model.data", "perPage", "page")
pages(data, perPage, page) { pages(data, perPage, page) {
@ -156,19 +160,19 @@ export default Component.extend({
} }
return pages; return pages;
}, }
actions: { @action
changePage(page) { changePage(page) {
this.set("page", page); this.set("page", page);
}, }
@action
sortByLabel(label) { sortByLabel(label) {
if (this.sortLabel === label) { if (this.sortLabel === label) {
this.set("sortDirection", this.sortDirection === 1 ? -1 : 1); this.set("sortDirection", this.sortDirection === 1 ? -1 : 1);
} else { } else {
this.set("sortLabel", label); this.set("sortLabel", label);
} }
}, }
}, }
});

View File

@ -1,4 +1,5 @@
import { tagName } from "@ember-decorators/component";
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({
tagName: "tr", @tagName("tr")
}); export default class AdminReportTrustLevelCounts extends Component {}

View File

@ -1,6 +1,7 @@
import { classNameBindings, classNames } from "@ember-decorators/component";
import { alias, and, equal, notEmpty, or } from "@ember/object/computed";
import EmberObject, { action, computed } from "@ember/object"; import EmberObject, { action, computed } from "@ember/object";
import Report, { DAILY_LIMIT_DAYS, SCHEMA_VERSION } from "admin/models/report"; import Report, { DAILY_LIMIT_DAYS, SCHEMA_VERSION } from "admin/models/report";
import { alias, and, equal, notEmpty, or } from "@ember/object/computed";
import Component from "@ember/component"; import Component from "@ember/component";
import I18n from "I18n"; import I18n from "I18n";
import ReportLoader from "discourse/lib/reports-loader"; import ReportLoader from "discourse/lib/reports-loader";
@ -21,51 +22,58 @@ const TABLE_OPTIONS = {
const CHART_OPTIONS = {}; const CHART_OPTIONS = {};
export default Component.extend({ @classNameBindings(
classNameBindings: [
"isHidden:hidden", "isHidden:hidden",
"isHidden::is-visible", "isHidden::is-visible",
"isEnabled", "isEnabled",
"isLoading", "isLoading",
"dasherizedDataSourceName", "dasherizedDataSourceName"
], )
classNames: ["admin-report"], @classNames("admin-report")
isEnabled: true, export default class AdminReport extends Component {
disabledLabel: I18n.t("admin.dashboard.disabled"), isEnabled = true;
isLoading: false, disabledLabel = I18n.t("admin.dashboard.disabled");
rateLimitationString: null, isLoading = false;
dataSourceName: null, rateLimitationString = null;
report: null, dataSourceName = null;
model: null, report = null;
reportOptions: null, model = null;
forcedModes: null, reportOptions = null;
showAllReportsLink: false, forcedModes = null;
filters: null, showAllReportsLink = false;
showTrend: false, filters = null;
showHeader: true, showTrend = false;
showTitle: true, showHeader = true;
showFilteringUI: false, showTitle = true;
showDatesOptions: alias("model.dates_filtering"), showFilteringUI = false;
showRefresh: or("showDatesOptions", "model.available_filters.length"),
shouldDisplayTrend: and("showTrend", "model.prev_period"),
endDate: null,
startDate: null,
init() { @alias("model.dates_filtering") showDatesOptions;
this._super(...arguments);
this._reports = []; @or("showDatesOptions", "model.available_filters.length") showRefresh;
},
isHidden: computed("siteSettings.dashboard_hidden_reports", function () { @and("showTrend", "model.prev_period") shouldDisplayTrend;
endDate = null;
startDate = null;
@or("showTimeoutError", "showExceptionError", "showNotFoundError") showError;
@equal("model.error", "not_found") showNotFoundError;
@equal("model.error", "timeout") showTimeoutError;
@equal("model.error", "exception") showExceptionError;
@notEmpty("model.data") hasData;
_reports = [];
@computed("siteSettings.dashboard_hidden_reports")
get isHidden() {
return (this.siteSettings.dashboard_hidden_reports || "") return (this.siteSettings.dashboard_hidden_reports || "")
.split("|") .split("|")
.filter(Boolean) .filter(Boolean)
.includes(this.dataSourceName); .includes(this.dataSourceName);
}), }
didReceiveAttrs() { didReceiveAttrs() {
this._super(...arguments); super.didReceiveAttrs(...arguments);
let startDate = moment(); let startDate = moment();
if (this.filters && isPresent(this.filters.startDate)) { if (this.filters && isPresent(this.filters.startDate)) {
@ -88,42 +96,35 @@ export default Component.extend({
} else if (this.dataSourceName) { } else if (this.dataSourceName) {
this._fetchReport(); this._fetchReport();
} }
}, }
showError: or("showTimeoutError", "showExceptionError", "showNotFoundError"),
showNotFoundError: equal("model.error", "not_found"),
showTimeoutError: equal("model.error", "timeout"),
showExceptionError: equal("model.error", "exception"),
hasData: notEmpty("model.data"),
@discourseComputed("dataSourceName", "model.type") @discourseComputed("dataSourceName", "model.type")
dasherizedDataSourceName(dataSourceName, type) { dasherizedDataSourceName(dataSourceName, type) {
return (dataSourceName || type || "undefined").replace(/_/g, "-"); return (dataSourceName || type || "undefined").replace(/_/g, "-");
}, }
@discourseComputed("dataSourceName", "model.type") @discourseComputed("dataSourceName", "model.type")
dataSource(dataSourceName, type) { dataSource(dataSourceName, type) {
dataSourceName = dataSourceName || type; dataSourceName = dataSourceName || type;
return `/admin/reports/${dataSourceName}`; return `/admin/reports/${dataSourceName}`;
}, }
@discourseComputed("displayedModes.length") @discourseComputed("displayedModes.length")
showModes(displayedModesLength) { showModes(displayedModesLength) {
return displayedModesLength > 1; return displayedModesLength > 1;
}, }
@discourseComputed("currentMode") @discourseComputed("currentMode")
isChartMode(currentMode) { isChartMode(currentMode) {
return currentMode === "chart"; return currentMode === "chart";
}, }
@action @action
changeGrouping(grouping) { changeGrouping(grouping) {
this.send("refreshReport", { this.send("refreshReport", {
chartGrouping: grouping, chartGrouping: grouping,
}); });
}, }
@discourseComputed("currentMode", "model.modes", "forcedModes") @discourseComputed("currentMode", "model.modes", "forcedModes")
displayedModes(currentMode, reportModes, forcedModes) { displayedModes(currentMode, reportModes, forcedModes) {
@ -139,12 +140,12 @@ export default Component.extend({
icon: mode === "table" ? "table" : "signal", icon: mode === "table" ? "table" : "signal",
}; };
}); });
}, }
@discourseComputed("currentMode") @discourseComputed("currentMode")
modeComponent(currentMode) { modeComponent(currentMode) {
return `admin-report-${currentMode.replace(/_/g, "-")}`; return `admin-report-${currentMode.replace(/_/g, "-")}`;
}, }
@discourseComputed( @discourseComputed(
"dataSourceName", "dataSourceName",
@ -178,7 +179,7 @@ export default Component.extend({
.join(":"); .join(":");
return reportKey; return reportKey;
}, }
@discourseComputed("options.chartGrouping", "model.chartData.length") @discourseComputed("options.chartGrouping", "model.chartData.length")
chartGroupings(grouping, count) { chartGroupings(grouping, count) {
@ -192,7 +193,7 @@ export default Component.extend({
class: `chart-grouping ${grouping === id ? "active" : "inactive"}`, class: `chart-grouping ${grouping === id ? "active" : "inactive"}`,
}; };
}); });
}, }
@action @action
onChangeDateRange(range) { onChangeDateRange(range) {
@ -200,7 +201,7 @@ export default Component.extend({
startDate: range.from, startDate: range.from,
endDate: range.to, endDate: range.to,
}); });
}, }
@action @action
applyFilter(id, value) { applyFilter(id, value) {
@ -215,7 +216,7 @@ export default Component.extend({
this.send("refreshReport", { this.send("refreshReport", {
filters: customFilters, filters: customFilters,
}); });
}, }
@action @action
refreshReport(options = {}) { refreshReport(options = {}) {
@ -238,7 +239,7 @@ export default Component.extend({
? this.get("filters.customFilters") ? this.get("filters.customFilters")
: options.filters, : options.filters,
}); });
}, }
@action @action
exportCsv() { exportCsv() {
@ -254,7 +255,7 @@ export default Component.extend({
} }
exportEntity("report", args).then(outputExportResult); exportEntity("report", args).then(outputExportResult);
}, }
@action @action
onChangeMode(mode) { onChangeMode(mode) {
@ -263,7 +264,7 @@ export default Component.extend({
this.send("refreshReport", { this.send("refreshReport", {
chartGrouping: null, chartGrouping: null,
}); });
}, }
_computeReport() { _computeReport() {
if (!this.element || this.isDestroying || this.isDestroyed) { if (!this.element || this.isDestroying || this.isDestroyed) {
@ -306,7 +307,7 @@ export default Component.extend({
} }
this._renderReport(report, this.forcedModes, this.currentMode); this._renderReport(report, this.forcedModes, this.currentMode);
}, }
_renderReport(report, forcedModes, currentMode) { _renderReport(report, forcedModes, currentMode) {
const modes = forcedModes ? forcedModes.split(",") : report.modes; const modes = forcedModes ? forcedModes.split(",") : report.modes;
@ -317,11 +318,9 @@ export default Component.extend({
currentMode, currentMode,
options: this._buildOptions(currentMode, report), options: this._buildOptions(currentMode, report),
}); });
}, }
_fetchReport() { _fetchReport() {
this._super(...arguments);
this.setProperties({ isLoading: true, rateLimitationString: null }); this.setProperties({ isLoading: true, rateLimitationString: null });
next(() => { next(() => {
@ -349,7 +348,7 @@ export default Component.extend({
ReportLoader.enqueue(this.dataSourceName, payload.data, callback); ReportLoader.enqueue(this.dataSourceName, payload.data, callback);
}); });
}, }
_buildPayload(facets) { _buildPayload(facets) {
let payload = { data: { facets } }; let payload = { data: { facets } };
@ -375,7 +374,7 @@ export default Component.extend({
} }
return payload; return payload;
}, }
_buildOptions(mode, report) { _buildOptions(mode, report) {
if (mode === "table") { if (mode === "table") {
@ -393,7 +392,7 @@ export default Component.extend({
}) })
); );
} }
}, }
_loadReport(jsonReport) { _loadReport(jsonReport) {
Report.fillMissingDates(jsonReport, { filledField: "chartData" }); Report.fillMissingDates(jsonReport, { filledField: "chartData" });
@ -423,5 +422,5 @@ export default Component.extend({
} }
return Report.create(jsonReport); return Report.create(jsonReport);
}, }
}); }

View File

@ -6,8 +6,10 @@ import { isDocumentRTL } from "discourse/lib/text-direction";
import { action } from "@ember/object"; import { action } from "@ember/object";
import { next } from "@ember/runloop"; import { next } from "@ember/runloop";
export default Component.extend({ export default class AdminThemeEditor extends Component {
warning: null, warning = null;
@fmt("fieldName", "currentTargetName", "%@|%@") editorId;
@discourseComputed("theme.targets", "onlyOverridden", "showAdvanced") @discourseComputed("theme.targets", "onlyOverridden", "showAdvanced")
visibleTargets(targets, onlyOverridden, showAdvanced) { visibleTargets(targets, onlyOverridden, showAdvanced) {
@ -20,7 +22,7 @@ export default Component.extend({
} }
return target.edited; return target.edited;
}); });
}, }
@discourseComputed("currentTargetName", "onlyOverridden", "theme.fields") @discourseComputed("currentTargetName", "onlyOverridden", "theme.fields")
visibleFields(targetName, onlyOverridden, fields) { visibleFields(targetName, onlyOverridden, fields) {
@ -29,7 +31,7 @@ export default Component.extend({
fields = fields.filter((field) => field.edited); fields = fields.filter((field) => field.edited);
} }
return fields; return fields;
}, }
@discourseComputed("currentTargetName", "fieldName") @discourseComputed("currentTargetName", "fieldName")
activeSectionMode(targetName, fieldName) { activeSectionMode(targetName, fieldName) {
@ -43,7 +45,7 @@ export default Component.extend({
return "scss"; return "scss";
} }
return fieldName && fieldName.includes("scss") ? "scss" : "html"; return fieldName && fieldName.includes("scss") ? "scss" : "html";
}, }
@discourseComputed("currentTargetName", "fieldName") @discourseComputed("currentTargetName", "fieldName")
placeholder(targetName, fieldName) { placeholder(targetName, fieldName) {
@ -58,30 +60,27 @@ export default Component.extend({
}); });
} }
return ""; return "";
}, }
@discourseComputed("fieldName", "currentTargetName", "theme") @discourseComputed("fieldName", "currentTargetName", "theme")
activeSection: { get activeSection() {
get(fieldName, target, model) { return this.model.getField(this.currentTargetName, this.fieldName);
return model.getField(target, fieldName); }
},
set(value, fieldName, target, model) {
model.setField(target, fieldName, value);
return value;
},
},
editorId: fmt("fieldName", "currentTargetName", "%@|%@"), set activeSection(value) {
this.theme.setField(this.fieldName, value);
return value;
}
@discourseComputed("maximized") @discourseComputed("maximized")
maximizeIcon(maximized) { maximizeIcon(maximized) {
return maximized ? "discourse-compress" : "discourse-expand"; return maximized ? "discourse-compress" : "discourse-expand";
}, }
@discourseComputed("currentTargetName", "theme.targets") @discourseComputed("currentTargetName", "theme.targets")
showAddField(currentTargetName, targets) { showAddField(currentTargetName, targets) {
return targets.find((t) => t.name === currentTargetName).customNames; return targets.find((t) => t.name === currentTargetName).customNames;
}, }
@discourseComputed( @discourseComputed(
"currentTargetName", "currentTargetName",
@ -90,32 +89,33 @@ export default Component.extend({
) )
error(target, fieldName) { error(target, fieldName) {
return this.theme.getError(target, fieldName); return this.theme.getError(target, fieldName);
}, }
@action @action
toggleShowAdvanced(event) { toggleShowAdvanced(event) {
event?.preventDefault(); event?.preventDefault();
this.toggleProperty("showAdvanced"); this.toggleProperty("showAdvanced");
}, }
@action @action
toggleAddField(event) { toggleAddField(event) {
event?.preventDefault(); event?.preventDefault();
this.toggleProperty("addingField"); this.toggleProperty("addingField");
}, }
@action @action
toggleMaximize(event) { toggleMaximize(event) {
event?.preventDefault(); event?.preventDefault();
this.toggleProperty("maximized"); this.toggleProperty("maximized");
next(() => this.appEvents.trigger("ace:resize")); next(() => this.appEvents.trigger("ace:resize"));
}, }
actions: { @action
cancelAddField() { cancelAddField() {
this.set("addingField", false); this.set("addingField", false);
}, }
@action
addField(name) { addField(name) {
if (!name) { if (!name) {
return; return;
@ -124,18 +124,20 @@ export default Component.extend({
this.theme.setField(this.currentTargetName, name, ""); this.theme.setField(this.currentTargetName, name, "");
this.setProperties({ newFieldName: "", addingField: false }); this.setProperties({ newFieldName: "", addingField: false });
this.fieldAdded(this.currentTargetName, name); this.fieldAdded(this.currentTargetName, name);
}, }
@action
onlyOverriddenChanged(value) { onlyOverriddenChanged(value) {
this.onlyOverriddenChanged(value); this.onlyOverriddenChanged(value);
}, }
@action
save() { save() {
this.attrs.save(); this.attrs.save();
}, }
@action
setWarning(message) { setWarning(message) {
this.set("warning", message); this.set("warning", message);
}, }
}, }
});

View File

@ -1,23 +1,27 @@
import Component from "@ember/component"; import { classNames } from "@ember-decorators/component";
import { inject as service } from "@ember/service";
import { alias, equal } from "@ember/object/computed"; import { alias, equal } from "@ember/object/computed";
import Component from "@ember/component";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { action } from "@ember/object"; import { action } from "@ember/object";
import I18n from "I18n"; import I18n from "I18n";
import { inject as service } from "@ember/service";
export default Component.extend({ @classNames("watched-word")
classNames: ["watched-word"], export default class AdminWatchedWord extends Component {
dialog: service(), @service dialog;
isReplace: equal("actionKey", "replace"), @equal("actionKey", "replace") isReplace;
isTag: equal("actionKey", "tag"),
isLink: equal("actionKey", "link"), @equal("actionKey", "tag") isTag;
isCaseSensitive: alias("word.case_sensitive"),
@equal("actionKey", "link") isLink;
@alias("word.case_sensitive") isCaseSensitive;
@discourseComputed("word.replacement") @discourseComputed("word.replacement")
tags(replacement) { tags(replacement) {
return replacement.split(","); return replacement.split(",");
}, }
@action @action
deleteWord() { deleteWord() {
@ -33,5 +37,5 @@ export default Component.extend({
}) })
); );
}); });
}, }
}); }

View File

@ -1,14 +1,15 @@
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({
export default class AdminWrapper extends Component {
didInsertElement() { didInsertElement() {
this._super(...arguments); super.didInsertElement(...arguments);
document.querySelector("html").classList.add("admin-area"); document.querySelector("html").classList.add("admin-area");
document.querySelector("body").classList.add("admin-interface"); document.querySelector("body").classList.add("admin-interface");
}, }
willDestroyElement() { willDestroyElement() {
this._super(...arguments); super.willDestroyElement(...arguments);
document.querySelector("html").classList.remove("admin-area"); document.querySelector("html").classList.remove("admin-area");
document.querySelector("body").classList.remove("admin-interface"); document.querySelector("body").classList.remove("admin-interface");
}, }
}); }

View File

@ -1,4 +1,5 @@
import { tagName } from "@ember-decorators/component";
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({
tagName: "", @tagName("")
}); export default class CancelLink extends Component {}

View File

@ -1,3 +1,4 @@
import { classNames } from "@ember-decorators/component";
import { action, computed } from "@ember/object"; import { action, computed } from "@ember/object";
import Component from "@ember/component"; import Component from "@ember/component";
import { observes } from "discourse-common/utils/decorators"; import { observes } from "discourse-common/utils/decorators";
@ -9,20 +10,20 @@ import { observes } from "discourse-common/utils/decorators";
@param brightnessValue is a number from 0 to 255 representing the brightness of the color. See ColorSchemeColor. @param brightnessValue is a number from 0 to 255 representing the brightness of the color. See ColorSchemeColor.
@params valid is a boolean indicating if the input field is a valid color. @params valid is a boolean indicating if the input field is a valid color.
**/ **/
export default Component.extend({ @classNames("color-picker")
classNames: ["color-picker"], export default class ColorInput extends Component {
onlyHex = true;
styleSelection = true;
onlyHex: true, @computed("onlyHex")
get maxlength() {
styleSelection: true,
maxlength: computed("onlyHex", function () {
return this.onlyHex ? 6 : null; return this.onlyHex ? 6 : null;
}), }
normalizedHexValue: computed("hexValue", function () { @computed("hexValue")
get normalizedHexValue() {
return this.normalize(this.hexValue); return this.normalize(this.hexValue);
}), }
normalize(color) { normalize(color) {
if (this._valid(color)) { if (this._valid(color)) {
@ -40,19 +41,19 @@ export default Component.extend({
} }
} }
return color; return color;
}, }
@action @action
onHexInput(color) { onHexInput(color) {
if (this.attrs.onChangeColor) { if (this.attrs.onChangeColor) {
this.attrs.onChangeColor(this.normalize(color || "")); this.attrs.onChangeColor(this.normalize(color || ""));
} }
}, }
@action @action
onPickerInput(event) { onPickerInput(event) {
this.set("hexValue", event.target.value.replace("#", "")); this.set("hexValue", event.target.value.replace("#", ""));
}, }
@observes("hexValue", "brightnessValue", "valid") @observes("hexValue", "brightnessValue", "valid")
hexValueChanged() { hexValueChanged() {
@ -65,9 +66,9 @@ export default Component.extend({
if (this._valid()) { if (this._valid()) {
this.element.querySelector(".picker").value = this.normalize(hex); this.element.querySelector(".picker").value = this.normalize(hex);
} }
}, }
_valid(color = this.hexValue) { _valid(color = this.hexValue) {
return /^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(color); return /^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(color);
}, }
}); }

View File

@ -1,3 +1,3 @@
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({}); export default class DashboardNewFeatureItem extends Component {}

View File

@ -1,18 +1,19 @@
import { classNameBindings, classNames } from "@ember-decorators/component";
import Component from "@ember/component"; import Component from "@ember/component";
import { action, computed } from "@ember/object"; import { action, computed } from "@ember/object";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
export default Component.extend({ @classNames("section", "dashboard-new-features")
newFeatures: null, @classNameBindings("hasUnseenFeatures:ordered-first")
classNames: ["section", "dashboard-new-features"], export default class DashboardNewFeatures extends Component {
classNameBindings: ["hasUnseenFeatures:ordered-first"], newFeatures = null;
releaseNotesLink: null, releaseNotesLink = null;
init() { constructor() {
this._super(...arguments); super(...arguments);
ajax("/admin/dashboard/new-features.json").then((json) => { ajax("/admin/dashboard/new-features.json").then((json) => {
if (!this.element || this.isDestroying || this.isDestroyed) { if (this.isDestroying || this.isDestroyed) {
return; return;
} }
@ -22,16 +23,17 @@ export default Component.extend({
releaseNotesLink: json.release_notes_link, releaseNotesLink: json.release_notes_link,
}); });
}); });
}, }
columnCountClass: computed("newFeatures", function () { @computed("newFeatures")
get columnCountClass() {
return this.newFeatures.length > 2 ? "three-or-more-items" : ""; return this.newFeatures.length > 2 ? "three-or-more-items" : "";
}), }
@action @action
dismissNewFeatures() { dismissNewFeatures() {
ajax("/admin/dashboard/mark-new-features-as-seen.json", { ajax("/admin/dashboard/mark-new-features-as-seen.json", {
type: "PUT", type: "PUT",
}).then(() => this.set("hasUnseenFeatures", false)); }).then(() => this.set("hasUnseenFeatures", false));
}, }
}); }

View File

@ -1,3 +1,3 @@
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({}); export default class DashboardProblems extends Component {}

View File

@ -1,17 +1,19 @@
import { action, computed } from "@ember/object";
import { inject as service } from "@ember/service";
import { reads } from "@ember/object/computed";
import Component from "@ember/component"; import Component from "@ember/component";
import I18n from "I18n"; import I18n from "I18n";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { reads } from "@ember/object/computed";
import { inject as service } from "@ember/service";
export default Component.extend({ export default class EmailStylesEditor extends Component {
dialog: service(), @service dialog;
editorId: reads("fieldName"),
@reads("fieldName") editorId;
@discourseComputed("fieldName") @discourseComputed("fieldName")
currentEditorMode(fieldName) { currentEditorMode(fieldName) {
return fieldName === "css" ? "scss" : fieldName; return fieldName === "css" ? "scss" : fieldName;
}, }
@discourseComputed("fieldName", "styles.html", "styles.css") @discourseComputed("fieldName", "styles.html", "styles.css")
resetDisabled(fieldName) { resetDisabled(fieldName) {
@ -19,20 +21,19 @@ export default Component.extend({
this.get(`styles.${fieldName}`) === this.get(`styles.${fieldName}`) ===
this.get(`styles.default_${fieldName}`) this.get(`styles.default_${fieldName}`)
); );
}, }
@discourseComputed("styles", "fieldName") @computed("styles", "fieldName")
editorContents: { get editorContents() {
get(styles, fieldName) { return this.styles[this.fieldName];
return styles[fieldName]; }
},
set(value, styles, fieldName) { set editorContents(value) {
styles.setField(fieldName, value); this.styles.setField(this.fieldName, value);
return value; return value;
}, }
},
actions: { @action
reset() { reset() {
this.dialog.yesNoConfirm({ this.dialog.yesNoConfirm({
message: I18n.t("admin.customize.email_style.reset_confirm", { message: I18n.t("admin.customize.email_style.reset_confirm", {
@ -46,9 +47,10 @@ export default Component.extend({
this.notifyPropertyChange("editorContents"); this.notifyPropertyChange("editorContents");
}, },
}); });
}, }
@action
save() { save() {
this.attrs.save(); this.attrs.save();
}, }
}, }
});

View File

@ -1,43 +1,48 @@
import { action } from "@ember/object";
import { tagName } from "@ember-decorators/component";
import { inject as service } from "@ember/service";
import { or } from "@ember/object/computed";
import Category from "discourse/models/category"; import Category from "discourse/models/category";
import Component from "@ember/component"; import Component from "@ember/component";
import I18n from "I18n"; import I18n from "I18n";
import { bufferedProperty } from "discourse/mixins/buffered-content"; import { bufferedProperty } from "discourse/mixins/buffered-content";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { inject as service } from "@ember/service";
import { isEmpty } from "@ember/utils"; import { isEmpty } from "@ember/utils";
import { or } from "@ember/object/computed";
import { popupAjaxError } from "discourse/lib/ajax-error"; import { popupAjaxError } from "discourse/lib/ajax-error";
export default Component.extend(bufferedProperty("host"), { @tagName("tr")
editToggled: false, export default class EmbeddableHost extends Component.extend(
tagName: "tr", bufferedProperty("host")
categoryId: null, ) {
category: null, @service dialog;
dialog: service(), editToggled = false;
categoryId = null;
category = null;
editing: or("host.isNew", "editToggled"), @or("host.isNew", "editToggled") editing;
init() { constructor() {
this._super(...arguments); super(...arguments);
const host = this.host; const host = this.host;
const categoryId = host.category_id || this.site.uncategorized_category_id; const categoryId = host.category_id || this.site.uncategorized_category_id;
const category = Category.findById(categoryId); const category = Category.findById(categoryId);
host.set("category", category); host.set("category", category);
}, }
@discourseComputed("buffered.host", "host.isSaving") @discourseComputed("buffered.host", "host.isSaving")
cantSave(host, isSaving) { cantSave(host, isSaving) {
return isSaving || isEmpty(host); return isSaving || isEmpty(host);
}, }
actions: { @action
edit() { edit() {
this.set("categoryId", this.get("host.category.id")); this.set("categoryId", this.get("host.category.id"));
this.set("editToggled", true); this.set("editToggled", true);
}, }
@action
save() { save() {
if (this.cantSave) { if (this.cantSave) {
return; return;
@ -59,8 +64,9 @@ export default Component.extend(bufferedProperty("host"), {
this.set("editToggled", false); this.set("editToggled", false);
}) })
.catch(popupAjaxError); .catch(popupAjaxError);
}, }
@action
delete() { delete() {
return this.dialog.confirm({ return this.dialog.confirm({
message: I18n.t("admin.embedding.confirm_delete"), message: I18n.t("admin.embedding.confirm_delete"),
@ -70,8 +76,9 @@ export default Component.extend(bufferedProperty("host"), {
}); });
}, },
}); });
}, }
@action
cancel() { cancel() {
const host = this.host; const host = this.host;
if (host.get("isNew")) { if (host.get("isNew")) {
@ -80,6 +87,5 @@ export default Component.extend(bufferedProperty("host"), {
this.rollbackBuffer(); this.rollbackBuffer();
this.set("editToggled", false); this.set("editToggled", false);
} }
}, }
}, }
});

View File

@ -1,33 +1,33 @@
import { classNames } from "@ember-decorators/component";
import { computed } from "@ember/object";
import Component from "@ember/component"; import Component from "@ember/component";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { dasherize } from "@ember/string"; import { dasherize } from "@ember/string";
export default Component.extend({ @classNames("embed-setting")
classNames: ["embed-setting"], export default class EmbeddingSetting extends Component {
@discourseComputed("field") @discourseComputed("field")
inputId(field) { inputId(field) {
return dasherize(field); return dasherize(field);
}, }
@discourseComputed("field") @discourseComputed("field")
translationKey(field) { translationKey(field) {
return `admin.embedding.${field}`; return `admin.embedding.${field}`;
}, }
@discourseComputed("type") @discourseComputed("type")
isCheckbox(type) { isCheckbox(type) {
return type === "checkbox"; return type === "checkbox";
}, }
@computed("value")
get checked() {
return !!this.value;
}
@discourseComputed("value")
checked: {
get(value) {
return !!value;
},
set(value) { set(value) {
this.set("value", value); this.set("value", value);
return value; return value;
}, }
}, }
});

View File

@ -1,3 +1,4 @@
import { classNameBindings } from "@ember-decorators/component";
import Component from "@ember/component"; import Component from "@ember/component";
import I18n from "I18n"; import I18n from "I18n";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
@ -6,12 +7,12 @@ import { action, set, setProperties } from "@ember/object";
import { schedule } from "@ember/runloop"; import { schedule } from "@ember/runloop";
import discourseLater from "discourse-common/lib/later"; import discourseLater from "discourse-common/lib/later";
export default Component.extend({ @classNameBindings(":value-list", ":emoji-list")
classNameBindings: [":value-list", ":emoji-list"], export default class EmojiValueList extends Component {
values: null, values = null;
validationMessage: null, validationMessage = null;
emojiPickerIsActive: false, emojiPickerIsActive = false;
isEditorFocused: false, isEditorFocused = false;
@discourseComputed("values") @discourseComputed("values")
collection(values) { collection(values) {
@ -28,14 +29,14 @@ export default Component.extend({
emojiUrl: emojiUrlFor(value), emojiUrl: emojiUrlFor(value),
}; };
}); });
}, }
@action @action
closeEmojiPicker() { closeEmojiPicker() {
this.collection.setEach("isEditing", false); this.collection.setEach("isEditing", false);
this.set("emojiPickerIsActive", false); this.set("emojiPickerIsActive", false);
this.set("isEditorFocused", false); this.set("isEditorFocused", false);
}, }
@action @action
emojiSelected(code) { emojiSelected(code) {
@ -65,12 +66,12 @@ export default Component.extend({
this.set("emojiPickerIsActive", false); this.set("emojiPickerIsActive", false);
this.set("isEditorFocused", false); this.set("isEditorFocused", false);
}, }
@discourseComputed("collection") @discourseComputed("collection")
showUpDownButtons(collection) { showUpDownButtons(collection) {
return collection.length - 1 ? true : false; return collection.length - 1 ? true : false;
}, }
_splitValues(values) { _splitValues(values) {
if (values && values.length) { if (values && values.length) {
@ -91,7 +92,7 @@ export default Component.extend({
} else { } else {
return []; return [];
} }
}, }
@action @action
editValue(index) { editValue(index) {
@ -111,12 +112,12 @@ export default Component.extend({
} }
}, 100); }, 100);
}); });
}, }
@action @action
removeValue(value) { removeValue(value) {
this._removeValue(value); this._removeValue(value);
}, }
@action @action
shift(operation, index) { shift(operation, index) {
@ -133,7 +134,7 @@ export default Component.extend({
this.collection.insertAt(futureIndex, shiftedEmoji); this.collection.insertAt(futureIndex, shiftedEmoji);
this._saveValues(); this._saveValues();
}, }
_validateInput(input) { _validateInput(input) {
this.set("validationMessage", null); this.set("validationMessage", null);
@ -147,12 +148,12 @@ export default Component.extend({
} }
return true; return true;
}, }
_removeValue(value) { _removeValue(value) {
this.collection.removeObject(value); this.collection.removeObject(value);
this._saveValues(); this._saveValues();
}, }
_replaceValue(index, newValue) { _replaceValue(index, newValue) {
const item = this.collection[index]; const item = this.collection[index];
@ -161,9 +162,9 @@ export default Component.extend({
} }
set(item, "value", newValue); set(item, "value", newValue);
this._saveValues(); this._saveValues();
}, }
_saveValues() { _saveValues() {
this.set("values", this.collection.mapBy("value").join("|")); this.set("values", this.collection.mapBy("value").join("|"));
}, }
}); }

View File

@ -1,4 +1,5 @@
import { classNames } from "@ember-decorators/component";
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({
classNames: ["flag-user-lists"], @classNames("flag-user-lists")
}); export default class FlagUserLists extends Component {}

View File

@ -1,3 +1,3 @@
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({}); export default class FlagUser extends Component {}

View File

@ -2,10 +2,10 @@ import { observes, on } from "discourse-common/utils/decorators";
import Component from "@ember/component"; import Component from "@ember/component";
import highlightSyntax from "discourse/lib/highlight-syntax"; import highlightSyntax from "discourse/lib/highlight-syntax";
export default Component.extend({ export default class HighlightedCode extends Component {
@on("didInsertElement") @on("didInsertElement")
@observes("code") @observes("code")
_refresh() { _refresh() {
highlightSyntax(this.element, this.siteSettings, this.session); highlightSyntax(this.element, this.siteSettings, this.session);
}, }
}); }

View File

@ -1,15 +1,15 @@
import { classNames } from "@ember-decorators/component";
import Component from "@ember/component"; import Component from "@ember/component";
import { action } from "@ember/object"; import { action } from "@ember/object";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend({ @classNames("inline-edit")
classNames: ["inline-edit"], export default class InlineEditCheckbox extends Component {
buffer = null;
buffer: null, bufferModelId = null;
bufferModelId: null,
didReceiveAttrs() { didReceiveAttrs() {
this._super(...arguments); super.didReceiveAttrs(...arguments);
if (this.modelId !== this.bufferModelId) { if (this.modelId !== this.bufferModelId) {
// HACK: The condition above ensures this method is called only when its // HACK: The condition above ensures this method is called only when its
@ -24,21 +24,21 @@ export default Component.extend({
bufferModelId: this.modelId, bufferModelId: this.modelId,
}); });
} }
}, }
@discourseComputed("checked", "buffer") @discourseComputed("checked", "buffer")
changed(checked, buffer) { changed(checked, buffer) {
return !!checked !== !!buffer; return !!checked !== !!buffer;
}, }
@action @action
apply() { apply() {
this.set("checked", this.buffer); this.set("checked", this.buffer);
this.action(); this.action();
}, }
@action @action
cancel() { cancel() {
this.set("buffer", this.checked); this.set("buffer", this.checked);
}, }
}); }

View File

@ -1,4 +1,5 @@
import { classNames } from "@ember-decorators/component";
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({
classNames: ["install-theme-item"], @classNames("install-theme-item")
}); export default class InstallThemeItem extends Component {}

View File

@ -1,3 +1,5 @@
import { classNames } from "@ember-decorators/component";
import { inject as service } from "@ember/service";
import AdminUser from "admin/models/admin-user"; import AdminUser from "admin/models/admin-user";
import Component from "@ember/component"; import Component from "@ember/component";
import EmberObject, { action } from "@ember/object"; import EmberObject, { action } from "@ember/object";
@ -6,12 +8,11 @@ import { ajax } from "discourse/lib/ajax";
import copyText from "discourse/lib/copy-text"; import copyText from "discourse/lib/copy-text";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import discourseLater from "discourse-common/lib/later"; import discourseLater from "discourse-common/lib/later";
import { inject as service } from "@ember/service";
import { popupAjaxError } from "discourse/lib/ajax-error"; import { popupAjaxError } from "discourse/lib/ajax-error";
export default Component.extend({ @classNames("ip-lookup")
classNames: ["ip-lookup"], export default class IpLookup extends Component {
dialog: service(), @service dialog;
@discourseComputed("other_accounts.length", "totalOthersWithSameIP") @discourseComputed("other_accounts.length", "totalOthersWithSameIP")
otherAccountsToDelete(otherAccountsLength, totalOthersWithSameIP) { otherAccountsToDelete(otherAccountsLength, totalOthersWithSameIP) {
@ -19,24 +20,22 @@ export default Component.extend({
const total = Math.min(50, totalOthersWithSameIP || 0); const total = Math.min(50, totalOthersWithSameIP || 0);
const visible = Math.min(50, otherAccountsLength || 0); const visible = Math.min(50, otherAccountsLength || 0);
return Math.max(visible, total); return Math.max(visible, total);
}, }
@action @action
hide(event) { hide(event) {
event?.preventDefault(); event?.preventDefault();
this.set("show", false); this.set("show", false);
}, }
actions: { @action
lookup() { lookup() {
this.set("show", true); this.set("show", true);
if (!this.location) { if (!this.location) {
ajax("/admin/users/ip-info", { ajax("/admin/users/ip-info", {
data: { ip: this.ip }, data: { ip: this.ip },
}).then((location) => }).then((location) => this.set("location", EmberObject.create(location)));
this.set("location", EmberObject.create(location))
);
} }
if (!this.other_accounts) { if (!this.other_accounts) {
@ -59,8 +58,9 @@ export default Component.extend({
}); });
}); });
} }
}, }
@action
copy() { copy() {
let text = `IP: ${this.ip}\n`; let text = `IP: ${this.ip}\n`;
const location = this.location; const location = this.location;
@ -90,8 +90,9 @@ export default Component.extend({
discourseLater(() => this.set("copied", false), 2000); discourseLater(() => this.set("copied", false), 2000);
} }
$copyRange.remove(); $copyRange.remove();
}, }
@action
deleteOtherAccounts() { deleteOtherAccounts() {
this.dialog.yesNoConfirm({ this.dialog.yesNoConfirm({
message: I18n.t("ip_lookup.confirm_delete_other_accounts"), message: I18n.t("ip_lookup.confirm_delete_other_accounts"),
@ -114,6 +115,5 @@ export default Component.extend({
.finally(this.send("lookup")); .finally(this.send("lookup"));
}, },
}); });
}, }
}, }
});

View File

@ -1,4 +1,5 @@
import { tagName } from "@ember-decorators/component";
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({
tagName: "tr", @tagName("tr")
}); export default class ModerationHistoryItem extends Component {}

View File

@ -1,3 +1,5 @@
import { tagName } from "@ember-decorators/component";
import { inject as service } from "@ember/service";
import Component from "@ember/component"; import Component from "@ember/component";
import I18n from "I18n"; import I18n from "I18n";
import Permalink from "admin/models/permalink"; import Permalink from "admin/models/permalink";
@ -5,16 +7,18 @@ import discourseComputed, { bind } from "discourse-common/utils/decorators";
import { fmt } from "discourse/lib/computed"; import { fmt } from "discourse/lib/computed";
import { schedule } from "@ember/runloop"; import { schedule } from "@ember/runloop";
import { action } from "@ember/object"; import { action } from "@ember/object";
import { inject as service } from "@ember/service";
export default Component.extend({ @tagName("")
tagName: "", export default class PermalinkForm extends Component {
dialog: service(), @service dialog;
formSubmitted: false,
permalinkType: "topic_id", formSubmitted = false;
permalinkTypePlaceholder: fmt("permalinkType", "admin.permalink.%@"), permalinkType = "topic_id";
action: null,
permalinkTypeValue: null, @fmt("permalinkType", "admin.permalink.%@") permalinkTypePlaceholder;
action = null;
permalinkTypeValue = null;
@discourseComputed @discourseComputed
permalinkTypes() { permalinkTypes() {
@ -25,21 +29,21 @@ export default Component.extend({
{ id: "tag_name", name: I18n.t("admin.permalink.tag_name") }, { id: "tag_name", name: I18n.t("admin.permalink.tag_name") },
{ id: "external_url", name: I18n.t("admin.permalink.external_url") }, { id: "external_url", name: I18n.t("admin.permalink.external_url") },
]; ];
}, }
@bind @bind
focusPermalink() { focusPermalink() {
schedule("afterRender", () => schedule("afterRender", () =>
document.querySelector(".permalink-url")?.focus() document.querySelector(".permalink-url")?.focus()
); );
}, }
@action @action
submitFormOnEnter(event) { submitFormOnEnter(event) {
if (event.key === "Enter") { if (event.key === "Enter") {
this.onSubmit(); this.onSubmit();
} }
}, }
@action @action
onSubmit() { onSubmit() {
@ -84,5 +88,5 @@ export default Component.extend({
} }
); );
} }
}, }
}); }

View File

@ -1,16 +1,16 @@
import FilterComponent from "admin/components/report-filters/filter"; import FilterComponent from "admin/components/report-filters/filter";
import { action } from "@ember/object"; import { action } from "@ember/object";
export default FilterComponent.extend({ export default class Bool extends FilterComponent {
checked: false, checked = false;
didReceiveAttrs() { didReceiveAttrs() {
this._super(...arguments); super.didReceiveAttrs(...arguments);
this.set("checked", !!this.filter.default); this.set("checked", !!this.filter.default);
}, }
@action @action
onChange() { onChange() {
this.applyFilter(this.filter.id, !this.checked || undefined); this.applyFilter(this.filter.id, !this.checked || undefined);
}, }
}); }

View File

@ -1,12 +1,12 @@
import { readOnly } from "@ember/object/computed";
import FilterComponent from "admin/components/report-filters/filter"; import FilterComponent from "admin/components/report-filters/filter";
import { action } from "@ember/object"; import { action } from "@ember/object";
import { readOnly } from "@ember/object/computed";
export default FilterComponent.extend({ export default class Category extends FilterComponent {
category: readOnly("filter.default"), @readOnly("filter.default") category;
@action @action
onChange(categoryId) { onChange(categoryId) {
this.applyFilter(this.filter.id, categoryId || undefined); this.applyFilter(this.filter.id, categoryId || undefined);
}, }
}); }

View File

@ -1,9 +1,9 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { action } from "@ember/object"; import { action } from "@ember/object";
export default Component.extend({ export default class Filter extends Component {
@action @action
onChange(value) { onChange(value) {
this.applyFilter(this.filter.id, value); this.applyFilter(this.filter.id, value);
}, }
}); }

View File

@ -1,18 +1,18 @@
import FilterComponent from "admin/components/report-filters/filter"; import { classNames } from "@ember-decorators/component";
import { computed } from "@ember/object"; import { computed } from "@ember/object";
import FilterComponent from "admin/components/report-filters/filter";
export default FilterComponent.extend({ @classNames("group-filter")
classNames: ["group-filter"], export default class Group extends FilterComponent {
@computed @computed
get groupOptions() { get groupOptions() {
return (this.site.groups || []).map((group) => { return (this.site.groups || []).map((group) => {
return { name: group["name"], value: group["id"] }; return { name: group["name"], value: group["id"] };
}); });
}, }
@computed("filter.default") @computed("filter.default")
get groupId() { get groupId() {
return this.filter.default ? parseInt(this.filter.default, 10) : null; return this.filter.default ? parseInt(this.filter.default, 10) : null;
}, }
}); }

View File

@ -1,3 +1,3 @@
import FilterComponent from "admin/components/report-filters/filter"; import FilterComponent from "admin/components/report-filters/filter";
export default FilterComponent.extend(); export default class List extends FilterComponent {}

View File

@ -1,3 +1,3 @@
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({}); export default class ResumableUpload extends Component {}

View File

@ -17,7 +17,7 @@
<DButton <DButton
@type="submit" @type="submit"
@class="btn-default" @class="btn-default"
@action={{action "submit"}} @action={{action "submitForm"}}
@disabled={{this.formSubmitted}} @disabled={{this.formSubmitted}}
@label="admin.logs.screened_ips.form.add" @label="admin.logs.screened_ips.form.add"
/> />

View File

@ -1,9 +1,11 @@
import { action } from "@ember/object";
import { classNames, tagName } from "@ember-decorators/component";
import { inject as service } from "@ember/service";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import Component from "@ember/component"; import Component from "@ember/component";
import I18n from "I18n"; import I18n from "I18n";
import ScreenedIpAddress from "admin/models/screened-ip-address"; import ScreenedIpAddress from "admin/models/screened-ip-address";
import { schedule } from "@ember/runloop"; import { schedule } from "@ember/runloop";
import { inject as service } from "@ember/service";
/** /**
A form to create an IP address that will be blocked or allowed. A form to create an IP address that will be blocked or allowed.
@ -16,12 +18,13 @@ import { inject as service } from "@ember/service";
as an argument. as an argument.
**/ **/
export default Component.extend({ @tagName("form")
tagName: "form", @classNames("screened-ip-address-form", "inline-form")
dialog: service(), export default class ScreenedIpAddressForm extends Component {
classNames: ["screened-ip-address-form", "inline-form"], @service dialog;
formSubmitted: false,
actionName: "block", formSubmitted = false;
actionName = "block";
@discourseComputed("siteSettings.use_admin_ip_allowlist") @discourseComputed("siteSettings.use_admin_ip_allowlist")
actionNames(adminAllowlistEnabled) { actionNames(adminAllowlistEnabled) {
@ -46,16 +49,16 @@ export default Component.extend({
}, },
]; ];
} }
}, }
focusInput() { focusInput() {
schedule("afterRender", () => { schedule("afterRender", () => {
this.element.querySelector("input").focus(); this.element.querySelector("input").focus();
}); });
}, }
actions: { @action
submit() { submitForm() {
if (!this.formSubmitted) { if (!this.formSubmitted) {
this.set("formSubmitted", true); this.set("formSubmitted", true);
const screenedIpAddress = ScreenedIpAddress.create({ const screenedIpAddress = ScreenedIpAddress.create({
@ -83,6 +86,5 @@ export default Component.extend({
}); });
}); });
} }
}, }
}, }
});

View File

@ -1,15 +1,16 @@
import { classNameBindings } from "@ember-decorators/component";
import Component from "@ember/component"; import Component from "@ember/component";
import I18n from "I18n"; import I18n from "I18n";
import { isEmpty } from "@ember/utils"; import { isEmpty } from "@ember/utils";
import { on } from "discourse-common/utils/decorators"; import { on } from "discourse-common/utils/decorators";
import { set } from "@ember/object"; import { action, set } from "@ember/object";
export default Component.extend({ @classNameBindings(":value-list", ":secret-value-list")
classNameBindings: [":value-list", ":secret-value-list"], export default class SecretValueList extends Component {
inputDelimiter: null, inputDelimiter = null;
collection: null, collection = null;
values: null, values = null;
validationMessage: null, validationMessage = null;
@on("didReceiveAttrs") @on("didReceiveAttrs")
_setupCollection() { _setupCollection() {
@ -19,9 +20,9 @@ export default Component.extend({
"collection", "collection",
this._splitValues(values, this.inputDelimiter || "\n") this._splitValues(values, this.inputDelimiter || "\n")
); );
}, }
actions: { @action
changeKey(index, event) { changeKey(index, event) {
const newValue = event.target.value; const newValue = event.target.value;
@ -30,8 +31,9 @@ export default Component.extend({
} }
this._replaceValue(index, newValue, "key"); this._replaceValue(index, newValue, "key");
}, }
@action
changeSecret(index, event) { changeSecret(index, event) {
const newValue = event.target.value; const newValue = event.target.value;
@ -40,20 +42,21 @@ export default Component.extend({
} }
this._replaceValue(index, newValue, "secret"); this._replaceValue(index, newValue, "secret");
}, }
@action
addValue() { addValue() {
if (this._checkInvalidInput([this.newKey, this.newSecret])) { if (this._checkInvalidInput([this.newKey, this.newSecret])) {
return; return;
} }
this._addValue(this.newKey, this.newSecret); this._addValue(this.newKey, this.newSecret);
this.setProperties({ newKey: "", newSecret: "" }); this.setProperties({ newKey: "", newSecret: "" });
}, }
@action
removeValue(value) { removeValue(value) {
this._removeValue(value); this._removeValue(value);
}, }
},
_checkInvalidInput(inputs) { _checkInvalidInput(inputs) {
this.set("validationMessage", null); this.set("validationMessage", null);
@ -66,25 +69,25 @@ export default Component.extend({
return true; return true;
} }
} }
}, }
_addValue(value, secret) { _addValue(value, secret) {
this.collection.addObject({ key: value, secret }); this.collection.addObject({ key: value, secret });
this._saveValues(); this._saveValues();
}, }
_removeValue(value) { _removeValue(value) {
const collection = this.collection; const collection = this.collection;
collection.removeObject(value); collection.removeObject(value);
this._saveValues(); this._saveValues();
}, }
_replaceValue(index, newValue, keyName) { _replaceValue(index, newValue, keyName) {
let item = this.collection[index]; let item = this.collection[index];
set(item, keyName, newValue); set(item, keyName, newValue);
this._saveValues(); this._saveValues();
}, }
_saveValues() { _saveValues() {
this.set( this.set(
@ -95,7 +98,7 @@ export default Component.extend({
}) })
.join("\n") .join("\n")
); );
}, }
_splitValues(values, delimiter) { _splitValues(values, delimiter) {
if (values && values.length) { if (values && values.length) {
@ -113,5 +116,5 @@ export default Component.extend({
} else { } else {
return []; return [];
} }
}, }
}); }

View File

@ -1,3 +1,3 @@
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({}); export default class SettingValidationMessage extends Component {}

View File

@ -1,4 +1,5 @@
import { tagName } from "@ember-decorators/component";
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({
tagName: "", @tagName("")
}); export default class SilenceDetails extends Component {}

View File

@ -1,34 +1,36 @@
import { classNameBindings } from "@ember-decorators/component";
import { empty } from "@ember/object/computed";
import Component from "@ember/component"; import Component from "@ember/component";
import { action } from "@ember/object"; import { action } from "@ember/object";
import { empty } from "@ember/object/computed";
import discourseComputed, { on } from "discourse-common/utils/decorators"; import discourseComputed, { on } from "discourse-common/utils/decorators";
export default Component.extend({ @classNameBindings(":simple-list", ":value-list")
classNameBindings: [":simple-list", ":value-list"], export default class SimpleList extends Component {
inputEmpty: empty("newValue"), @empty("newValue") inputEmpty;
inputDelimiter: null,
newValue: "", inputDelimiter = null;
collection: null, newValue = "";
values: null, collection = null;
values = null;
@on("didReceiveAttrs") @on("didReceiveAttrs")
_setupCollection() { _setupCollection() {
this.set("collection", this._splitValues(this.values, this.inputDelimiter)); this.set("collection", this._splitValues(this.values, this.inputDelimiter));
}, }
keyDown(event) { keyDown(event) {
if (event.which === 13) { if (event.which === 13) {
this.addValue(this.newValue); this.addValue(this.newValue);
return; return;
} }
}, }
@action @action
changeValue(index, event) { changeValue(index, event) {
this.collection.replace(index, 1, [event.target.value]); this.collection.replace(index, 1, [event.target.value]);
this.collection.arrayContentDidChange(index); this.collection.arrayContentDidChange(index);
this._onChange(); this._onChange();
}, }
@action @action
addValue(newValue) { addValue(newValue) {
@ -39,13 +41,13 @@ export default Component.extend({
this.set("newValue", null); this.set("newValue", null);
this.collection.addObject(newValue); this.collection.addObject(newValue);
this._onChange(); this._onChange();
}, }
@action @action
removeValue(value) { removeValue(value) {
this.collection.removeObject(value); this.collection.removeObject(value);
this._onChange(); this._onChange();
}, }
@action @action
shift(operation, index) { shift(operation, index) {
@ -62,20 +64,20 @@ export default Component.extend({
this.collection.insertAt(futureIndex, shiftedValue); this.collection.insertAt(futureIndex, shiftedValue);
this._onChange(); this._onChange();
}, }
_onChange() { _onChange() {
this.onChange?.(this.collection); this.onChange?.(this.collection);
}, }
@discourseComputed("collection") @discourseComputed("collection")
showUpDownButtons(collection) { showUpDownButtons(collection) {
return collection.length - 1 ? true : false; return collection.length - 1 ? true : false;
}, }
_splitValues(values, delimiter) { _splitValues(values, delimiter) {
return values && values.length return values && values.length
? values.split(delimiter || "\n").filter(Boolean) ? values.split(delimiter || "\n").filter(Boolean)
: []; : [];
}, }
}); }

View File

@ -1,3 +1,3 @@
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({}); export default class SiteCustomizationChangeDetails extends Component {}

View File

@ -1,3 +1,3 @@
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({}); export default class SiteCustomizationChangeField extends Component {}

View File

@ -1,18 +1,21 @@
import { readOnly } from "@ember/object/computed";
import BufferedContent from "discourse/mixins/buffered-content"; import BufferedContent from "discourse/mixins/buffered-content";
import Component from "@ember/component"; import Component from "@ember/component";
import SettingComponent from "admin/mixins/setting-component"; import SettingComponent from "admin/mixins/setting-component";
import SiteSetting from "admin/models/site-setting"; import SiteSetting from "admin/models/site-setting";
import { readOnly } from "@ember/object/computed";
export default Component.extend(BufferedContent, SettingComponent, { export default class SiteSettingComponent extends Component.extend(
updateExistingUsers: null, BufferedContent,
SettingComponent
) {
updateExistingUsers = null;
@readOnly("setting.staffLogFilter") staffLogFilter;
_save() { _save() {
const setting = this.buffered; const setting = this.buffered;
return SiteSetting.update(setting.get("setting"), setting.get("value"), { return SiteSetting.update(setting.get("setting"), setting.get("value"), {
updateExistingUsers: this.updateExistingUsers, updateExistingUsers: this.updateExistingUsers,
}); });
}, }
}
staffLogFilter: readOnly("setting.staffLogFilter"),
});

View File

@ -1,19 +1,18 @@
import { computed } from "@ember/object";
import Component from "@ember/component"; import Component from "@ember/component";
import discourseComputed from "discourse-common/utils/decorators";
import { isEmpty } from "@ember/utils"; import { isEmpty } from "@ember/utils";
export default Component.extend({ export default class Bool extends Component {
@discourseComputed("value") @computed("value")
enabled: { get enabled() {
get(value) { if (isEmpty(this.value)) {
if (isEmpty(value)) {
return false; return false;
} }
return value.toString() === "true"; return this.value.toString() === "true";
}, }
set(value) {
set enabled(value) {
this.set("value", value ? "true" : "false"); this.set("value", value ? "true" : "false");
return value; return value;
}, }
}, }
});

View File

@ -1,15 +1,15 @@
import { action, computed } from "@ember/object";
import Category from "discourse/models/category"; import Category from "discourse/models/category";
import Component from "@ember/component"; import Component from "@ember/component";
import { computed } from "@ember/object";
export default Component.extend({ export default class CategoryList extends Component {
selectedCategories: computed("value", function () { @computed("value")
get selectedCategories() {
return Category.findByIds(this.value.split("|").filter(Boolean)); return Category.findByIds(this.value.split("|").filter(Boolean));
}), }
actions: { @action
onChangeSelectedCategories(value) { onChangeSelectedCategories(value) {
this.set("value", (value || []).mapBy("id").join("|")); this.set("value", (value || []).mapBy("id").join("|"));
}, }
}, }
});

View File

@ -1,3 +1,3 @@
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({}); export default class Category extends Component {}

View File

@ -24,8 +24,9 @@ function RGBToHex(rgb) {
return "#" + r + g + b; return "#" + r + g + b;
} }
export default Component.extend({ export default class Color extends Component {
valid: computed("value", function () { @computed("value")
get valid() {
let value = this.value.toLowerCase(); let value = this.value.toLowerCase();
let testColor = new Option().style; let testColor = new Option().style;
@ -43,10 +44,10 @@ export default Component.extend({
} }
return testColor.color && hexifiedColor === value; return testColor.color && hexifiedColor === value;
}), }
@action @action
onChangeColor(color) { onChangeColor(color) {
this.set("value", color); this.set("value", color);
}, }
}); }

View File

@ -1,21 +1,18 @@
import { action, computed } from "@ember/object";
import Component from "@ember/component"; import Component from "@ember/component";
import { computed } from "@ember/object";
import { makeArray } from "discourse-common/lib/helpers"; import { makeArray } from "discourse-common/lib/helpers";
export default Component.extend({ export default class CompactList extends Component {
tokenSeparator: "|", tokenSeparator = "|";
createdChoices = null;
createdChoices: null, @computed("value")
get settingValue() {
settingValue: computed("value", function () {
return this.value.toString().split(this.tokenSeparator).filter(Boolean); return this.value.toString().split(this.tokenSeparator).filter(Boolean);
}), }
settingChoices: computed( @computed("settingValue", "setting.choices.[]", "createdChoices.[]")
"settingValue", get settingChoices() {
"setting.choices.[]",
"createdChoices.[]",
function () {
return [ return [
...new Set([ ...new Set([
...makeArray(this.settingValue), ...makeArray(this.settingValue),
@ -24,17 +21,16 @@ export default Component.extend({
]), ]),
]; ];
} }
),
actions: { @action
onChangeListSetting(value) { onChangeListSetting(value) {
this.set("value", value.join(this.tokenSeparator)); this.set("value", value.join(this.tokenSeparator));
}, }
@action
onChangeChoices(choices) { onChangeChoices(choices) {
this.set("createdChoices", [ this.set("createdChoices", [
...new Set([...makeArray(this.createdChoices), ...makeArray(choices)]), ...new Set([...makeArray(this.createdChoices), ...makeArray(choices)]),
]); ]);
}, }
}, }
});

View File

@ -1,3 +1,3 @@
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({}); export default class EmojiList extends Component {}

View File

@ -1,3 +1,3 @@
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({}); export default class Enum extends Component {}

View File

@ -1,25 +1,25 @@
import { action, computed } from "@ember/object";
import Component from "@ember/component"; import Component from "@ember/component";
import { computed } from "@ember/object";
export default Component.extend({ export default class GroupList extends Component {
tokenSeparator: "|", tokenSeparator = "|";
nameProperty = "name";
valueProperty = "id";
nameProperty: "name", @computed("site.groups")
valueProperty: "id", get groupChoices() {
groupChoices: computed("site.groups", function () {
return (this.site.groups || []).map((g) => { return (this.site.groups || []).map((g) => {
return { name: g.name, id: g.id.toString() }; return { name: g.name, id: g.id.toString() };
}); });
}), }
settingValue: computed("value", function () { @computed("value")
get settingValue() {
return (this.value || "").split(this.tokenSeparator).filter(Boolean); return (this.value || "").split(this.tokenSeparator).filter(Boolean);
}), }
actions: { @action
onChangeGroupListSetting(value) { onChangeGroupListSetting(value) {
this.set("value", value.join(this.tokenSeparator)); this.set("value", value.join(this.tokenSeparator));
}, }
}, }
});

View File

@ -1,14 +1,14 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { action, computed } from "@ember/object"; import { action, computed } from "@ember/object";
export default Component.extend({ export default class HostList extends Component {
tokenSeparator: "|", tokenSeparator = "|";
choices: null, choices = null;
@computed("value") @computed("value")
get settingValue() { get settingValue() {
return this.value.toString().split(this.tokenSeparator).filter(Boolean); return this.value.toString().split(this.tokenSeparator).filter(Boolean);
}, }
@action @action
onChange(value) { onChange(value) {
@ -17,5 +17,5 @@ export default Component.extend({
} }
this.set("value", value.join(this.tokenSeparator)); this.set("value", value.join(this.tokenSeparator));
}, }
}); }

View File

@ -1,3 +1,3 @@
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({}); export default class List extends Component {}

View File

@ -1,13 +1,13 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { action, computed } from "@ember/object"; import { action, computed } from "@ember/object";
export default Component.extend({ export default class NamedList extends Component {
tokenSeparator: "|", tokenSeparator = "|";
@computed("value") @computed("value")
get settingValue() { get settingValue() {
return this.value.toString().split(this.tokenSeparator).filter(Boolean); return this.value.toString().split(this.tokenSeparator).filter(Boolean);
}, }
@computed("setting.choices.[]", "settingValue") @computed("setting.choices.[]", "settingValue")
get settingChoices() { get settingChoices() {
@ -24,10 +24,10 @@ export default Component.extend({
} }
return choices; return choices;
}, }
@action @action
onChangeListSetting(value) { onChangeListSetting(value) {
this.set("value", value.join(this.tokenSeparator)); this.set("value", value.join(this.tokenSeparator));
}, }
}); }

View File

@ -1,3 +1,3 @@
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({}); export default class SecretList extends Component {}

View File

@ -1,11 +1,11 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { action } from "@ember/object"; import { action } from "@ember/object";
export default Component.extend({ export default class SimpleList extends Component {
inputDelimiter: "|", inputDelimiter = "|";
@action @action
onChange(value) { onChange(value) {
this.set("value", value.join(this.inputDelimiter || "\n")); this.set("value", value.join(this.inputDelimiter || "\n"));
}, }
}); }

View File

@ -2,7 +2,7 @@ import { action } from "@ember/object";
import Component from "@ember/component"; import Component from "@ember/component";
import showModal from "discourse/lib/show-modal"; import showModal from "discourse/lib/show-modal";
export default Component.extend({ export default class String extends Component {
@action @action
launchJsonEditorModal() { launchJsonEditorModal() {
const schemaModal = showModal("json-schema-editor", { const schemaModal = showModal("json-schema-editor", {
@ -16,5 +16,5 @@ export default Component.extend({
schemaModal.set("onClose", () => { schemaModal.set("onClose", () => {
this.set("value", schemaModal.model.value); this.set("value", schemaModal.model.value);
}); });
}, }
}); }

View File

@ -2,16 +2,14 @@ import Component from "@ember/component";
import { action } from "@ember/object"; import { action } from "@ember/object";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend({ export default class TagList extends Component {
@discourseComputed("value") @discourseComputed("value")
selectedTags: { selectedTags(value) {
get(value) {
return value.split("|").filter(Boolean); return value.split("|").filter(Boolean);
}, }
},
@action @action
changeSelectedTags(tags) { changeSelectedTags(tags) {
this.set("value", tags.join("|")); this.set("value", tags.join("|"));
}, }
}); }

View File

@ -1,3 +1,3 @@
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({}); export default class Upload extends Component {}

View File

@ -1,8 +1,9 @@
import { action } from "@ember/object";
import Component from "@ember/component"; import Component from "@ember/component";
import showModal from "discourse/lib/show-modal"; import showModal from "discourse/lib/show-modal";
export default Component.extend({ export default class UploadedImageList extends Component {
actions: { @action
showUploadModal({ value, setting }) { showUploadModal({ value, setting }) {
showModal("admin-uploaded-image-list", { showModal("admin-uploaded-image-list", {
admin: true, admin: true,
@ -11,6 +12,5 @@ export default Component.extend({
}).setProperties({ }).setProperties({
save: (v) => this.set("value", v), save: (v) => this.set("value", v),
}); });
}, }
}, }
});

View File

@ -1,3 +1,3 @@
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({}); export default class UrlList extends Component {}

View File

@ -1,3 +1,3 @@
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({}); export default class ValueList extends Component {}

View File

@ -1,11 +1,11 @@
import { classNameBindings, classNames } from "@ember-decorators/component";
import Component from "@ember/component"; import Component from "@ember/component";
import highlightHTML from "discourse/lib/highlight-html"; import highlightHTML from "discourse/lib/highlight-html";
import { on } from "discourse-common/utils/decorators"; import { on } from "discourse-common/utils/decorators";
export default Component.extend({ @classNames("site-text")
classNames: ["site-text"], @classNameBindings("siteText.overridden")
classNameBindings: ["siteText.overridden"], export default class SiteTextSummary extends Component {
@on("didInsertElement") @on("didInsertElement")
highlightTerm() { highlightTerm() {
const term = this._searchTerm(); const term = this._searchTerm();
@ -19,11 +19,11 @@ export default Component.extend({
} }
); );
} }
}, }
click() { click() {
this.editAction(this.siteText); this.editAction(this.siteText);
}, }
_searchTerm() { _searchTerm() {
const regex = this.searchRegex; const regex = this.searchRegex;
@ -37,5 +37,5 @@ export default Component.extend({
} }
return this.term; return this.term;
}, }
}); }

View File

@ -1,10 +1,10 @@
import { tagName } from "@ember-decorators/component";
import { action } from "@ember/object"; import { action } from "@ember/object";
import Component from "@ember/component"; import Component from "@ember/component";
import DiscourseURL from "discourse/lib/url"; import DiscourseURL from "discourse/lib/url";
export default Component.extend({ @tagName("")
tagName: "", export default class StaffActions extends Component {
@action @action
openLinks(event) { openLinks(event) {
const dataset = event.target.dataset; const dataset = event.target.dataset;
@ -20,5 +20,5 @@ export default Component.extend({
DiscourseURL.routeTo(`/t/${dataset.linkTopicId}`); DiscourseURL.routeTo(`/t/${dataset.linkTopicId}`);
} }
}, }
}); }

View File

@ -1,24 +1,27 @@
import { inject as service } from "@ember/service";
import { alias } from "@ember/object/computed";
import Component from "@ember/component"; import Component from "@ember/component";
import I18n from "I18n"; import I18n from "I18n";
import UppyUploadMixin from "discourse/mixins/uppy-upload"; import UppyUploadMixin from "discourse/mixins/uppy-upload";
import { alias } from "@ember/object/computed";
import { inject as service } from "@ember/service";
export default Component.extend(UppyUploadMixin, { export default class TagsUploader extends Component.extend(UppyUploadMixin) {
type: "csv", @service dialog;
dialog: service(), type = "csv";
uploadUrl: "/tags/upload",
addDisabled: alias("uploading"), uploadUrl = "/tags/upload";
elementId: "tag-uploader",
preventDirectS3Uploads: true, @alias("uploading") addDisabled;
elementId = "tag-uploader";
preventDirectS3Uploads = true;
validateUploadedFilesOptions() { validateUploadedFilesOptions() {
return { csvOnly: true }; return { csvOnly: true };
}, }
uploadDone() { uploadDone() {
this.closeModal(); this.closeModal();
this.refresh(); this.refresh();
this.dialog.alert(I18n.t("tagging.upload_successful")); this.dialog.alert(I18n.t("tagging.upload_successful"));
}, }
}); }

View File

@ -3,9 +3,10 @@ import { alias } from "@ember/object/computed";
export default class ThemeTranslation extends SiteSettingComponent { export default class ThemeTranslation extends SiteSettingComponent {
@alias("translation") setting; @alias("translation") setting;
type = "string";
@alias("translation.key") settingName; @alias("translation.key") settingName;
type = "string";
_save() { _save() {
return this.model.saveTranslation( return this.model.saveTranslation(
this.get("translation.key"), this.get("translation.key"),

View File

@ -1,3 +1,4 @@
import { classNameBindings, classNames } from "@ember-decorators/component";
import { and, gt } from "@ember/object/computed"; import { and, gt } from "@ember/object/computed";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import Component from "@ember/component"; import Component from "@ember/component";
@ -7,19 +8,22 @@ import { action } from "@ember/object";
const MAX_COMPONENTS = 4; const MAX_COMPONENTS = 4;
export default Component.extend({ @classNames("themes-list-item")
childrenExpanded: false, @classNameBindings("theme.selected:selected")
classNames: ["themes-list-item"], export default class ThemesListItem extends Component {
classNameBindings: ["theme.selected:selected"], childrenExpanded = false;
hasComponents: gt("children.length", 0),
displayComponents: and("hasComponents", "theme.isActive"), @gt("children.length", 0) hasComponents;
displayHasMore: gt("theme.childThemes.length", MAX_COMPONENTS),
@and("hasComponents", "theme.isActive") displayComponents;
@gt("theme.childThemes.length", MAX_COMPONENTS) displayHasMore;
click(e) { click(e) {
if (!e.target.classList.contains("others-count")) { if (!e.target.classList.contains("others-count")) {
this.navigateToTheme(); this.navigateToTheme();
} }
}, }
@discourseComputed( @discourseComputed(
"theme.component", "theme.component",
@ -40,12 +44,12 @@ export default Component.extend({
const name = escape(t.name); const name = escape(t.name);
return t.enabled ? name : `${iconHTML("ban")} ${name}`; return t.enabled ? name : `${iconHTML("ban")} ${name}`;
}); });
}, }
@discourseComputed("children") @discourseComputed("children")
childrenString(children) { childrenString(children) {
return children.join(", "); return children.join(", ");
}, }
@discourseComputed( @discourseComputed(
"theme.childThemes.length", "theme.childThemes.length",
@ -58,11 +62,11 @@ export default Component.extend({
return 0; return 0;
} }
return childrenCount - MAX_COMPONENTS; return childrenCount - MAX_COMPONENTS;
}, }
@action @action
toggleChildrenExpanded(event) { toggleChildrenExpanded(event) {
event?.preventDefault(); event?.preventDefault();
this.toggleProperty("childrenExpanded"); this.toggleProperty("childrenExpanded");
}, }
}); }

View File

@ -1,25 +1,30 @@
import { COMPONENTS, THEMES } from "admin/models/theme"; import { classNames } from "@ember-decorators/component";
import { inject as service } from "@ember/service";
import { equal, gt, gte } from "@ember/object/computed"; import { equal, gt, gte } from "@ember/object/computed";
import { COMPONENTS, THEMES } from "admin/models/theme";
import Component from "@ember/component"; import Component from "@ember/component";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { inject as service } from "@ember/service";
import { action } from "@ember/object"; import { action } from "@ember/object";
export default Component.extend({ @classNames("themes-list")
router: service(), export default class ThemesList extends Component {
THEMES, @service router;
COMPONENTS,
classNames: ["themes-list"], THEMES = THEMES;
filterTerm: null, COMPONENTS = COMPONENTS;
filterTerm = null;
hasThemes: gt("themesList.length", 0), @gt("themesList.length", 0) hasThemes;
hasActiveThemes: gt("activeThemes.length", 0),
hasInactiveThemes: gt("inactiveThemes.length", 0),
showFilter: gte("themesList.length", 10),
themesTabActive: equal("currentTab", THEMES), @gt("activeThemes.length", 0) hasActiveThemes;
componentsTabActive: equal("currentTab", COMPONENTS),
@gt("inactiveThemes.length", 0) hasInactiveThemes;
@gte("themesList.length", 10) showFilter;
@equal("currentTab", THEMES) themesTabActive;
@equal("currentTab", COMPONENTS) componentsTabActive;
@discourseComputed("themes", "components", "currentTab") @discourseComputed("themes", "components", "currentTab")
themesList(themes, components) { themesList(themes, components) {
@ -28,7 +33,7 @@ export default Component.extend({
} else { } else {
return components; return components;
} }
}, }
@discourseComputed( @discourseComputed(
"themesList", "themesList",
@ -49,7 +54,7 @@ export default Component.extend({
); );
} }
return this._filterThemes(results, this.filterTerm); return this._filterThemes(results, this.filterTerm);
}, }
@discourseComputed( @discourseComputed(
"themesList", "themesList",
@ -78,7 +83,7 @@ export default Component.extend({
}); });
} }
return this._filterThemes(results, this.filterTerm); return this._filterThemes(results, this.filterTerm);
}, }
_filterThemes(themes, term) { _filterThemes(themes, term) {
term = term?.trim()?.toLowerCase(); term = term?.trim()?.toLowerCase();
@ -86,7 +91,7 @@ export default Component.extend({
return themes; return themes;
} }
return themes.filter(({ name }) => name.toLowerCase().includes(term)); return themes.filter(({ name }) => name.toLowerCase().includes(term));
}, }
@action @action
changeView(newTab) { changeView(newTab) {
@ -96,10 +101,10 @@ export default Component.extend({
this.set("filterTerm", null); this.set("filterTerm", null);
} }
} }
}, }
@action @action
navigateToTheme(theme) { navigateToTheme(theme) {
this.router.transitionTo("adminCustomizeThemes.show", theme); this.router.transitionTo("adminCustomizeThemes.show", theme);
}, }
}); }

View File

@ -1,17 +1,21 @@
import discourseComputed, { on } from "discourse-common/utils/decorators"; import { action } from "@ember/object";
import { classNames } from "@ember-decorators/component";
import { empty, reads } from "@ember/object/computed"; import { empty, reads } from "@ember/object/computed";
import discourseComputed, { on } from "discourse-common/utils/decorators";
import Component from "@ember/component"; import Component from "@ember/component";
import { makeArray } from "discourse-common/lib/helpers"; import { makeArray } from "discourse-common/lib/helpers";
export default Component.extend({ @classNames("value-list")
classNameBindings: [":value-list"], export default class ValueList extends Component {
inputInvalid: empty("newValue"), @empty("newValue") inputInvalid;
inputDelimiter: null,
inputType: null, inputDelimiter = null;
newValue: "", inputType = null;
collection: null, newValue = "";
values: null, collection = null;
noneKey: reads("addKey"), values = null;
@reads("addKey") noneKey;
@on("didReceiveAttrs") @on("didReceiveAttrs")
_setupCollection() { _setupCollection() {
@ -25,24 +29,25 @@ export default Component.extend({
"collection", "collection",
this._splitValues(values, this.inputDelimiter || "\n") this._splitValues(values, this.inputDelimiter || "\n")
); );
}, }
@discourseComputed("choices.[]", "collection.[]") @discourseComputed("choices.[]", "collection.[]")
filteredChoices(choices, collection) { filteredChoices(choices, collection) {
return makeArray(choices).filter((i) => !collection.includes(i)); return makeArray(choices).filter((i) => !collection.includes(i));
}, }
keyDown(event) { keyDown(event) {
if (event.key === "Enter") { if (event.key === "Enter") {
this.send("addValue", this.newValue); this.send("addValue", this.newValue);
} }
}, }
actions: { @action
changeValue(index, event) { changeValue(index, event) {
this._replaceValue(index, event.target.value); this._replaceValue(index, event.target.value);
}, }
@action
addValue(newValue) { addValue(newValue) {
if (this.inputInvalid) { if (this.inputInvalid) {
return; return;
@ -50,16 +55,19 @@ export default Component.extend({
this.set("newValue", null); this.set("newValue", null);
this._addValue(newValue); this._addValue(newValue);
}, }
@action
removeValue(value) { removeValue(value) {
this._removeValue(value); this._removeValue(value);
}, }
@action
selectChoice(choice) { selectChoice(choice) {
this._addValue(choice); this._addValue(choice);
}, }
@action
shift(operation, index) { shift(operation, index) {
let futureIndex = index + operation; let futureIndex = index + operation;
@ -74,8 +82,7 @@ export default Component.extend({
this.collection.insertAt(futureIndex, shiftedValue); this.collection.insertAt(futureIndex, shiftedValue);
this._saveValues(); this._saveValues();
}, }
},
_addValue(value) { _addValue(value) {
this.collection.addObject(value); this.collection.addObject(value);
@ -87,7 +94,7 @@ export default Component.extend({
} }
this._saveValues(); this._saveValues();
}, }
_removeValue(value) { _removeValue(value) {
this.collection.removeObject(value); this.collection.removeObject(value);
@ -99,12 +106,12 @@ export default Component.extend({
} }
this._saveValues(); this._saveValues();
}, }
_replaceValue(index, newValue) { _replaceValue(index, newValue) {
this.collection.replace(index, 1, [newValue]); this.collection.replace(index, 1, [newValue]);
this._saveValues(); this._saveValues();
}, }
_saveValues() { _saveValues() {
if (this.inputType === "array") { if (this.inputType === "array") {
@ -113,12 +120,12 @@ export default Component.extend({
} }
this.set("values", this.collection.join(this.inputDelimiter || "\n")); this.set("values", this.collection.join(this.inputDelimiter || "\n"));
}, }
@discourseComputed("collection") @discourseComputed("collection")
showUpDownButtons(collection) { showUpDownButtons(collection) {
return collection.length - 1 ? true : false; return collection.length - 1 ? true : false;
}, }
_splitValues(values, delimiter) { _splitValues(values, delimiter) {
if (values && values.length) { if (values && values.length) {
@ -126,5 +133,5 @@ export default Component.extend({
} else { } else {
return []; return [];
} }
}, }
}); }

View File

@ -1,3 +1,3 @@
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({}); export default class VersionChecks extends Component {}

View File

@ -79,7 +79,7 @@
<DButton <DButton
@type="submit" @type="submit"
@class="btn btn-primary" @class="btn btn-primary"
@action={{action "submit"}} @action={{action "submitForm"}}
@disabled={{this.submitDisabled}} @disabled={{this.submitDisabled}}
@label="admin.watched_words.form.add" @label="admin.watched_words.form.add"
/> />

View File

@ -1,30 +1,37 @@
import { action } from "@ember/object";
import { classNames, tagName } from "@ember-decorators/component";
import { inject as service } from "@ember/service";
import { equal, not } from "@ember/object/computed";
import discourseComputed, { observes } from "discourse-common/utils/decorators"; import discourseComputed, { observes } from "discourse-common/utils/decorators";
import Component from "@ember/component"; import Component from "@ember/component";
import I18n from "I18n"; import I18n from "I18n";
import WatchedWord from "admin/models/watched-word"; import WatchedWord from "admin/models/watched-word";
import { equal, not } from "@ember/object/computed";
import { isEmpty } from "@ember/utils"; import { isEmpty } from "@ember/utils";
import { schedule } from "@ember/runloop"; import { schedule } from "@ember/runloop";
import { inject as service } from "@ember/service";
export default Component.extend({ @tagName("form")
tagName: "form", @classNames("watched-word-form")
dialog: service(), export default class WatchedWordForm extends Component {
classNames: ["watched-word-form"], @service dialog;
formSubmitted: false,
actionKey: null, formSubmitted = false;
showMessage: false, actionKey = null;
selectedTags: null, showMessage = false;
isCaseSensitive: false, selectedTags = null;
submitDisabled: not("word"), isCaseSensitive = false;
canReplace: equal("actionKey", "replace"),
canTag: equal("actionKey", "tag"), @not("word") submitDisabled;
canLink: equal("actionKey", "link"),
@equal("actionKey", "replace") canReplace;
@equal("actionKey", "tag") canTag;
@equal("actionKey", "link") canLink;
didInsertElement() { didInsertElement() {
this._super(...arguments); super.didInsertElement(...arguments);
this.set("selectedTags", []); this.set("selectedTags", []);
}, }
@discourseComputed("siteSettings.watched_words_regular_expressions") @discourseComputed("siteSettings.watched_words_regular_expressions")
placeholderKey(watchedWordsRegularExpressions) { placeholderKey(watchedWordsRegularExpressions) {
@ -33,14 +40,14 @@ export default Component.extend({
} else { } else {
return "admin.watched_words.form.placeholder"; return "admin.watched_words.form.placeholder";
} }
}, }
@observes("word") @observes("word")
removeMessage() { removeMessage() {
if (this.showMessage && !isEmpty(this.word)) { if (this.showMessage && !isEmpty(this.word)) {
this.set("showMessage", false); this.set("showMessage", false);
} }
}, }
@discourseComputed("word") @discourseComputed("word")
isUniqueWord(word) { isUniqueWord(word) {
@ -54,21 +61,22 @@ export default Component.extend({
} }
return content.word.toLowerCase() !== word.toLowerCase(); return content.word.toLowerCase() !== word.toLowerCase();
}); });
}, }
focusInput() { focusInput() {
schedule("afterRender", () => this.element.querySelector("input").focus()); schedule("afterRender", () => this.element.querySelector("input").focus());
}, }
actions: { @action
changeSelectedTags(tags) { changeSelectedTags(tags) {
this.setProperties({ this.setProperties({
selectedTags: tags, selectedTags: tags,
replacement: tags.join(","), replacement: tags.join(","),
}); });
}, }
submit() { @action
submitForm() {
if (!this.isUniqueWord) { if (!this.isUniqueWord) {
this.setProperties({ this.setProperties({
showMessage: true, showMessage: true,
@ -119,6 +127,5 @@ export default Component.extend({
}); });
}); });
} }
}, }
}, }
});

View File

@ -1,28 +1,33 @@
import { classNames } from "@ember-decorators/component";
import { alias } from "@ember/object/computed";
import Component from "@ember/component"; import Component from "@ember/component";
import I18n from "I18n"; import I18n from "I18n";
import UppyUploadMixin from "discourse/mixins/uppy-upload"; import UppyUploadMixin from "discourse/mixins/uppy-upload";
import { alias } from "@ember/object/computed";
import { dialog } from "discourse/lib/uploads"; import { dialog } from "discourse/lib/uploads";
export default Component.extend(UppyUploadMixin, { @classNames("watched-words-uploader")
type: "txt", export default class WatchedWordUploader extends Component.extend(
classNames: "watched-words-uploader", UppyUploadMixin
uploadUrl: "/admin/customize/watched_words/upload", ) {
addDisabled: alias("uploading"), type = "txt";
preventDirectS3Uploads: true, uploadUrl = "/admin/customize/watched_words/upload";
@alias("uploading") addDisabled;
preventDirectS3Uploads = true;
validateUploadedFilesOptions() { validateUploadedFilesOptions() {
return { skipValidation: true }; return { skipValidation: true };
}, }
_perFileData() { _perFileData() {
return { action_key: this.actionKey }; return { action_key: this.actionKey };
}, }
uploadDone() { uploadDone() {
if (this) { if (this) {
dialog.alert(I18n.t("admin.watched_words.form.upload_successful")); dialog.alert(I18n.t("admin.watched_words.form.upload_successful"));
this.done(); this.done();
} }
}, }
}); }