diff --git a/app/assets/javascripts/admin/addon/components/ace-editor.js b/app/assets/javascripts/admin/addon/components/ace-editor.js
index 06ed376303..bc32497833 100644
--- a/app/assets/javascripts/admin/addon/components/ace-editor.js
+++ b/app/assets/javascripts/admin/addon/components/ace-editor.js
@@ -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 getURL from "discourse-common/lib/get-url";
import loadScript from "discourse/lib/load-script";
import I18n from "I18n";
import { bind, observes } from "discourse-common/utils/decorators";
-import { on } from "@ember/object/evented";
const COLOR_VARS_REGEX =
/\$(primary|secondary|tertiary|quaternary|header_background|header_primary|highlight|danger|success|love)(\s|;|-(low|medium|high))/g;
-export default Component.extend({
- mode: "css",
- classNames: ["ace-wrapper"],
- _editor: null,
- _skipContentChangeEvent: null,
- disabled: false,
- htmlPlaceholder: false,
+@classNames("ace-wrapper")
+export default class AceEditor extends Component {
+ mode = "css";
+ disabled = false;
+ htmlPlaceholder = false;
+ _editor = null;
+ _skipContentChangeEvent = null;
@observes("editorId")
editorIdChanged() {
if (this.autofocus) {
this.send("focus");
}
- },
+ }
didRender() {
this._skipContentChangeEvent = false;
- },
+ }
@observes("content")
contentChanged() {
@@ -33,14 +35,14 @@ export default Component.extend({
if (this._editor && !this._skipContentChangeEvent) {
this._editor.getSession().setValue(content);
}
- },
+ }
@observes("mode")
modeChanged() {
if (this._editor && !this._skipContentChangeEvent) {
this._editor.getSession().setMode("ace/mode/" + this.mode);
}
- },
+ }
@observes("placeholder")
placeholderChanged() {
@@ -49,12 +51,12 @@ export default Component.extend({
placeholder: this.placeholder,
});
}
- },
+ }
@observes("disabled")
disabledStateChanged() {
this.changeDisabledState();
- },
+ }
changeDisabledState() {
const editor = this._editor;
@@ -67,9 +69,10 @@ export default Component.extend({
});
editor.container.parentNode.setAttribute("data-disabled", disabled);
}
- },
+ }
- _destroyEditor: on("willDestroyElement", function () {
+ @on("willDestroyElement")
+ _destroyEditor() {
if (this._editor) {
this._editor.destroy();
this._editor = null;
@@ -80,16 +83,16 @@ export default Component.extend({
}
$(window).off("ace:resize");
- }),
+ }
resize() {
if (this._editor) {
this._editor.resize();
}
- },
+ }
didInsertElement() {
- this._super(...arguments);
+ super.didInsertElement(...arguments);
loadScript("/javascripts/ace/ace.js").then(() => {
window.ace.require(["ace/ace"], (loadedAce) => {
loadedAce.config.set("loadWorkerFromBlob", false);
@@ -153,13 +156,13 @@ export default Component.extend({
this._darkModeListener.addListener(this.setAceTheme);
});
});
- },
+ }
willDestroyElement() {
if (this._darkModeListener) {
this._darkModeListener.removeListener(this.setAceTheme);
}
- },
+ }
@bind
setAceTheme() {
@@ -170,7 +173,7 @@ export default Component.extend({
this._editor.setTheme(
`ace/theme/${schemeType === "dark" ? "chaos" : "chrome"}`
);
- },
+ }
warnSCSSDeprecations() {
if (
@@ -202,16 +205,15 @@ export default Component.extend({
? I18n.t("admin.customize.theme.scss_color_variables_warning")
: false
);
- },
+ }
- actions: {
- focus() {
- if (this._editor) {
- this._editor.focus();
- this._editor.navigateFileEnd();
- }
- },
- },
+ @action
+ focus() {
+ if (this._editor) {
+ this._editor.focus();
+ this._editor.navigateFileEnd();
+ }
+ }
_overridePlaceholder(loadedAce) {
const originalPlaceholderSetter =
@@ -239,5 +241,5 @@ export default Component.extend({
this.$updatePlaceholder();
};
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/admin-backups-logs.js b/app/assets/javascripts/admin/addon/components/admin-backups-logs.js
index c707c99b70..436702f96e 100644
--- a/app/assets/javascripts/admin/addon/components/admin-backups-logs.js
+++ b/app/assets/javascripts/admin/addon/components/admin-backups-logs.js
@@ -1,28 +1,29 @@
+import { classNames } from "@ember-decorators/component";
import { observes, on } from "discourse-common/utils/decorators";
import Component from "@ember/component";
import I18n from "I18n";
import discourseDebounce from "discourse-common/lib/debounce";
import { scheduleOnce } from "@ember/runloop";
-export default Component.extend({
- classNames: ["admin-backups-logs"],
- showLoadingSpinner: false,
- hasFormattedLogs: false,
- noLogsMessage: I18n.t("admin.backups.logs.none"),
+@classNames("admin-backups-logs")
+export default class AdminBackupsLogs extends Component {
+ showLoadingSpinner = false;
+ hasFormattedLogs = false;
+ noLogsMessage = I18n.t("admin.backups.logs.none");
init() {
- this._super(...arguments);
+ super.init(...arguments);
this._reset();
- },
+ }
_reset() {
this.setProperties({ formattedLogs: "", index: 0 });
- },
+ }
_scrollDown() {
const div = this.element;
div.scrollTop = div.scrollHeight;
- },
+ }
@on("init")
@observes("logs.[]")
@@ -31,7 +32,7 @@ export default Component.extend({
this._reset(); // reset the cached logs whenever the model is reset
this.renderLogs();
}
- },
+ }
_updateFormattedLogsFunc() {
const logs = this.logs;
@@ -55,13 +56,13 @@ export default Component.extend({
this.renderLogs();
scheduleOnce("afterRender", this, this._scrollDown);
- },
+ }
@on("init")
@observes("logs.[]")
_updateFormattedLogs() {
discourseDebounce(this, this._updateFormattedLogsFunc, 150);
- },
+ }
renderLogs() {
const formattedLogs = this.formattedLogs;
@@ -76,5 +77,5 @@ export default Component.extend({
} else {
this.set("showLoadingSpinner", false);
}
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/admin-editable-field.js b/app/assets/javascripts/admin/addon/components/admin-editable-field.js
index 892a3208e8..2e1f80b305 100644
--- a/app/assets/javascripts/admin/addon/components/admin-editable-field.js
+++ b/app/assets/javascripts/admin/addon/components/admin-editable-field.js
@@ -1,28 +1,27 @@
+import { tagName } from "@ember-decorators/component";
import Component from "@ember/component";
import { action } from "@ember/object";
-export default Component.extend({
- tagName: "",
-
- buffer: "",
- editing: false,
+@tagName("")
+export default class AdminEditableField extends Component {
+ buffer = "";
+ editing = false;
init() {
- this._super(...arguments);
+ super.init(...arguments);
this.set("editing", false);
- },
+ }
@action
edit(event) {
event?.preventDefault();
this.set("buffer", this.value);
this.toggleProperty("editing");
- },
+ }
- actions: {
- save() {
- // Action has to toggle 'editing' property.
- this.action(this.buffer);
- },
- },
-});
+ @action
+ save() {
+ // Action has to toggle 'editing' property.
+ this.action(this.buffer);
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/admin-form-row.js b/app/assets/javascripts/admin/addon/components/admin-form-row.js
index 6217c6b913..9745818920 100644
--- a/app/assets/javascripts/admin/addon/components/admin-form-row.js
+++ b/app/assets/javascripts/admin/addon/components/admin-form-row.js
@@ -1,4 +1,4 @@
+import { classNames } from "@ember-decorators/component";
import Component from "@ember/component";
-export default Component.extend({
- classNames: ["row"],
-});
+@classNames("row")
+export default class AdminFormRow extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/admin-graph.js b/app/assets/javascripts/admin/addon/components/admin-graph.js
index 1107abeb2c..4ef05fca32 100644
--- a/app/assets/javascripts/admin/addon/components/admin-graph.js
+++ b/app/assets/javascripts/admin/addon/components/admin-graph.js
@@ -1,9 +1,10 @@
+import { tagName } from "@ember-decorators/component";
import Component from "@ember/component";
import loadScript from "discourse/lib/load-script";
-export default Component.extend({
- tagName: "canvas",
- type: "line",
+@tagName("canvas")
+export default class AdminGraph extends Component {
+ type = "line";
refreshChart() {
const ctx = this.element.getContext("2d");
@@ -49,11 +50,11 @@ export default Component.extend({
};
this._chart = new window.Chart(ctx, config);
- },
+ }
didInsertElement() {
loadScript("/javascripts/Chart.min.js").then(() =>
this.refreshChart.apply(this)
);
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/admin-nav.js b/app/assets/javascripts/admin/addon/components/admin-nav.js
index 0e6d50b17d..97dfb56e8b 100644
--- a/app/assets/javascripts/admin/addon/components/admin-nav.js
+++ b/app/assets/javascripts/admin/addon/components/admin-nav.js
@@ -1,4 +1,4 @@
+import { tagName } from "@ember-decorators/component";
import Component from "@ember/component";
-export default Component.extend({
- tagName: "",
-});
+@tagName("")
+export default class AdminNav extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/admin-penalty-history.js b/app/assets/javascripts/admin/addon/components/admin-penalty-history.js
index 32c288b248..0931ac8e4a 100644
--- a/app/assets/javascripts/admin/addon/components/admin-penalty-history.js
+++ b/app/assets/javascripts/admin/addon/components/admin-penalty-history.js
@@ -1,16 +1,16 @@
+import { classNames } from "@ember-decorators/component";
import Component from "@ember/component";
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")
suspendedCountClass(count) {
if (count > 0) {
return "danger";
}
return "";
- },
+ }
@discourseComputed("user.penalty_counts.silenced")
silencedCountClass(count) {
@@ -18,5 +18,5 @@ export default Component.extend({
return "danger";
}
return "";
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/admin-penalty-post-action.js b/app/assets/javascripts/admin/addon/components/admin-penalty-post-action.js
index eb201ae089..0831492546 100644
--- a/app/assets/javascripts/admin/addon/components/admin-penalty-post-action.js
+++ b/app/assets/javascripts/admin/addon/components/admin-penalty-post-action.js
@@ -1,5 +1,6 @@
-import Component from "@ember/component";
+import { action } from "@ember/object";
import { equal } from "@ember/object/computed";
+import Component from "@ember/component";
import discourseComputed, {
afterRender,
} from "discourse-common/utils/decorators";
@@ -7,30 +8,28 @@ import I18n from "I18n";
const ACTIONS = ["delete", "delete_replies", "edit", "none"];
-export default Component.extend({
- postId: null,
- postAction: null,
- postEdit: null,
+export default class AdminPenaltyPostAction extends Component {
+ postId = null;
+ postAction = null;
+ postEdit = null;
+ @equal("postAction", "edit") editing;
@discourseComputed
penaltyActions() {
return ACTIONS.map((id) => {
return { id, name: I18n.t(`admin.user.penalty_post_${id}`) };
});
- },
+ }
- editing: equal("postAction", "edit"),
+ @action
+ penaltyChanged(postAction) {
+ this.set("postAction", postAction);
- actions: {
- penaltyChanged(postAction) {
- this.set("postAction", postAction);
-
- // If we switch to edit mode, jump to the edit textarea
- if (postAction === "edit") {
- this._focusEditTextarea();
- }
- },
- },
+ // If we switch to edit mode, jump to the edit textarea
+ if (postAction === "edit") {
+ this._focusEditTextarea();
+ }
+ }
@afterRender
_focusEditTextarea() {
@@ -38,5 +37,5 @@ export default Component.extend({
const body = elem.closest(".modal-body");
body.scrollTo(0, body.clientHeight);
elem.querySelector(".post-editor").focus();
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/admin-penalty-similar-users.js b/app/assets/javascripts/admin/addon/components/admin-penalty-similar-users.js
index 241927a7b7..52996d458f 100644
--- a/app/assets/javascripts/admin/addon/components/admin-penalty-similar-users.js
+++ b/app/assets/javascripts/admin/addon/components/admin-penalty-similar-users.js
@@ -1,10 +1,10 @@
+import { tagName } from "@ember-decorators/component";
import Component from "@ember/component";
import { action } from "@ember/object";
import discourseComputed from "discourse-common/utils/decorators";
-export default Component.extend({
- tagName: "",
-
+@tagName("")
+export default class AdminPenaltySimilarUsers extends Component {
@discourseComputed("penaltyType")
penaltyField(penaltyType) {
if (penaltyType === "suspend") {
@@ -12,7 +12,7 @@ export default Component.extend({
} else if (penaltyType === "silence") {
return "can_be_silenced";
}
- },
+ }
@action
selectUserId(userId, event) {
@@ -25,5 +25,5 @@ export default Component.extend({
} else {
this.selectedUserIds.removeObject(userId);
}
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/admin-report-chart.js b/app/assets/javascripts/admin/addon/components/admin-report-chart.js
index 1c4ad1caa3..64f09aa0d7 100644
--- a/app/assets/javascripts/admin/addon/components/admin-report-chart.js
+++ b/app/assets/javascripts/admin/addon/components/admin-report-chart.js
@@ -1,3 +1,4 @@
+import { classNames } from "@ember-decorators/component";
import Report from "admin/models/report";
import Component from "@ember/component";
import discourseDebounce from "discourse-common/lib/debounce";
@@ -7,31 +8,31 @@ import { number } from "discourse/lib/formatter";
import { schedule } from "@ember/runloop";
import { bind } from "discourse-common/utils/decorators";
-export default Component.extend({
- classNames: ["admin-report-chart"],
- limit: 8,
- total: 0,
- options: null,
+@classNames("admin-report-chart")
+export default class AdminReportChart extends Component {
+ limit = 8;
+ total = 0;
+ options = null;
didInsertElement() {
- this._super(...arguments);
+ super.didInsertElement(...arguments);
window.addEventListener("resize", this._resizeHandler);
- },
+ }
willDestroyElement() {
- this._super(...arguments);
+ super.willDestroyElement(...arguments);
window.removeEventListener("resize", this._resizeHandler);
this._resetChart();
- },
+ }
didReceiveAttrs() {
- this._super(...arguments);
+ super.didReceiveAttrs(...arguments);
discourseDebounce(this, this._scheduleChartRendering, 100);
- },
+ }
_scheduleChartRendering() {
schedule("afterRender", () => {
@@ -40,7 +41,7 @@ export default Component.extend({
this.element && this.element.querySelector(".chart-canvas")
);
});
- },
+ }
_renderChart(model, chartCanvas) {
if (!chartCanvas) {
@@ -99,7 +100,7 @@ export default Component.extend({
this._buildChartConfig(data, this.options)
);
});
- },
+ }
_buildChartConfig(data, options) {
return {
@@ -161,21 +162,21 @@ export default Component.extend({
},
},
};
- },
+ }
_resetChart() {
if (this._chart) {
this._chart.destroy();
this._chart = null;
}
- },
+ }
_applyChartGrouping(model, data, options) {
return Report.collapse(model, data, options.chartGrouping);
- },
+ }
@bind
_resizeHandler() {
discourseDebounce(this, this._scheduleChartRendering, 500);
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/admin-report-counters.js b/app/assets/javascripts/admin/addon/components/admin-report-counters.js
index c956b93e35..f299190c9e 100644
--- a/app/assets/javascripts/admin/addon/components/admin-report-counters.js
+++ b/app/assets/javascripts/admin/addon/components/admin-report-counters.js
@@ -1,6 +1,5 @@
+import { attributeBindings, classNames } from "@ember-decorators/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 {}
diff --git a/app/assets/javascripts/admin/addon/components/admin-report-counts.js b/app/assets/javascripts/admin/addon/components/admin-report-counts.js
index 03c690dbbd..a6f8bac86a 100644
--- a/app/assets/javascripts/admin/addon/components/admin-report-counts.js
+++ b/app/assets/javascripts/admin/addon/components/admin-report-counts.js
@@ -1,11 +1,11 @@
-import Component from "@ember/component";
+import { classNameBindings, tagName } from "@ember-decorators/component";
import { match } from "@ember/object/computed";
-export default Component.extend({
- allTime: true,
- tagName: "tr",
- reverseColors: match(
- "report.type",
- /^(time_to_first_response|topics_with_no_response)$/
- ),
- classNameBindings: ["reverseColors"],
-});
+import Component from "@ember/component";
+@tagName("tr")
+@classNameBindings("reverseColors")
+export default class AdminReportCounts extends Component {
+ allTime = true;
+
+ @match("report.type", /^(time_to_first_response|topics_with_no_response)$/)
+ reverseColors;
+}
diff --git a/app/assets/javascripts/admin/addon/components/admin-report-inline-table.js b/app/assets/javascripts/admin/addon/components/admin-report-inline-table.js
index 753320cc31..8b21d22f5e 100644
--- a/app/assets/javascripts/admin/addon/components/admin-report-inline-table.js
+++ b/app/assets/javascripts/admin/addon/components/admin-report-inline-table.js
@@ -1,4 +1,4 @@
+import { classNames } from "@ember-decorators/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 {}
diff --git a/app/assets/javascripts/admin/addon/components/admin-report-per-day-counts.js b/app/assets/javascripts/admin/addon/components/admin-report-per-day-counts.js
index 7f039c061e..4b4b82f998 100644
--- a/app/assets/javascripts/admin/addon/components/admin-report-per-day-counts.js
+++ b/app/assets/javascripts/admin/addon/components/admin-report-per-day-counts.js
@@ -1,4 +1,4 @@
+import { tagName } from "@ember-decorators/component";
import Component from "@ember/component";
-export default Component.extend({
- tagName: "tr",
-});
+@tagName("tr")
+export default class AdminReportPerDayCounts extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/admin-report-stacked-chart.js b/app/assets/javascripts/admin/addon/components/admin-report-stacked-chart.js
index 6b773957f6..b69e75141e 100644
--- a/app/assets/javascripts/admin/addon/components/admin-report-stacked-chart.js
+++ b/app/assets/javascripts/admin/addon/components/admin-report-stacked-chart.js
@@ -1,3 +1,4 @@
+import { classNames } from "@ember-decorators/component";
import Report from "admin/models/report";
import Component from "@ember/component";
import discourseDebounce from "discourse-common/lib/debounce";
@@ -7,32 +8,31 @@ import { number } from "discourse/lib/formatter";
import { schedule } from "@ember/runloop";
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() {
- this._super(...arguments);
+ super.didInsertElement(...arguments);
window.addEventListener("resize", this._resizeHandler);
- },
+ }
willDestroyElement() {
- this._super(...arguments);
+ super.willDestroyElement(...arguments);
window.removeEventListener("resize", this._resizeHandler);
this._resetChart();
- },
+ }
didReceiveAttrs() {
- this._super(...arguments);
+ super.didReceiveAttrs(...arguments);
discourseDebounce(this, this._scheduleChartRendering, 100);
- },
+ }
@bind
_resizeHandler() {
discourseDebounce(this, this._scheduleChartRendering, 500);
- },
+ }
_scheduleChartRendering() {
schedule("afterRender", () => {
@@ -45,7 +45,7 @@ export default Component.extend({
this.element.querySelector(".chart-canvas")
);
});
- },
+ }
_renderChart(model, chartCanvas) {
if (!chartCanvas) {
@@ -79,7 +79,7 @@ export default Component.extend({
this._chart = new window.Chart(context, this._buildChartConfig(data));
});
- },
+ }
_buildChartConfig(data) {
return {
@@ -150,10 +150,10 @@ export default Component.extend({
},
},
};
- },
+ }
_resetChart() {
this._chart?.destroy();
this._chart = null;
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/admin-report-storage-stats.js b/app/assets/javascripts/admin/addon/components/admin-report-storage-stats.js
index e12bc6432f..ee0d7d2476 100644
--- a/app/assets/javascripts/admin/addon/components/admin-report-storage-stats.js
+++ b/app/assets/javascripts/admin/addon/components/admin-report-storage-stats.js
@@ -1,43 +1,45 @@
+import { classNames } from "@ember-decorators/component";
+import { alias } from "@ember/object/computed";
import Component from "@ember/component";
import I18n from "I18n";
-import { alias } from "@ember/object/computed";
import discourseComputed from "discourse-common/utils/decorators";
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"),
- backupStats: alias("model.data.backups"),
- uploadStats: alias("model.data.uploads"),
+ @alias("model.data.backups") backupStats;
+
+ @alias("model.data.uploads") uploadStats;
@discourseComputed("backupStats")
showBackupStats(stats) {
return stats && this.currentUser.admin;
- },
+ }
@discourseComputed("backupLocation")
backupLocationName(backupLocation) {
return I18n.t(`admin.backups.location.${backupLocation}`);
- },
+ }
@discourseComputed("backupStats.used_bytes")
usedBackupSpace(bytes) {
return I18n.toHumanSize(bytes);
- },
+ }
@discourseComputed("backupStats.free_bytes")
freeBackupSpace(bytes) {
return I18n.toHumanSize(bytes);
- },
+ }
@discourseComputed("uploadStats.used_bytes")
usedUploadSpace(bytes) {
return I18n.toHumanSize(bytes);
- },
+ }
@discourseComputed("uploadStats.free_bytes")
freeUploadSpace(bytes) {
return I18n.toHumanSize(bytes);
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/admin-report-table-cell.js b/app/assets/javascripts/admin/addon/components/admin-report-table-cell.js
index 838d8dbe1d..bf8417d3f8 100644
--- a/app/assets/javascripts/admin/addon/components/admin-report-table-cell.js
+++ b/app/assets/javascripts/admin/addon/components/admin-report-table-cell.js
@@ -1,21 +1,26 @@
-import Component from "@ember/component";
+import {
+ attributeBindings,
+ classNameBindings,
+ classNames,
+ tagName,
+} from "@ember-decorators/component";
import { alias } from "@ember/object/computed";
+import Component from "@ember/component";
import discourseComputed from "discourse-common/utils/decorators";
-export default Component.extend({
- tagName: "td",
- classNames: ["admin-report-table-cell"],
- classNameBindings: ["type", "property"],
- attributeBindings: ["value:title"],
- options: null,
+@tagName("td")
+@classNames("admin-report-table-cell")
+@classNameBindings("type", "property")
+@attributeBindings("value:title")
+export default class AdminReportTableCell extends Component {
+ options = null;
+ @alias("label.type") type;
+ @alias("label.mainProperty") property;
+ @alias("computedLabel.formattedValue") formattedValue;
+ @alias("computedLabel.value") value;
@discourseComputed("label", "data", "options")
computedLabel(label, data, options) {
return label.compute(data, options || {});
- },
-
- type: alias("label.type"),
- property: alias("label.mainProperty"),
- formattedValue: alias("computedLabel.formattedValue"),
- value: alias("computedLabel.value"),
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/admin-report-table-header.js b/app/assets/javascripts/admin/addon/components/admin-report-table-header.js
index 5c7cdf1e4c..7de3ac9708 100644
--- a/app/assets/javascripts/admin/addon/components/admin-report-table-header.js
+++ b/app/assets/javascripts/admin/addon/components/admin-report-table-header.js
@@ -1,19 +1,24 @@
+import {
+ attributeBindings,
+ classNameBindings,
+ classNames,
+ tagName,
+} from "@ember-decorators/component";
import Component from "@ember/component";
import discourseComputed from "discourse-common/utils/decorators";
-export default Component.extend({
- tagName: "th",
- classNames: ["admin-report-table-header"],
- classNameBindings: ["label.mainProperty", "label.type", "isCurrentSort"],
- attributeBindings: ["label.title:title"],
-
+@tagName("th")
+@classNames("admin-report-table-header")
+@classNameBindings("label.mainProperty", "label.type", "isCurrentSort")
+@attributeBindings("label.title:title")
+export default class AdminReportTableHeader extends Component {
@discourseComputed("currentSortLabel.sortProperty", "label.sortProperty")
isCurrentSort(currentSortField, labelSortField) {
return currentSortField === labelSortField;
- },
+ }
@discourseComputed("currentSortDirection")
sortIcon(currentSortDirection) {
return currentSortDirection === 1 ? "caret-up" : "caret-down";
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/admin-report-table-row.js b/app/assets/javascripts/admin/addon/components/admin-report-table-row.js
index ff34cb94e8..e8de9a822c 100644
--- a/app/assets/javascripts/admin/addon/components/admin-report-table-row.js
+++ b/app/assets/javascripts/admin/addon/components/admin-report-table-row.js
@@ -1,6 +1,7 @@
+import { classNames, tagName } from "@ember-decorators/component";
import Component from "@ember/component";
-export default Component.extend({
- tagName: "tr",
- classNames: ["admin-report-table-row"],
- options: null,
-});
+@tagName("tr")
+@classNames("admin-report-table-row")
+export default class AdminReportTableRow extends Component {
+ options = null;
+}
diff --git a/app/assets/javascripts/admin/addon/components/admin-report-table.js b/app/assets/javascripts/admin/addon/components/admin-report-table.js
index a237e93ee4..3638625f87 100644
--- a/app/assets/javascripts/admin/addon/components/admin-report-table.js
+++ b/app/assets/javascripts/admin/addon/components/admin-report-table.js
@@ -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 Component from "@ember/component";
import discourseComputed from "discourse-common/utils/decorators";
import { makeArray } from "discourse-common/lib/helpers";
const PAGES_LIMIT = 8;
-export default Component.extend({
- classNameBindings: ["sortable", "twoColumns"],
- classNames: ["admin-report-table"],
- sortable: false,
- sortDirection: 1,
- perPage: alias("options.perPage"),
- page: 0,
+@classNameBindings("sortable", "twoColumns")
+@classNames("admin-report-table")
+export default class AdminReportTable extends Component {
+ sortable = false;
+ sortDirection = 1;
+
+ @alias("options.perPage") perPage;
+
+ page = 0;
@discourseComputed("model.computedLabels.length")
twoColumns(labelsLength) {
return labelsLength === 2;
- },
+ }
@discourseComputed(
"totalsForSample",
@@ -31,12 +35,12 @@ export default Component.extend({
.reduce((s, v) => s + v, 0);
return sum >= 1 && total && datesFiltering;
- },
+ }
@discourseComputed("model.total", "options.total", "twoColumns")
showTotal(reportTotal, total, twoColumns) {
return reportTotal && total && twoColumns;
- },
+ }
@discourseComputed(
"model.{average,data}",
@@ -50,17 +54,17 @@ export default Component.extend({
sampleTotalValue &&
hasTwoColumns
);
- },
+ }
@discourseComputed("totalsForSample.1.value", "model.data.length")
averageForSample(totals, count) {
return (totals / count).toFixed(0);
- },
+ }
@discourseComputed("model.data.length")
showSortingUI(dataLength) {
return dataLength >= 5;
- },
+ }
@discourseComputed("totalsForSampleRow", "model.computedLabels")
totalsForSample(row, labels) {
@@ -70,7 +74,7 @@ export default Component.extend({
computedLabel.property = label.mainProperty;
return computedLabel;
});
- },
+ }
@discourseComputed("model.data", "model.computedLabels")
totalsForSampleRow(rows, labels) {
@@ -98,7 +102,7 @@ export default Component.extend({
});
return totalsRow;
- },
+ }
@discourseComputed("sortLabel", "sortDirection", "model.data.[]")
sortedData(sortLabel, sortDirection, data) {
@@ -118,7 +122,7 @@ export default Component.extend({
}
return data;
- },
+ }
@discourseComputed("sortedData.[]", "perPage", "page")
paginatedData(data, perPage, page) {
@@ -128,7 +132,7 @@ export default Component.extend({
}
return data;
- },
+ }
@discourseComputed("model.data", "perPage", "page")
pages(data, perPage, page) {
@@ -156,19 +160,19 @@ export default Component.extend({
}
return pages;
- },
+ }
- actions: {
- changePage(page) {
- this.set("page", page);
- },
+ @action
+ changePage(page) {
+ this.set("page", page);
+ }
- sortByLabel(label) {
- if (this.sortLabel === label) {
- this.set("sortDirection", this.sortDirection === 1 ? -1 : 1);
- } else {
- this.set("sortLabel", label);
- }
- },
- },
-});
+ @action
+ sortByLabel(label) {
+ if (this.sortLabel === label) {
+ this.set("sortDirection", this.sortDirection === 1 ? -1 : 1);
+ } else {
+ this.set("sortLabel", label);
+ }
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/admin-report-trust-level-counts.js b/app/assets/javascripts/admin/addon/components/admin-report-trust-level-counts.js
index 7f039c061e..a68241e445 100644
--- a/app/assets/javascripts/admin/addon/components/admin-report-trust-level-counts.js
+++ b/app/assets/javascripts/admin/addon/components/admin-report-trust-level-counts.js
@@ -1,4 +1,4 @@
+import { tagName } from "@ember-decorators/component";
import Component from "@ember/component";
-export default Component.extend({
- tagName: "tr",
-});
+@tagName("tr")
+export default class AdminReportTrustLevelCounts extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/admin-report.js b/app/assets/javascripts/admin/addon/components/admin-report.js
index 9f60e09a25..8d7f4d4ceb 100644
--- a/app/assets/javascripts/admin/addon/components/admin-report.js
+++ b/app/assets/javascripts/admin/addon/components/admin-report.js
@@ -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 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 I18n from "I18n";
import ReportLoader from "discourse/lib/reports-loader";
@@ -21,51 +22,61 @@ const TABLE_OPTIONS = {
const CHART_OPTIONS = {};
-export default Component.extend({
- classNameBindings: [
- "isHidden:hidden",
- "isHidden::is-visible",
- "isEnabled",
- "isLoading",
- "dasherizedDataSourceName",
- ],
- classNames: ["admin-report"],
- isEnabled: true,
- disabledLabel: I18n.t("admin.dashboard.disabled"),
- isLoading: false,
- rateLimitationString: null,
- dataSourceName: null,
- report: null,
- model: null,
- reportOptions: null,
- forcedModes: null,
- showAllReportsLink: false,
- filters: null,
- showTrend: false,
- showHeader: true,
- showTitle: true,
- showFilteringUI: false,
- showDatesOptions: alias("model.dates_filtering"),
- showRefresh: or("showDatesOptions", "model.available_filters.length"),
- shouldDisplayTrend: and("showTrend", "model.prev_period"),
- endDate: null,
- startDate: null,
+@classNameBindings(
+ "isHidden:hidden",
+ "isHidden::is-visible",
+ "isEnabled",
+ "isLoading",
+ "dasherizedDataSourceName"
+)
+@classNames("admin-report")
+export default class AdminReport extends Component {
+ isEnabled = true;
+ disabledLabel = I18n.t("admin.dashboard.disabled");
+ isLoading = false;
+ rateLimitationString = null;
+ dataSourceName = null;
+ report = null;
+ model = null;
+ reportOptions = null;
+ forcedModes = null;
+ showAllReportsLink = false;
+ filters = null;
+ showTrend = false;
+ showHeader = true;
+ showTitle = true;
+ showFilteringUI = false;
+ @alias("model.dates_filtering") showDatesOptions;
+
+ @or("showDatesOptions", "model.available_filters.length") showRefresh;
+
+ @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;
init() {
- this._super(...arguments);
+ super.init(...arguments);
this._reports = [];
- },
+ }
- isHidden: computed("siteSettings.dashboard_hidden_reports", function () {
+ @computed("siteSettings.dashboard_hidden_reports")
+ get isHidden() {
return (this.siteSettings.dashboard_hidden_reports || "")
.split("|")
.filter(Boolean)
.includes(this.dataSourceName);
- }),
+ }
didReceiveAttrs() {
- this._super(...arguments);
+ super.didReceiveAttrs(...arguments);
let startDate = moment();
if (this.filters && isPresent(this.filters.startDate)) {
@@ -88,42 +99,35 @@ export default Component.extend({
} else if (this.dataSourceName) {
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")
dasherizedDataSourceName(dataSourceName, type) {
return (dataSourceName || type || "undefined").replace(/_/g, "-");
- },
+ }
@discourseComputed("dataSourceName", "model.type")
dataSource(dataSourceName, type) {
dataSourceName = dataSourceName || type;
return `/admin/reports/${dataSourceName}`;
- },
+ }
@discourseComputed("displayedModes.length")
showModes(displayedModesLength) {
return displayedModesLength > 1;
- },
+ }
@discourseComputed("currentMode")
isChartMode(currentMode) {
return currentMode === "chart";
- },
+ }
@action
changeGrouping(grouping) {
this.send("refreshReport", {
chartGrouping: grouping,
});
- },
+ }
@discourseComputed("currentMode", "model.modes", "forcedModes")
displayedModes(currentMode, reportModes, forcedModes) {
@@ -139,12 +143,12 @@ export default Component.extend({
icon: mode === "table" ? "table" : "signal",
};
});
- },
+ }
@discourseComputed("currentMode")
modeComponent(currentMode) {
return `admin-report-${currentMode.replace(/_/g, "-")}`;
- },
+ }
@discourseComputed(
"dataSourceName",
@@ -178,7 +182,7 @@ export default Component.extend({
.join(":");
return reportKey;
- },
+ }
@discourseComputed("options.chartGrouping", "model.chartData.length")
chartGroupings(grouping, count) {
@@ -192,7 +196,7 @@ export default Component.extend({
class: `chart-grouping ${grouping === id ? "active" : "inactive"}`,
};
});
- },
+ }
@action
onChangeDateRange(range) {
@@ -200,7 +204,7 @@ export default Component.extend({
startDate: range.from,
endDate: range.to,
});
- },
+ }
@action
applyFilter(id, value) {
@@ -215,7 +219,7 @@ export default Component.extend({
this.send("refreshReport", {
filters: customFilters,
});
- },
+ }
@action
refreshReport(options = {}) {
@@ -238,7 +242,7 @@ export default Component.extend({
? this.get("filters.customFilters")
: options.filters,
});
- },
+ }
@action
exportCsv() {
@@ -254,7 +258,7 @@ export default Component.extend({
}
exportEntity("report", args).then(outputExportResult);
- },
+ }
@action
onChangeMode(mode) {
@@ -263,7 +267,7 @@ export default Component.extend({
this.send("refreshReport", {
chartGrouping: null,
});
- },
+ }
_computeReport() {
if (!this.element || this.isDestroying || this.isDestroyed) {
@@ -306,7 +310,7 @@ export default Component.extend({
}
this._renderReport(report, this.forcedModes, this.currentMode);
- },
+ }
_renderReport(report, forcedModes, currentMode) {
const modes = forcedModes ? forcedModes.split(",") : report.modes;
@@ -317,10 +321,10 @@ export default Component.extend({
currentMode,
options: this._buildOptions(currentMode, report),
});
- },
+ }
_fetchReport() {
- this._super(...arguments);
+ undefined;
this.setProperties({ isLoading: true, rateLimitationString: null });
@@ -349,7 +353,7 @@ export default Component.extend({
ReportLoader.enqueue(this.dataSourceName, payload.data, callback);
});
- },
+ }
_buildPayload(facets) {
let payload = { data: { facets } };
@@ -375,7 +379,7 @@ export default Component.extend({
}
return payload;
- },
+ }
_buildOptions(mode, report) {
if (mode === "table") {
@@ -393,7 +397,7 @@ export default Component.extend({
})
);
}
- },
+ }
_loadReport(jsonReport) {
Report.fillMissingDates(jsonReport, { filledField: "chartData" });
@@ -423,5 +427,5 @@ export default Component.extend({
}
return Report.create(jsonReport);
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/admin-watched-word.js b/app/assets/javascripts/admin/addon/components/admin-watched-word.js
index 7de7e3d8ab..d6bde8016d 100644
--- a/app/assets/javascripts/admin/addon/components/admin-watched-word.js
+++ b/app/assets/javascripts/admin/addon/components/admin-watched-word.js
@@ -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 Component from "@ember/component";
import discourseComputed from "discourse-common/utils/decorators";
import { action } from "@ember/object";
import I18n from "I18n";
-import { inject as service } from "@ember/service";
-export default Component.extend({
- classNames: ["watched-word"],
- dialog: service(),
+@classNames("watched-word")
+export default class AdminWatchedWord extends Component {
+ @service dialog;
- isReplace: equal("actionKey", "replace"),
- isTag: equal("actionKey", "tag"),
- isLink: equal("actionKey", "link"),
- isCaseSensitive: alias("word.case_sensitive"),
+ @equal("actionKey", "replace") isReplace;
+
+ @equal("actionKey", "tag") isTag;
+
+ @equal("actionKey", "link") isLink;
+
+ @alias("word.case_sensitive") isCaseSensitive;
@discourseComputed("word.replacement")
tags(replacement) {
return replacement.split(",");
- },
+ }
@action
deleteWord() {
@@ -33,5 +37,5 @@ export default Component.extend({
})
);
});
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/admin-wrapper.js b/app/assets/javascripts/admin/addon/components/admin-wrapper.js
index d6a3564d42..45410964be 100644
--- a/app/assets/javascripts/admin/addon/components/admin-wrapper.js
+++ b/app/assets/javascripts/admin/addon/components/admin-wrapper.js
@@ -1,14 +1,14 @@
import Component from "@ember/component";
-export default Component.extend({
+export default class AdminWrapper extends Component {
didInsertElement() {
- this._super(...arguments);
+ super.didInsertElement(...arguments);
document.querySelector("html").classList.add("admin-area");
document.querySelector("body").classList.add("admin-interface");
- },
+ }
willDestroyElement() {
- this._super(...arguments);
+ super.willDestroyElement(...arguments);
document.querySelector("html").classList.remove("admin-area");
document.querySelector("body").classList.remove("admin-interface");
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/cancel-link.js b/app/assets/javascripts/admin/addon/components/cancel-link.js
index 0e6d50b17d..7b78896e83 100644
--- a/app/assets/javascripts/admin/addon/components/cancel-link.js
+++ b/app/assets/javascripts/admin/addon/components/cancel-link.js
@@ -1,4 +1,4 @@
+import { tagName } from "@ember-decorators/component";
import Component from "@ember/component";
-export default Component.extend({
- tagName: "",
-});
+@tagName("")
+export default class CancelLink extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/color-input.js b/app/assets/javascripts/admin/addon/components/color-input.js
index 2974b43871..662b6eb714 100644
--- a/app/assets/javascripts/admin/addon/components/color-input.js
+++ b/app/assets/javascripts/admin/addon/components/color-input.js
@@ -1,3 +1,4 @@
+import { classNames } from "@ember-decorators/component";
import { action, computed } from "@ember/object";
import Component from "@ember/component";
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.
@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,
-
- styleSelection: true,
-
- maxlength: computed("onlyHex", function () {
+ @computed("onlyHex")
+ get maxlength() {
return this.onlyHex ? 6 : null;
- }),
+ }
- normalizedHexValue: computed("hexValue", function () {
+ @computed("hexValue")
+ get normalizedHexValue() {
return this.normalize(this.hexValue);
- }),
+ }
normalize(color) {
if (this._valid(color)) {
@@ -40,19 +41,19 @@ export default Component.extend({
}
}
return color;
- },
+ }
@action
onHexInput(color) {
if (this.attrs.onChangeColor) {
this.attrs.onChangeColor(this.normalize(color || ""));
}
- },
+ }
@action
onPickerInput(event) {
this.set("hexValue", event.target.value.replace("#", ""));
- },
+ }
@observes("hexValue", "brightnessValue", "valid")
hexValueChanged() {
@@ -65,9 +66,9 @@ export default Component.extend({
if (this._valid()) {
this.element.querySelector(".picker").value = this.normalize(hex);
}
- },
+ }
_valid(color = this.hexValue) {
return /^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(color);
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/dashboard-new-feature-item.js b/app/assets/javascripts/admin/addon/components/dashboard-new-feature-item.js
index 87d5ddb040..80e6cd8a16 100644
--- a/app/assets/javascripts/admin/addon/components/dashboard-new-feature-item.js
+++ b/app/assets/javascripts/admin/addon/components/dashboard-new-feature-item.js
@@ -1,3 +1,3 @@
import Component from "@ember/component";
-export default Component.extend({});
+export default class DashboardNewFeatureItem extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/dashboard-new-features.js b/app/assets/javascripts/admin/addon/components/dashboard-new-features.js
index 6e8defb93c..0dcf5aaf33 100644
--- a/app/assets/javascripts/admin/addon/components/dashboard-new-features.js
+++ b/app/assets/javascripts/admin/addon/components/dashboard-new-features.js
@@ -1,15 +1,16 @@
+import { classNameBindings, classNames } from "@ember-decorators/component";
import Component from "@ember/component";
import { action, computed } from "@ember/object";
import { ajax } from "discourse/lib/ajax";
-export default Component.extend({
- newFeatures: null,
- classNames: ["section", "dashboard-new-features"],
- classNameBindings: ["hasUnseenFeatures:ordered-first"],
- releaseNotesLink: null,
+@classNames("section", "dashboard-new-features")
+@classNameBindings("hasUnseenFeatures:ordered-first")
+export default class DashboardNewFeatures extends Component {
+ newFeatures = null;
+ releaseNotesLink = null;
init() {
- this._super(...arguments);
+ super.init(...arguments);
ajax("/admin/dashboard/new-features.json").then((json) => {
if (!this.element || this.isDestroying || this.isDestroyed) {
@@ -22,16 +23,17 @@ export default Component.extend({
releaseNotesLink: json.release_notes_link,
});
});
- },
+ }
- columnCountClass: computed("newFeatures", function () {
+ @computed("newFeatures")
+ get columnCountClass() {
return this.newFeatures.length > 2 ? "three-or-more-items" : "";
- }),
+ }
@action
dismissNewFeatures() {
ajax("/admin/dashboard/mark-new-features-as-seen.json", {
type: "PUT",
}).then(() => this.set("hasUnseenFeatures", false));
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/dashboard-problems.js b/app/assets/javascripts/admin/addon/components/dashboard-problems.js
index 87d5ddb040..c4df8401e0 100644
--- a/app/assets/javascripts/admin/addon/components/dashboard-problems.js
+++ b/app/assets/javascripts/admin/addon/components/dashboard-problems.js
@@ -1,3 +1,3 @@
import Component from "@ember/component";
-export default Component.extend({});
+export default class DashboardProblems extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/emoji-value-list.js b/app/assets/javascripts/admin/addon/components/emoji-value-list.js
index 3f2810383d..40363b874d 100644
--- a/app/assets/javascripts/admin/addon/components/emoji-value-list.js
+++ b/app/assets/javascripts/admin/addon/components/emoji-value-list.js
@@ -1,3 +1,4 @@
+import { classNameBindings } from "@ember-decorators/component";
import Component from "@ember/component";
import I18n from "I18n";
import discourseComputed from "discourse-common/utils/decorators";
@@ -6,12 +7,12 @@ import { action, set, setProperties } from "@ember/object";
import { schedule } from "@ember/runloop";
import discourseLater from "discourse-common/lib/later";
-export default Component.extend({
- classNameBindings: [":value-list", ":emoji-list"],
- values: null,
- validationMessage: null,
- emojiPickerIsActive: false,
- isEditorFocused: false,
+@classNameBindings(":value-list", ":emoji-list")
+export default class EmojiValueList extends Component {
+ values = null;
+ validationMessage = null;
+ emojiPickerIsActive = false;
+ isEditorFocused = false;
@discourseComputed("values")
collection(values) {
@@ -28,14 +29,14 @@ export default Component.extend({
emojiUrl: emojiUrlFor(value),
};
});
- },
+ }
@action
closeEmojiPicker() {
this.collection.setEach("isEditing", false);
this.set("emojiPickerIsActive", false);
this.set("isEditorFocused", false);
- },
+ }
@action
emojiSelected(code) {
@@ -65,12 +66,12 @@ export default Component.extend({
this.set("emojiPickerIsActive", false);
this.set("isEditorFocused", false);
- },
+ }
@discourseComputed("collection")
showUpDownButtons(collection) {
return collection.length - 1 ? true : false;
- },
+ }
_splitValues(values) {
if (values && values.length) {
@@ -91,7 +92,7 @@ export default Component.extend({
} else {
return [];
}
- },
+ }
@action
editValue(index) {
@@ -111,12 +112,12 @@ export default Component.extend({
}
}, 100);
});
- },
+ }
@action
removeValue(value) {
this._removeValue(value);
- },
+ }
@action
shift(operation, index) {
@@ -133,7 +134,7 @@ export default Component.extend({
this.collection.insertAt(futureIndex, shiftedEmoji);
this._saveValues();
- },
+ }
_validateInput(input) {
this.set("validationMessage", null);
@@ -147,12 +148,12 @@ export default Component.extend({
}
return true;
- },
+ }
_removeValue(value) {
this.collection.removeObject(value);
this._saveValues();
- },
+ }
_replaceValue(index, newValue) {
const item = this.collection[index];
@@ -161,9 +162,9 @@ export default Component.extend({
}
set(item, "value", newValue);
this._saveValues();
- },
+ }
_saveValues() {
this.set("values", this.collection.mapBy("value").join("|"));
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/flag-user-lists.js b/app/assets/javascripts/admin/addon/components/flag-user-lists.js
index 8b88604768..1a9dea9032 100644
--- a/app/assets/javascripts/admin/addon/components/flag-user-lists.js
+++ b/app/assets/javascripts/admin/addon/components/flag-user-lists.js
@@ -1,4 +1,4 @@
+import { classNames } from "@ember-decorators/component";
import Component from "@ember/component";
-export default Component.extend({
- classNames: ["flag-user-lists"],
-});
+@classNames("flag-user-lists")
+export default class FlagUserLists extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/flag-user.js b/app/assets/javascripts/admin/addon/components/flag-user.js
index 87d5ddb040..ef9b83f780 100644
--- a/app/assets/javascripts/admin/addon/components/flag-user.js
+++ b/app/assets/javascripts/admin/addon/components/flag-user.js
@@ -1,3 +1,3 @@
import Component from "@ember/component";
-export default Component.extend({});
+export default class FlagUser extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/highlighted-code.js b/app/assets/javascripts/admin/addon/components/highlighted-code.js
index 21cfaf6b15..5f0331fac5 100644
--- a/app/assets/javascripts/admin/addon/components/highlighted-code.js
+++ b/app/assets/javascripts/admin/addon/components/highlighted-code.js
@@ -2,10 +2,10 @@ import { observes, on } from "discourse-common/utils/decorators";
import Component from "@ember/component";
import highlightSyntax from "discourse/lib/highlight-syntax";
-export default Component.extend({
+export default class HighlightedCode extends Component {
@on("didInsertElement")
@observes("code")
_refresh() {
highlightSyntax(this.element, this.siteSettings, this.session);
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/inline-edit-checkbox.js b/app/assets/javascripts/admin/addon/components/inline-edit-checkbox.js
index cfbd2f82f9..8618e4044b 100644
--- a/app/assets/javascripts/admin/addon/components/inline-edit-checkbox.js
+++ b/app/assets/javascripts/admin/addon/components/inline-edit-checkbox.js
@@ -1,15 +1,15 @@
+import { classNames } from "@ember-decorators/component";
import Component from "@ember/component";
import { action } from "@ember/object";
import discourseComputed from "discourse-common/utils/decorators";
-export default Component.extend({
- classNames: ["inline-edit"],
-
- buffer: null,
- bufferModelId: null,
+@classNames("inline-edit")
+export default class InlineEditCheckbox extends Component {
+ buffer = null;
+ bufferModelId = null;
didReceiveAttrs() {
- this._super(...arguments);
+ super.didReceiveAttrs(...arguments);
if (this.modelId !== this.bufferModelId) {
// HACK: The condition above ensures this method is called only when its
@@ -24,21 +24,21 @@ export default Component.extend({
bufferModelId: this.modelId,
});
}
- },
+ }
@discourseComputed("checked", "buffer")
changed(checked, buffer) {
return !!checked !== !!buffer;
- },
+ }
@action
apply() {
this.set("checked", this.buffer);
this.action();
- },
+ }
@action
cancel() {
this.set("buffer", this.checked);
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/install-theme-item.js b/app/assets/javascripts/admin/addon/components/install-theme-item.js
index b8d8823109..56cb7989da 100644
--- a/app/assets/javascripts/admin/addon/components/install-theme-item.js
+++ b/app/assets/javascripts/admin/addon/components/install-theme-item.js
@@ -1,4 +1,4 @@
+import { classNames } from "@ember-decorators/component";
import Component from "@ember/component";
-export default Component.extend({
- classNames: ["install-theme-item"],
-});
+@classNames("install-theme-item")
+export default class InstallThemeItem extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/ip-lookup.js b/app/assets/javascripts/admin/addon/components/ip-lookup.js
index 02a5240564..42c5f12811 100644
--- a/app/assets/javascripts/admin/addon/components/ip-lookup.js
+++ b/app/assets/javascripts/admin/addon/components/ip-lookup.js
@@ -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 Component from "@ember/component";
import EmberObject, { action } from "@ember/object";
@@ -6,12 +8,11 @@ import { ajax } from "discourse/lib/ajax";
import copyText from "discourse/lib/copy-text";
import discourseComputed from "discourse-common/utils/decorators";
import discourseLater from "discourse-common/lib/later";
-import { inject as service } from "@ember/service";
import { popupAjaxError } from "discourse/lib/ajax-error";
-export default Component.extend({
- classNames: ["ip-lookup"],
- dialog: service(),
+@classNames("ip-lookup")
+export default class IpLookup extends Component {
+ @service dialog;
@discourseComputed("other_accounts.length", "totalOthersWithSameIP")
otherAccountsToDelete(otherAccountsLength, totalOthersWithSameIP) {
@@ -19,101 +20,100 @@ export default Component.extend({
const total = Math.min(50, totalOthersWithSameIP || 0);
const visible = Math.min(50, otherAccountsLength || 0);
return Math.max(visible, total);
- },
+ }
@action
hide(event) {
event?.preventDefault();
this.set("show", false);
- },
+ }
- actions: {
- lookup() {
- this.set("show", true);
+ @action
+ lookup() {
+ this.set("show", true);
- if (!this.location) {
- ajax("/admin/users/ip-info", {
- data: { ip: this.ip },
- }).then((location) =>
- this.set("location", EmberObject.create(location))
- );
- }
+ if (!this.location) {
+ ajax("/admin/users/ip-info", {
+ data: { ip: this.ip },
+ }).then((location) => this.set("location", EmberObject.create(location)));
+ }
- if (!this.other_accounts) {
- this.set("otherAccountsLoading", true);
+ if (!this.other_accounts) {
+ this.set("otherAccountsLoading", true);
- const data = {
- ip: this.ip,
- exclude: this.userId,
- order: "trust_level DESC",
- };
+ const data = {
+ ip: this.ip,
+ exclude: this.userId,
+ order: "trust_level DESC",
+ };
- ajax("/admin/users/total-others-with-same-ip", {
- data,
- }).then((result) => this.set("totalOthersWithSameIP", result.total));
+ ajax("/admin/users/total-others-with-same-ip", {
+ data,
+ }).then((result) => this.set("totalOthersWithSameIP", result.total));
- AdminUser.findAll("active", data).then((users) => {
- this.setProperties({
- other_accounts: users,
- otherAccountsLoading: false,
- });
+ AdminUser.findAll("active", data).then((users) => {
+ this.setProperties({
+ other_accounts: users,
+ otherAccountsLoading: false,
});
- }
- },
-
- copy() {
- let text = `IP: ${this.ip}\n`;
- const location = this.location;
- if (location) {
- if (location.hostname) {
- text += `${I18n.t("ip_lookup.hostname")}: ${location.hostname}\n`;
- }
-
- text += I18n.t("ip_lookup.location");
- if (location.location) {
- text += `: ${location.location}\n`;
- } else {
- text += `: ${I18n.t("ip_lookup.location_not_found")}\n`;
- }
-
- if (location.organization) {
- text += I18n.t("ip_lookup.organisation");
- text += `: ${location.organization}\n`;
- }
- }
-
- const $copyRange = $('
');
- $copyRange.html(text.trim().replace(/\n/g, "
"));
- $(document.body).append($copyRange);
- if (copyText(text, $copyRange[0])) {
- this.set("copied", true);
- discourseLater(() => this.set("copied", false), 2000);
- }
- $copyRange.remove();
- },
-
- deleteOtherAccounts() {
- this.dialog.yesNoConfirm({
- message: I18n.t("ip_lookup.confirm_delete_other_accounts"),
- didConfirm: () => {
- this.setProperties({
- other_accounts: null,
- otherAccountsLoading: true,
- totalOthersWithSameIP: null,
- });
-
- ajax("/admin/users/delete-others-with-same-ip.json", {
- type: "DELETE",
- data: {
- ip: this.ip,
- exclude: this.userId,
- order: "trust_level DESC",
- },
- })
- .catch(popupAjaxError)
- .finally(this.send("lookup"));
- },
});
- },
- },
-});
+ }
+ }
+
+ @action
+ copy() {
+ let text = `IP: ${this.ip}\n`;
+ const location = this.location;
+ if (location) {
+ if (location.hostname) {
+ text += `${I18n.t("ip_lookup.hostname")}: ${location.hostname}\n`;
+ }
+
+ text += I18n.t("ip_lookup.location");
+ if (location.location) {
+ text += `: ${location.location}\n`;
+ } else {
+ text += `: ${I18n.t("ip_lookup.location_not_found")}\n`;
+ }
+
+ if (location.organization) {
+ text += I18n.t("ip_lookup.organisation");
+ text += `: ${location.organization}\n`;
+ }
+ }
+
+ const $copyRange = $('');
+ $copyRange.html(text.trim().replace(/\n/g, "
"));
+ $(document.body).append($copyRange);
+ if (copyText(text, $copyRange[0])) {
+ this.set("copied", true);
+ discourseLater(() => this.set("copied", false), 2000);
+ }
+ $copyRange.remove();
+ }
+
+ @action
+ deleteOtherAccounts() {
+ this.dialog.yesNoConfirm({
+ message: I18n.t("ip_lookup.confirm_delete_other_accounts"),
+ didConfirm: () => {
+ this.setProperties({
+ other_accounts: null,
+ otherAccountsLoading: true,
+ totalOthersWithSameIP: null,
+ });
+
+ ajax("/admin/users/delete-others-with-same-ip.json", {
+ type: "DELETE",
+ data: {
+ ip: this.ip,
+ exclude: this.userId,
+ order: "trust_level DESC",
+ },
+ })
+ .catch(popupAjaxError)
+ .finally(this.send("lookup"));
+ },
+ });
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/moderation-history-item.js b/app/assets/javascripts/admin/addon/components/moderation-history-item.js
index 7f039c061e..6083ef60f5 100644
--- a/app/assets/javascripts/admin/addon/components/moderation-history-item.js
+++ b/app/assets/javascripts/admin/addon/components/moderation-history-item.js
@@ -1,4 +1,4 @@
+import { tagName } from "@ember-decorators/component";
import Component from "@ember/component";
-export default Component.extend({
- tagName: "tr",
-});
+@tagName("tr")
+export default class ModerationHistoryItem extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/permalink-form.js b/app/assets/javascripts/admin/addon/components/permalink-form.js
index 9c0c64de6b..129ab0d58e 100644
--- a/app/assets/javascripts/admin/addon/components/permalink-form.js
+++ b/app/assets/javascripts/admin/addon/components/permalink-form.js
@@ -1,3 +1,5 @@
+import { tagName } from "@ember-decorators/component";
+import { inject as service } from "@ember/service";
import Component from "@ember/component";
import I18n from "I18n";
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 { schedule } from "@ember/runloop";
import { action } from "@ember/object";
-import { inject as service } from "@ember/service";
-export default Component.extend({
- tagName: "",
- dialog: service(),
- formSubmitted: false,
- permalinkType: "topic_id",
- permalinkTypePlaceholder: fmt("permalinkType", "admin.permalink.%@"),
- action: null,
- permalinkTypeValue: null,
+@tagName("")
+export default class PermalinkForm extends Component {
+ @service dialog;
+
+ formSubmitted = false;
+ permalinkType = "topic_id";
+
+ @fmt("permalinkType", "admin.permalink.%@") permalinkTypePlaceholder;
+
+ action = null;
+ permalinkTypeValue = null;
@discourseComputed
permalinkTypes() {
@@ -25,21 +29,21 @@ export default Component.extend({
{ id: "tag_name", name: I18n.t("admin.permalink.tag_name") },
{ id: "external_url", name: I18n.t("admin.permalink.external_url") },
];
- },
+ }
@bind
focusPermalink() {
schedule("afterRender", () =>
document.querySelector(".permalink-url")?.focus()
);
- },
+ }
@action
submitFormOnEnter(event) {
if (event.key === "Enter") {
this.onSubmit();
}
- },
+ }
@action
onSubmit() {
@@ -84,5 +88,5 @@ export default Component.extend({
}
);
}
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/report-filters/bool.js b/app/assets/javascripts/admin/addon/components/report-filters/bool.js
index 544709791c..d406b1e87e 100644
--- a/app/assets/javascripts/admin/addon/components/report-filters/bool.js
+++ b/app/assets/javascripts/admin/addon/components/report-filters/bool.js
@@ -1,16 +1,16 @@
import FilterComponent from "admin/components/report-filters/filter";
import { action } from "@ember/object";
-export default FilterComponent.extend({
- checked: false,
+export default class Bool extends FilterComponent {
+ checked = false;
didReceiveAttrs() {
- this._super(...arguments);
+ super.didReceiveAttrs(...arguments);
this.set("checked", !!this.filter.default);
- },
+ }
@action
onChange() {
this.applyFilter(this.filter.id, !this.checked || undefined);
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/report-filters/category.js b/app/assets/javascripts/admin/addon/components/report-filters/category.js
index 877c3aee7a..c32e99c50f 100644
--- a/app/assets/javascripts/admin/addon/components/report-filters/category.js
+++ b/app/assets/javascripts/admin/addon/components/report-filters/category.js
@@ -1,12 +1,12 @@
+import { readOnly } from "@ember/object/computed";
import FilterComponent from "admin/components/report-filters/filter";
import { action } from "@ember/object";
-import { readOnly } from "@ember/object/computed";
-export default FilterComponent.extend({
- category: readOnly("filter.default"),
+export default class Category extends FilterComponent {
+ @readOnly("filter.default") category;
@action
onChange(categoryId) {
this.applyFilter(this.filter.id, categoryId || undefined);
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/report-filters/filter.js b/app/assets/javascripts/admin/addon/components/report-filters/filter.js
index e89fb38386..697611d1ac 100644
--- a/app/assets/javascripts/admin/addon/components/report-filters/filter.js
+++ b/app/assets/javascripts/admin/addon/components/report-filters/filter.js
@@ -1,9 +1,9 @@
import Component from "@ember/component";
import { action } from "@ember/object";
-export default Component.extend({
+export default class Filter extends Component {
@action
onChange(value) {
this.applyFilter(this.filter.id, value);
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/report-filters/group.js b/app/assets/javascripts/admin/addon/components/report-filters/group.js
index 30dd4c7b1b..8ac7eb3b9a 100644
--- a/app/assets/javascripts/admin/addon/components/report-filters/group.js
+++ b/app/assets/javascripts/admin/addon/components/report-filters/group.js
@@ -1,18 +1,18 @@
-import FilterComponent from "admin/components/report-filters/filter";
+import { classNames } from "@ember-decorators/component";
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
get groupOptions() {
return (this.site.groups || []).map((group) => {
return { name: group["name"], value: group["id"] };
});
- },
+ }
@computed("filter.default")
get groupId() {
return this.filter.default ? parseInt(this.filter.default, 10) : null;
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/report-filters/list.js b/app/assets/javascripts/admin/addon/components/report-filters/list.js
index 654269ecd0..7ecc076e96 100644
--- a/app/assets/javascripts/admin/addon/components/report-filters/list.js
+++ b/app/assets/javascripts/admin/addon/components/report-filters/list.js
@@ -1,3 +1,3 @@
import FilterComponent from "admin/components/report-filters/filter";
-export default FilterComponent.extend();
+export default class List extends FilterComponent {}
diff --git a/app/assets/javascripts/admin/addon/components/resumable-upload.js b/app/assets/javascripts/admin/addon/components/resumable-upload.js
index 87d5ddb040..abfa01ea01 100644
--- a/app/assets/javascripts/admin/addon/components/resumable-upload.js
+++ b/app/assets/javascripts/admin/addon/components/resumable-upload.js
@@ -1,3 +1,3 @@
import Component from "@ember/component";
-export default Component.extend({});
+export default class ResumableUpload extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/secret-value-list.js b/app/assets/javascripts/admin/addon/components/secret-value-list.js
index 1f31dc40e2..4530393fe5 100644
--- a/app/assets/javascripts/admin/addon/components/secret-value-list.js
+++ b/app/assets/javascripts/admin/addon/components/secret-value-list.js
@@ -1,15 +1,16 @@
+import { classNameBindings } from "@ember-decorators/component";
import Component from "@ember/component";
import I18n from "I18n";
import { isEmpty } from "@ember/utils";
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"],
- inputDelimiter: null,
- collection: null,
- values: null,
- validationMessage: null,
+@classNameBindings(":value-list", ":secret-value-list")
+export default class SecretValueList extends Component {
+ inputDelimiter = null;
+ collection = null;
+ values = null;
+ validationMessage = null;
@on("didReceiveAttrs")
_setupCollection() {
@@ -19,41 +20,43 @@ export default Component.extend({
"collection",
this._splitValues(values, this.inputDelimiter || "\n")
);
- },
+ }
- actions: {
- changeKey(index, event) {
- const newValue = event.target.value;
+ @action
+ changeKey(index, event) {
+ const newValue = event.target.value;
- if (this._checkInvalidInput(newValue)) {
- return;
- }
+ if (this._checkInvalidInput(newValue)) {
+ return;
+ }
- this._replaceValue(index, newValue, "key");
- },
+ this._replaceValue(index, newValue, "key");
+ }
- changeSecret(index, event) {
- const newValue = event.target.value;
+ @action
+ changeSecret(index, event) {
+ const newValue = event.target.value;
- if (this._checkInvalidInput(newValue)) {
- return;
- }
+ if (this._checkInvalidInput(newValue)) {
+ return;
+ }
- this._replaceValue(index, newValue, "secret");
- },
+ this._replaceValue(index, newValue, "secret");
+ }
- addValue() {
- if (this._checkInvalidInput([this.newKey, this.newSecret])) {
- return;
- }
- this._addValue(this.newKey, this.newSecret);
- this.setProperties({ newKey: "", newSecret: "" });
- },
+ @action
+ addValue() {
+ if (this._checkInvalidInput([this.newKey, this.newSecret])) {
+ return;
+ }
+ this._addValue(this.newKey, this.newSecret);
+ this.setProperties({ newKey: "", newSecret: "" });
+ }
- removeValue(value) {
- this._removeValue(value);
- },
- },
+ @action
+ removeValue(value) {
+ this._removeValue(value);
+ }
_checkInvalidInput(inputs) {
this.set("validationMessage", null);
@@ -66,25 +69,25 @@ export default Component.extend({
return true;
}
}
- },
+ }
_addValue(value, secret) {
this.collection.addObject({ key: value, secret });
this._saveValues();
- },
+ }
_removeValue(value) {
const collection = this.collection;
collection.removeObject(value);
this._saveValues();
- },
+ }
_replaceValue(index, newValue, keyName) {
let item = this.collection[index];
set(item, keyName, newValue);
this._saveValues();
- },
+ }
_saveValues() {
this.set(
@@ -95,7 +98,7 @@ export default Component.extend({
})
.join("\n")
);
- },
+ }
_splitValues(values, delimiter) {
if (values && values.length) {
@@ -113,5 +116,5 @@ export default Component.extend({
} else {
return [];
}
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/setting-validation-message.js b/app/assets/javascripts/admin/addon/components/setting-validation-message.js
index 87d5ddb040..4e60ec9c88 100644
--- a/app/assets/javascripts/admin/addon/components/setting-validation-message.js
+++ b/app/assets/javascripts/admin/addon/components/setting-validation-message.js
@@ -1,3 +1,3 @@
import Component from "@ember/component";
-export default Component.extend({});
+export default class SettingValidationMessage extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/silence-details.js b/app/assets/javascripts/admin/addon/components/silence-details.js
index 0e6d50b17d..4921a0950e 100644
--- a/app/assets/javascripts/admin/addon/components/silence-details.js
+++ b/app/assets/javascripts/admin/addon/components/silence-details.js
@@ -1,4 +1,4 @@
+import { tagName } from "@ember-decorators/component";
import Component from "@ember/component";
-export default Component.extend({
- tagName: "",
-});
+@tagName("")
+export default class SilenceDetails extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/simple-list.js b/app/assets/javascripts/admin/addon/components/simple-list.js
index 5ca219ee80..d7e0bf69f3 100644
--- a/app/assets/javascripts/admin/addon/components/simple-list.js
+++ b/app/assets/javascripts/admin/addon/components/simple-list.js
@@ -1,34 +1,36 @@
+import { classNameBindings } from "@ember-decorators/component";
+import { empty } from "@ember/object/computed";
import Component from "@ember/component";
import { action } from "@ember/object";
-import { empty } from "@ember/object/computed";
import discourseComputed, { on } from "discourse-common/utils/decorators";
-export default Component.extend({
- classNameBindings: [":simple-list", ":value-list"],
- inputEmpty: empty("newValue"),
- inputDelimiter: null,
- newValue: "",
- collection: null,
- values: null,
+@classNameBindings(":simple-list", ":value-list")
+export default class SimpleList extends Component {
+ @empty("newValue") inputEmpty;
+
+ inputDelimiter = null;
+ newValue = "";
+ collection = null;
+ values = null;
@on("didReceiveAttrs")
_setupCollection() {
this.set("collection", this._splitValues(this.values, this.inputDelimiter));
- },
+ }
keyDown(event) {
if (event.which === 13) {
this.addValue(this.newValue);
return;
}
- },
+ }
@action
changeValue(index, event) {
this.collection.replace(index, 1, [event.target.value]);
this.collection.arrayContentDidChange(index);
this._onChange();
- },
+ }
@action
addValue(newValue) {
@@ -39,13 +41,13 @@ export default Component.extend({
this.set("newValue", null);
this.collection.addObject(newValue);
this._onChange();
- },
+ }
@action
removeValue(value) {
this.collection.removeObject(value);
this._onChange();
- },
+ }
@action
shift(operation, index) {
@@ -62,20 +64,20 @@ export default Component.extend({
this.collection.insertAt(futureIndex, shiftedValue);
this._onChange();
- },
+ }
_onChange() {
this.onChange?.(this.collection);
- },
+ }
@discourseComputed("collection")
showUpDownButtons(collection) {
return collection.length - 1 ? true : false;
- },
+ }
_splitValues(values, delimiter) {
return values && values.length
? values.split(delimiter || "\n").filter(Boolean)
: [];
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/site-customization-change-details.js b/app/assets/javascripts/admin/addon/components/site-customization-change-details.js
index 87d5ddb040..cb9487ad2b 100644
--- a/app/assets/javascripts/admin/addon/components/site-customization-change-details.js
+++ b/app/assets/javascripts/admin/addon/components/site-customization-change-details.js
@@ -1,3 +1,3 @@
import Component from "@ember/component";
-export default Component.extend({});
+export default class SiteCustomizationChangeDetails extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/site-customization-change-field.js b/app/assets/javascripts/admin/addon/components/site-customization-change-field.js
index 87d5ddb040..0e361124a0 100644
--- a/app/assets/javascripts/admin/addon/components/site-customization-change-field.js
+++ b/app/assets/javascripts/admin/addon/components/site-customization-change-field.js
@@ -1,3 +1,3 @@
import Component from "@ember/component";
-export default Component.extend({});
+export default class SiteCustomizationChangeField extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/site-setting.js b/app/assets/javascripts/admin/addon/components/site-setting.js
index 888daa3117..f0d9da1101 100644
--- a/app/assets/javascripts/admin/addon/components/site-setting.js
+++ b/app/assets/javascripts/admin/addon/components/site-setting.js
@@ -1,18 +1,20 @@
+import { readOnly } from "@ember/object/computed";
import BufferedContent from "discourse/mixins/buffered-content";
import Component from "@ember/component";
import SettingComponent from "admin/mixins/setting-component";
import SiteSetting from "admin/models/site-setting";
-import { readOnly } from "@ember/object/computed";
-export default Component.extend(BufferedContent, SettingComponent, {
- updateExistingUsers: null,
+export default class SiteSettingComponent extends Component.extend(
+ BufferedContent,
+ SettingComponent
+) {
+ updateExistingUsers = null;
+ @readOnly("setting.staffLogFilter") staffLogFilter;
_save() {
const setting = this.buffered;
return SiteSetting.update(setting.get("setting"), setting.get("value"), {
updateExistingUsers: this.updateExistingUsers,
});
- },
-
- staffLogFilter: readOnly("setting.staffLogFilter"),
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/category-list.js b/app/assets/javascripts/admin/addon/components/site-settings/category-list.js
index 9dc792e6de..44fdee3a71 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/category-list.js
+++ b/app/assets/javascripts/admin/addon/components/site-settings/category-list.js
@@ -1,15 +1,15 @@
+import { action, computed } from "@ember/object";
import Category from "discourse/models/category";
import Component from "@ember/component";
-import { computed } from "@ember/object";
-export default Component.extend({
- selectedCategories: computed("value", function () {
+export default class CategoryList extends Component {
+ @computed("value")
+ get selectedCategories() {
return Category.findByIds(this.value.split("|").filter(Boolean));
- }),
+ }
- actions: {
- onChangeSelectedCategories(value) {
- this.set("value", (value || []).mapBy("id").join("|"));
- },
- },
-});
+ @action
+ onChangeSelectedCategories(value) {
+ this.set("value", (value || []).mapBy("id").join("|"));
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/category.js b/app/assets/javascripts/admin/addon/components/site-settings/category.js
index 87d5ddb040..8e11b94d30 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/category.js
+++ b/app/assets/javascripts/admin/addon/components/site-settings/category.js
@@ -1,3 +1,3 @@
import Component from "@ember/component";
-export default Component.extend({});
+export default class Category extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/color.js b/app/assets/javascripts/admin/addon/components/site-settings/color.js
index 39df6da7d5..a044348c0b 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/color.js
+++ b/app/assets/javascripts/admin/addon/components/site-settings/color.js
@@ -24,8 +24,9 @@ function RGBToHex(rgb) {
return "#" + r + g + b;
}
-export default Component.extend({
- valid: computed("value", function () {
+export default class Color extends Component {
+ @computed("value")
+ get valid() {
let value = this.value.toLowerCase();
let testColor = new Option().style;
@@ -43,10 +44,10 @@ export default Component.extend({
}
return testColor.color && hexifiedColor === value;
- }),
+ }
@action
onChangeColor(color) {
this.set("value", color);
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/compact-list.js b/app/assets/javascripts/admin/addon/components/site-settings/compact-list.js
index 246d56066a..35d86e32dc 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/compact-list.js
+++ b/app/assets/javascripts/admin/addon/components/site-settings/compact-list.js
@@ -1,40 +1,36 @@
+import { action, computed } from "@ember/object";
import Component from "@ember/component";
-import { computed } from "@ember/object";
import { makeArray } from "discourse-common/lib/helpers";
-export default Component.extend({
- tokenSeparator: "|",
+export default class CompactList extends Component {
+ tokenSeparator = "|";
+ createdChoices = null;
- createdChoices: null,
-
- settingValue: computed("value", function () {
+ @computed("value")
+ get settingValue() {
return this.value.toString().split(this.tokenSeparator).filter(Boolean);
- }),
+ }
- settingChoices: computed(
- "settingValue",
- "setting.choices.[]",
- "createdChoices.[]",
- function () {
- return [
- ...new Set([
- ...makeArray(this.settingValue),
- ...makeArray(this.setting.choices),
- ...makeArray(this.createdChoices),
- ]),
- ];
- }
- ),
+ @computed("settingValue", "setting.choices.[]", "createdChoices.[]")
+ get settingChoices() {
+ return [
+ ...new Set([
+ ...makeArray(this.settingValue),
+ ...makeArray(this.setting.choices),
+ ...makeArray(this.createdChoices),
+ ]),
+ ];
+ }
- actions: {
- onChangeListSetting(value) {
- this.set("value", value.join(this.tokenSeparator));
- },
+ @action
+ onChangeListSetting(value) {
+ this.set("value", value.join(this.tokenSeparator));
+ }
- onChangeChoices(choices) {
- this.set("createdChoices", [
- ...new Set([...makeArray(this.createdChoices), ...makeArray(choices)]),
- ]);
- },
- },
-});
+ @action
+ onChangeChoices(choices) {
+ this.set("createdChoices", [
+ ...new Set([...makeArray(this.createdChoices), ...makeArray(choices)]),
+ ]);
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/emoji-list.js b/app/assets/javascripts/admin/addon/components/site-settings/emoji-list.js
index 87d5ddb040..706d6d8084 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/emoji-list.js
+++ b/app/assets/javascripts/admin/addon/components/site-settings/emoji-list.js
@@ -1,3 +1,3 @@
import Component from "@ember/component";
-export default Component.extend({});
+export default class EmojiList extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/enum.js b/app/assets/javascripts/admin/addon/components/site-settings/enum.js
index 87d5ddb040..faebe31c2d 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/enum.js
+++ b/app/assets/javascripts/admin/addon/components/site-settings/enum.js
@@ -1,3 +1,3 @@
import Component from "@ember/component";
-export default Component.extend({});
+export default class Enum extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/group-list.js b/app/assets/javascripts/admin/addon/components/site-settings/group-list.js
index ad9dbbfd1c..e483afc395 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/group-list.js
+++ b/app/assets/javascripts/admin/addon/components/site-settings/group-list.js
@@ -1,25 +1,25 @@
+import { action, computed } from "@ember/object";
import Component from "@ember/component";
-import { computed } from "@ember/object";
-export default Component.extend({
- tokenSeparator: "|",
+export default class GroupList extends Component {
+ tokenSeparator = "|";
+ nameProperty = "name";
+ valueProperty = "id";
- nameProperty: "name",
- valueProperty: "id",
-
- groupChoices: computed("site.groups", function () {
+ @computed("site.groups")
+ get groupChoices() {
return (this.site.groups || []).map((g) => {
return { name: g.name, id: g.id.toString() };
});
- }),
+ }
- settingValue: computed("value", function () {
+ @computed("value")
+ get settingValue() {
return (this.value || "").split(this.tokenSeparator).filter(Boolean);
- }),
+ }
- actions: {
- onChangeGroupListSetting(value) {
- this.set("value", value.join(this.tokenSeparator));
- },
- },
-});
+ @action
+ onChangeGroupListSetting(value) {
+ this.set("value", value.join(this.tokenSeparator));
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/host-list.js b/app/assets/javascripts/admin/addon/components/site-settings/host-list.js
index 8cc320da8f..3ce615eb4f 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/host-list.js
+++ b/app/assets/javascripts/admin/addon/components/site-settings/host-list.js
@@ -1,14 +1,14 @@
import Component from "@ember/component";
import { action, computed } from "@ember/object";
-export default Component.extend({
- tokenSeparator: "|",
- choices: null,
+export default class HostList extends Component {
+ tokenSeparator = "|";
+ choices = null;
@computed("value")
get settingValue() {
return this.value.toString().split(this.tokenSeparator).filter(Boolean);
- },
+ }
@action
onChange(value) {
@@ -17,5 +17,5 @@ export default Component.extend({
}
this.set("value", value.join(this.tokenSeparator));
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/list.js b/app/assets/javascripts/admin/addon/components/site-settings/list.js
index 87d5ddb040..d23ceb2ba7 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/list.js
+++ b/app/assets/javascripts/admin/addon/components/site-settings/list.js
@@ -1,3 +1,3 @@
import Component from "@ember/component";
-export default Component.extend({});
+export default class List extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/named-list.js b/app/assets/javascripts/admin/addon/components/site-settings/named-list.js
index c6cf872d79..fadfedc9f0 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/named-list.js
+++ b/app/assets/javascripts/admin/addon/components/site-settings/named-list.js
@@ -1,13 +1,13 @@
import Component from "@ember/component";
import { action, computed } from "@ember/object";
-export default Component.extend({
- tokenSeparator: "|",
+export default class NamedList extends Component {
+ tokenSeparator = "|";
@computed("value")
get settingValue() {
return this.value.toString().split(this.tokenSeparator).filter(Boolean);
- },
+ }
@computed("setting.choices.[]", "settingValue")
get settingChoices() {
@@ -24,10 +24,10 @@ export default Component.extend({
}
return choices;
- },
+ }
@action
onChangeListSetting(value) {
this.set("value", value.join(this.tokenSeparator));
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/secret-list.js b/app/assets/javascripts/admin/addon/components/site-settings/secret-list.js
index 87d5ddb040..167dbdc6e5 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/secret-list.js
+++ b/app/assets/javascripts/admin/addon/components/site-settings/secret-list.js
@@ -1,3 +1,3 @@
import Component from "@ember/component";
-export default Component.extend({});
+export default class SecretList extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/simple-list.js b/app/assets/javascripts/admin/addon/components/site-settings/simple-list.js
index 383dfeee42..ccc75e2b9d 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/simple-list.js
+++ b/app/assets/javascripts/admin/addon/components/site-settings/simple-list.js
@@ -1,11 +1,11 @@
import Component from "@ember/component";
import { action } from "@ember/object";
-export default Component.extend({
- inputDelimiter: "|",
+export default class SimpleList extends Component {
+ inputDelimiter = "|";
@action
onChange(value) {
this.set("value", value.join(this.inputDelimiter || "\n"));
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/string.js b/app/assets/javascripts/admin/addon/components/site-settings/string.js
index 2224c8745f..c38c1e0908 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/string.js
+++ b/app/assets/javascripts/admin/addon/components/site-settings/string.js
@@ -2,7 +2,7 @@ import { action } from "@ember/object";
import Component from "@ember/component";
import showModal from "discourse/lib/show-modal";
-export default Component.extend({
+export default class String extends Component {
@action
launchJsonEditorModal() {
const schemaModal = showModal("json-schema-editor", {
@@ -16,5 +16,5 @@ export default Component.extend({
schemaModal.set("onClose", () => {
this.set("value", schemaModal.model.value);
});
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/upload.js b/app/assets/javascripts/admin/addon/components/site-settings/upload.js
index 87d5ddb040..ac849a7364 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/upload.js
+++ b/app/assets/javascripts/admin/addon/components/site-settings/upload.js
@@ -1,3 +1,3 @@
import Component from "@ember/component";
-export default Component.extend({});
+export default class Upload extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/uploaded-image-list.js b/app/assets/javascripts/admin/addon/components/site-settings/uploaded-image-list.js
index d66b07e0e8..4d241b84f7 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/uploaded-image-list.js
+++ b/app/assets/javascripts/admin/addon/components/site-settings/uploaded-image-list.js
@@ -1,16 +1,16 @@
+import { action } from "@ember/object";
import Component from "@ember/component";
import showModal from "discourse/lib/show-modal";
-export default Component.extend({
- actions: {
- showUploadModal({ value, setting }) {
- showModal("admin-uploaded-image-list", {
- admin: true,
- title: `admin.site_settings.${setting.setting}.title`,
- model: { value, setting },
- }).setProperties({
- save: (v) => this.set("value", v),
- });
- },
- },
-});
+export default class UploadedImageList extends Component {
+ @action
+ showUploadModal({ value, setting }) {
+ showModal("admin-uploaded-image-list", {
+ admin: true,
+ title: `admin.site_settings.${setting.setting}.title`,
+ model: { value, setting },
+ }).setProperties({
+ save: (v) => this.set("value", v),
+ });
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/url-list.js b/app/assets/javascripts/admin/addon/components/site-settings/url-list.js
index 87d5ddb040..87e25fd416 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/url-list.js
+++ b/app/assets/javascripts/admin/addon/components/site-settings/url-list.js
@@ -1,3 +1,3 @@
import Component from "@ember/component";
-export default Component.extend({});
+export default class UrlList extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/site-settings/value-list.js b/app/assets/javascripts/admin/addon/components/site-settings/value-list.js
index 87d5ddb040..c358c36779 100644
--- a/app/assets/javascripts/admin/addon/components/site-settings/value-list.js
+++ b/app/assets/javascripts/admin/addon/components/site-settings/value-list.js
@@ -1,3 +1,3 @@
import Component from "@ember/component";
-export default Component.extend({});
+export default class ValueList extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/site-text-summary.js b/app/assets/javascripts/admin/addon/components/site-text-summary.js
index 8f9b3f3b6c..15ad253a68 100644
--- a/app/assets/javascripts/admin/addon/components/site-text-summary.js
+++ b/app/assets/javascripts/admin/addon/components/site-text-summary.js
@@ -1,11 +1,11 @@
+import { classNameBindings, classNames } from "@ember-decorators/component";
import Component from "@ember/component";
import highlightHTML from "discourse/lib/highlight-html";
import { on } from "discourse-common/utils/decorators";
-export default Component.extend({
- classNames: ["site-text"],
- classNameBindings: ["siteText.overridden"],
-
+@classNames("site-text")
+@classNameBindings("siteText.overridden")
+export default class SiteTextSummary extends Component {
@on("didInsertElement")
highlightTerm() {
const term = this._searchTerm();
@@ -19,11 +19,11 @@ export default Component.extend({
}
);
}
- },
+ }
click() {
this.editAction(this.siteText);
- },
+ }
_searchTerm() {
const regex = this.searchRegex;
@@ -37,5 +37,5 @@ export default Component.extend({
}
return this.term;
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/staff-actions.js b/app/assets/javascripts/admin/addon/components/staff-actions.js
index c639a04746..4e4fe55c50 100644
--- a/app/assets/javascripts/admin/addon/components/staff-actions.js
+++ b/app/assets/javascripts/admin/addon/components/staff-actions.js
@@ -1,10 +1,10 @@
+import { tagName } from "@ember-decorators/component";
import { action } from "@ember/object";
import Component from "@ember/component";
import DiscourseURL from "discourse/lib/url";
-export default Component.extend({
- tagName: "",
-
+@tagName("")
+export default class StaffActions extends Component {
@action
openLinks(event) {
const dataset = event.target.dataset;
@@ -20,5 +20,5 @@ export default Component.extend({
DiscourseURL.routeTo(`/t/${dataset.linkTopicId}`);
}
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/tags-uploader.js b/app/assets/javascripts/admin/addon/components/tags-uploader.js
index 39425b9b65..acc31e3506 100644
--- a/app/assets/javascripts/admin/addon/components/tags-uploader.js
+++ b/app/assets/javascripts/admin/addon/components/tags-uploader.js
@@ -1,24 +1,27 @@
+import { inject as service } from "@ember/service";
+import { alias } from "@ember/object/computed";
import Component from "@ember/component";
import I18n from "I18n";
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, {
- type: "csv",
- dialog: service(),
- uploadUrl: "/tags/upload",
- addDisabled: alias("uploading"),
- elementId: "tag-uploader",
- preventDirectS3Uploads: true,
+export default class TagsUploader extends Component.extend(UppyUploadMixin) {
+ @service dialog;
+ type = "csv";
+
+ uploadUrl = "/tags/upload";
+
+ @alias("uploading") addDisabled;
+
+ elementId = "tag-uploader";
+ preventDirectS3Uploads = true;
validateUploadedFilesOptions() {
return { csvOnly: true };
- },
+ }
uploadDone() {
this.closeModal();
this.refresh();
this.dialog.alert(I18n.t("tagging.upload_successful"));
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/themes-list-item.js b/app/assets/javascripts/admin/addon/components/themes-list-item.js
index 29158c4496..b059b96ea4 100644
--- a/app/assets/javascripts/admin/addon/components/themes-list-item.js
+++ b/app/assets/javascripts/admin/addon/components/themes-list-item.js
@@ -1,3 +1,4 @@
+import { classNameBindings, classNames } from "@ember-decorators/component";
import { and, gt } from "@ember/object/computed";
import discourseComputed from "discourse-common/utils/decorators";
import Component from "@ember/component";
@@ -7,19 +8,22 @@ import { action } from "@ember/object";
const MAX_COMPONENTS = 4;
-export default Component.extend({
- childrenExpanded: false,
- classNames: ["themes-list-item"],
- classNameBindings: ["theme.selected:selected"],
- hasComponents: gt("children.length", 0),
- displayComponents: and("hasComponents", "theme.isActive"),
- displayHasMore: gt("theme.childThemes.length", MAX_COMPONENTS),
+@classNames("themes-list-item")
+@classNameBindings("theme.selected:selected")
+export default class ThemesListItem extends Component {
+ childrenExpanded = false;
+
+ @gt("children.length", 0) hasComponents;
+
+ @and("hasComponents", "theme.isActive") displayComponents;
+
+ @gt("theme.childThemes.length", MAX_COMPONENTS) displayHasMore;
click(e) {
if (!e.target.classList.contains("others-count")) {
this.navigateToTheme();
}
- },
+ }
@discourseComputed(
"theme.component",
@@ -40,12 +44,12 @@ export default Component.extend({
const name = escape(t.name);
return t.enabled ? name : `${iconHTML("ban")} ${name}`;
});
- },
+ }
@discourseComputed("children")
childrenString(children) {
return children.join(", ");
- },
+ }
@discourseComputed(
"theme.childThemes.length",
@@ -58,11 +62,11 @@ export default Component.extend({
return 0;
}
return childrenCount - MAX_COMPONENTS;
- },
+ }
@action
toggleChildrenExpanded(event) {
event?.preventDefault();
this.toggleProperty("childrenExpanded");
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/themes-list.js b/app/assets/javascripts/admin/addon/components/themes-list.js
index ca1d872f46..e3ca02ef43 100644
--- a/app/assets/javascripts/admin/addon/components/themes-list.js
+++ b/app/assets/javascripts/admin/addon/components/themes-list.js
@@ -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 { COMPONENTS, THEMES } from "admin/models/theme";
import Component from "@ember/component";
import discourseComputed from "discourse-common/utils/decorators";
-import { inject as service } from "@ember/service";
import { action } from "@ember/object";
-export default Component.extend({
- router: service(),
- THEMES,
- COMPONENTS,
+@classNames("themes-list")
+export default class ThemesList extends Component {
+ @service router;
- classNames: ["themes-list"],
- filterTerm: null,
+ THEMES = THEMES;
+ COMPONENTS = COMPONENTS;
+ filterTerm = null;
- hasThemes: gt("themesList.length", 0),
- hasActiveThemes: gt("activeThemes.length", 0),
- hasInactiveThemes: gt("inactiveThemes.length", 0),
- showFilter: gte("themesList.length", 10),
+ @gt("themesList.length", 0) hasThemes;
- themesTabActive: equal("currentTab", THEMES),
- componentsTabActive: equal("currentTab", COMPONENTS),
+ @gt("activeThemes.length", 0) hasActiveThemes;
+
+ @gt("inactiveThemes.length", 0) hasInactiveThemes;
+
+ @gte("themesList.length", 10) showFilter;
+
+ @equal("currentTab", THEMES) themesTabActive;
+
+ @equal("currentTab", COMPONENTS) componentsTabActive;
@discourseComputed("themes", "components", "currentTab")
themesList(themes, components) {
@@ -28,7 +33,7 @@ export default Component.extend({
} else {
return components;
}
- },
+ }
@discourseComputed(
"themesList",
@@ -49,7 +54,7 @@ export default Component.extend({
);
}
return this._filterThemes(results, this.filterTerm);
- },
+ }
@discourseComputed(
"themesList",
@@ -78,7 +83,7 @@ export default Component.extend({
});
}
return this._filterThemes(results, this.filterTerm);
- },
+ }
_filterThemes(themes, term) {
term = term?.trim()?.toLowerCase();
@@ -86,7 +91,7 @@ export default Component.extend({
return themes;
}
return themes.filter(({ name }) => name.toLowerCase().includes(term));
- },
+ }
@action
changeView(newTab) {
@@ -96,10 +101,10 @@ export default Component.extend({
this.set("filterTerm", null);
}
}
- },
+ }
@action
navigateToTheme(theme) {
this.router.transitionTo("adminCustomizeThemes.show", theme);
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/value-list.js b/app/assets/javascripts/admin/addon/components/value-list.js
index 65b47c5058..f6621335cc 100644
--- a/app/assets/javascripts/admin/addon/components/value-list.js
+++ b/app/assets/javascripts/admin/addon/components/value-list.js
@@ -1,17 +1,21 @@
-import discourseComputed, { on } from "discourse-common/utils/decorators";
+import { action } from "@ember/object";
+import { classNameBindings } from "@ember-decorators/component";
import { empty, reads } from "@ember/object/computed";
+import discourseComputed, { on } from "discourse-common/utils/decorators";
import Component from "@ember/component";
import { makeArray } from "discourse-common/lib/helpers";
-export default Component.extend({
- classNameBindings: [":value-list"],
- inputInvalid: empty("newValue"),
- inputDelimiter: null,
- inputType: null,
- newValue: "",
- collection: null,
- values: null,
- noneKey: reads("addKey"),
+@classNameBindings(":value-list")
+export default class ValueList extends Component {
+ @empty("newValue") inputInvalid;
+
+ inputDelimiter = null;
+ inputType = null;
+ newValue = "";
+ collection = null;
+ values = null;
+
+ @reads("addKey") noneKey;
@on("didReceiveAttrs")
_setupCollection() {
@@ -25,57 +29,60 @@ export default Component.extend({
"collection",
this._splitValues(values, this.inputDelimiter || "\n")
);
- },
+ }
@discourseComputed("choices.[]", "collection.[]")
filteredChoices(choices, collection) {
return makeArray(choices).filter((i) => !collection.includes(i));
- },
+ }
keyDown(event) {
if (event.key === "Enter") {
this.send("addValue", this.newValue);
}
- },
+ }
- actions: {
- changeValue(index, event) {
- this._replaceValue(index, event.target.value);
- },
+ @action
+ changeValue(index, event) {
+ this._replaceValue(index, event.target.value);
+ }
- addValue(newValue) {
- if (this.inputInvalid) {
- return;
- }
+ @action
+ addValue(newValue) {
+ if (this.inputInvalid) {
+ return;
+ }
- this.set("newValue", null);
- this._addValue(newValue);
- },
+ this.set("newValue", null);
+ this._addValue(newValue);
+ }
- removeValue(value) {
- this._removeValue(value);
- },
+ @action
+ removeValue(value) {
+ this._removeValue(value);
+ }
- selectChoice(choice) {
- this._addValue(choice);
- },
+ @action
+ selectChoice(choice) {
+ this._addValue(choice);
+ }
- shift(operation, index) {
- let futureIndex = index + operation;
+ @action
+ shift(operation, index) {
+ let futureIndex = index + operation;
- if (futureIndex > this.collection.length - 1) {
- futureIndex = 0;
- } else if (futureIndex < 0) {
- futureIndex = this.collection.length - 1;
- }
+ if (futureIndex > this.collection.length - 1) {
+ futureIndex = 0;
+ } else if (futureIndex < 0) {
+ futureIndex = this.collection.length - 1;
+ }
- const shiftedValue = this.collection[index];
- this.collection.removeAt(index);
- this.collection.insertAt(futureIndex, shiftedValue);
+ const shiftedValue = this.collection[index];
+ this.collection.removeAt(index);
+ this.collection.insertAt(futureIndex, shiftedValue);
- this._saveValues();
- },
- },
+ this._saveValues();
+ }
_addValue(value) {
this.collection.addObject(value);
@@ -87,7 +94,7 @@ export default Component.extend({
}
this._saveValues();
- },
+ }
_removeValue(value) {
this.collection.removeObject(value);
@@ -99,12 +106,12 @@ export default Component.extend({
}
this._saveValues();
- },
+ }
_replaceValue(index, newValue) {
this.collection.replace(index, 1, [newValue]);
this._saveValues();
- },
+ }
_saveValues() {
if (this.inputType === "array") {
@@ -113,12 +120,12 @@ export default Component.extend({
}
this.set("values", this.collection.join(this.inputDelimiter || "\n"));
- },
+ }
@discourseComputed("collection")
showUpDownButtons(collection) {
return collection.length - 1 ? true : false;
- },
+ }
_splitValues(values, delimiter) {
if (values && values.length) {
@@ -126,5 +133,5 @@ export default Component.extend({
} else {
return [];
}
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/addon/components/version-checks.js b/app/assets/javascripts/admin/addon/components/version-checks.js
index 87d5ddb040..b06deba9d5 100644
--- a/app/assets/javascripts/admin/addon/components/version-checks.js
+++ b/app/assets/javascripts/admin/addon/components/version-checks.js
@@ -1,3 +1,3 @@
import Component from "@ember/component";
-export default Component.extend({});
+export default class VersionChecks extends Component {}
diff --git a/app/assets/javascripts/admin/addon/components/watched-word-uploader.js b/app/assets/javascripts/admin/addon/components/watched-word-uploader.js
index 27c43ad576..3c29a88cf7 100644
--- a/app/assets/javascripts/admin/addon/components/watched-word-uploader.js
+++ b/app/assets/javascripts/admin/addon/components/watched-word-uploader.js
@@ -1,28 +1,33 @@
+import { classNames } from "@ember-decorators/component";
+import { alias } from "@ember/object/computed";
import Component from "@ember/component";
import I18n from "I18n";
import UppyUploadMixin from "discourse/mixins/uppy-upload";
-import { alias } from "@ember/object/computed";
import { dialog } from "discourse/lib/uploads";
-export default Component.extend(UppyUploadMixin, {
- type: "txt",
- classNames: "watched-words-uploader",
- uploadUrl: "/admin/customize/watched_words/upload",
- addDisabled: alias("uploading"),
- preventDirectS3Uploads: true,
+@classNames("watched-words-uploader")
+export default class WatchedWordUploader extends Component.extend(
+ UppyUploadMixin
+) {
+ type = "txt";
+ uploadUrl = "/admin/customize/watched_words/upload";
+
+ @alias("uploading") addDisabled;
+
+ preventDirectS3Uploads = true;
validateUploadedFilesOptions() {
return { skipValidation: true };
- },
+ }
_perFileData() {
return { action_key: this.actionKey };
- },
+ }
uploadDone() {
if (this) {
dialog.alert(I18n.t("admin.watched_words.form.upload_successful"));
this.done();
}
- },
-});
+ }
+}
diff --git a/app/assets/javascripts/admin/codemods.log b/app/assets/javascripts/admin/codemods.log
new file mode 100644
index 0000000000..c9f534b3f5
--- /dev/null
+++ b/app/assets/javascripts/admin/codemods.log
@@ -0,0 +1,85 @@
+2023-02-20T18:38:30.812Z [info] [./addon/components/admin-report-table.js]: SUCCESS
+2023-02-20T18:38:31.070Z [info] [./addon/components/site-customization-change-details.js]: SUCCESS
+2023-02-20T18:38:30.860Z [warn] [./addon/components/admin-user-field-item.js]: SKIPPED: Did not find any 'EmberObject.extend()' expressions
+2023-02-20T18:38:30.874Z [info] [./addon/components/admin-wrapper.js]: SUCCESS
+2023-02-20T18:38:30.983Z [error] [./addon/components/admin-theme-editor.js]: FAILURE
+Validation errors for class 'AdminThemeEditor':
+ [activeSection]: Transform not supported - value is of type object. For more details: eslint-plugin-ember/avoid-leaking-state-in-ember-objects
+2023-02-20T18:38:30.996Z [info] [./addon/components/cancel-link.js]: SUCCESS
+2023-02-20T18:38:31.058Z [info] [./addon/components/color-input.js]: SUCCESS
+2023-02-20T18:38:31.080Z [info] [./addon/components/admin-watched-word.js]: SUCCESS
+2023-02-20T18:38:31.093Z [info] [./addon/components/themes-list.js]: SUCCESS
+2023-02-20T18:38:31.114Z [info] [./addon/components/install-theme-item.js]: SUCCESS
+2023-02-20T18:38:31.149Z [info] [./addon/components/dashboard-new-features.js]: SUCCESS
+2023-02-20T18:38:31.132Z [info] [./addon/components/site-text-summary.js]: SUCCESS
+2023-02-20T18:38:31.157Z [info] [./addon/components/site-setting.js]: SUCCESS
+2023-02-20T18:38:31.165Z [info] [./addon/components/site-customization-change-field.js]: SUCCESS
+2023-02-20T18:38:31.182Z [warn] [./addon/components/theme-setting-editor.js]: SKIPPED: Did not find any 'EmberObject.extend()' expressions
+2023-02-20T18:38:31.218Z [info] [./addon/components/staff-actions.js]: SUCCESS
+2023-02-20T18:38:31.231Z [info] [./addon/components/tags-uploader.js]: SUCCESS
+2023-02-20T18:38:31.105Z [info] [./addon/components/dashboard-new-feature-item.js]: SUCCESS
+2023-02-20T18:38:31.111Z [info] [./addon/components/admin-report-trust-level-counts.js]: SUCCESS
+2023-02-20T18:38:31.225Z [info] [./addon/components/admin-report.js]: SUCCESS
+2023-02-20T18:38:31.240Z [info] [./addon/components/admin-editable-field.js]: SUCCESS
+2023-02-20T18:38:31.278Z [info] [./addon/components/admin-report-counters.js]: SUCCESS
+2023-02-20T18:38:31.151Z [info] [./addon/components/version-checks.js]: SUCCESS
+2023-02-20T18:38:31.201Z [info] [./addon/components/value-list.js]: SUCCESS
+2023-02-20T18:38:31.247Z [info] [./addon/components/watched-word-uploader.js]: SUCCESS
+2023-02-20T18:38:31.269Z [error] [./addon/components/watched-word-form.js]: FAILURE
+Validation errors for class 'WatchedWordForm':
+ [actions]: Transform not supported - [submit]: action name matches one of the lifecycle hooks. Rename and try again. See https://github.com/scalvert/ember-native-class-codemod/issues/34 for more details
+2023-02-20T18:38:31.283Z [warn] [./addon/components/webhook-event.js]: SKIPPED
+Could not find runtime data NO_RUNTIME_DATA
+2023-02-20T18:38:31.242Z [warn] [./addon/components/theme-translation.js]: SKIPPED: Did not find any 'EmberObject.extend()' expressions
+2023-02-20T18:38:31.259Z [warn] [./addon/components/theme-setting-relatives-selector.js]: SKIPPED: Did not find any 'EmberObject.extend()' expressions
+2023-02-20T18:38:31.287Z [info] [./addon/components/themes-list-item.js]: SUCCESS
+2023-02-20T18:38:31.163Z [info] [./addon/components/dashboard-problems.js]: SUCCESS
+2023-02-20T18:38:31.242Z [info] [./addon/components/emoji-value-list.js]: SUCCESS
+2023-02-20T18:38:31.261Z [info] [./addon/components/flag-user-lists.js]: SUCCESS
+2023-02-20T18:38:31.271Z [info] [./addon/components/flag-user.js]: SUCCESS
+2023-02-20T18:38:31.289Z [info] [./addon/components/highlighted-code.js]: SUCCESS
+2023-02-20T18:38:31.306Z [info] [./addon/components/inline-edit-checkbox.js]: SUCCESS
+2023-02-20T18:38:31.298Z [warn] [./addon/components/webhook-status.js]: SKIPPED
+Could not find runtime data NO_RUNTIME_DATA
+2023-02-20T18:38:31.327Z [warn] [./addon/components/webhook-event-chooser.js]: SKIPPED
+Could not find runtime data NO_RUNTIME_DATA
+2023-02-20T18:38:31.337Z [warn] [./addon/components/webhook-events.js]: SKIPPED
+Could not find runtime data NO_RUNTIME_DATA
+2023-02-20T18:38:31.333Z [error] [./addon/components/email-styles-editor.js]: FAILURE
+Validation errors for class 'EmailStylesEditor':
+ [editorContents]: Transform not supported - value is of type object. For more details: eslint-plugin-ember/avoid-leaking-state-in-ember-objects
+2023-02-20T18:38:31.367Z [warn] [./addon/components/embeddable-host.js]: SKIPPED: Did not find any 'EmberObject.extend()' expressions
+2023-02-20T18:38:31.374Z [error] [./addon/components/embedding-setting.js]: FAILURE
+Validation errors for class 'EmbeddingSetting':
+ [checked]: Transform not supported - value is of type object. For more details: eslint-plugin-ember/avoid-leaking-state-in-ember-objects
+2023-02-20T18:38:31.189Z [info] [./addon/components/ip-lookup.js]: SUCCESS
+2023-02-20T18:38:31.227Z [info] [./addon/components/permalink-form.js]: SUCCESS
+2023-02-20T18:38:31.239Z [info] [./addon/components/moderation-history-item.js]: SUCCESS
+2023-02-20T18:38:31.251Z [info] [./addon/components/resumable-upload.js]: SUCCESS
+2023-02-20T18:38:31.310Z [info] [./addon/components/secret-value-list.js]: SUCCESS
+2023-02-20T18:38:31.333Z [info] [./addon/components/setting-validation-message.js]: SUCCESS
+2023-02-20T18:38:31.354Z [info] [./addon/components/silence-details.js]: SUCCESS
+2023-02-20T18:38:31.381Z [info] [./addon/components/simple-list.js]: SUCCESS
+2023-02-20T18:38:31.397Z [error] [./addon/components/screened-ip-address-form.js]: FAILURE
+Validation errors for class 'ScreenedIpAddressForm':
+ [actions]: Transform not supported - [submit]: action name matches one of the lifecycle hooks. Rename and try again. See https://github.com/scalvert/ember-native-class-codemod/issues/34 for more details
+2023-02-20T18:38:31.266Z [info] [./addon/components/admin-form-row.js]: SUCCESS
+2023-02-20T18:38:31.273Z [info] [./addon/components/admin-nav.js]: SUCCESS
+2023-02-20T18:38:31.316Z [info] [./addon/components/admin-backups-logs.js]: SUCCESS
+2023-02-20T18:38:31.388Z [info] [./addon/components/ace-editor.js]: SUCCESS
+2023-02-20T18:38:31.414Z [info] [./addon/components/admin-graph.js]: SUCCESS
+2023-02-20T18:38:31.424Z [info] [./addon/components/admin-penalty-history.js]: SUCCESS
+2023-02-20T18:38:31.435Z [info] [./addon/components/admin-penalty-similar-users.js]: SUCCESS
+2023-02-20T18:38:31.449Z [error] [./addon/components/admin-penalty-reason.js]: FAILURE
+Validation errors for class 'AdminPenaltyReason':
+ [reasonKeys]: Transform not supported - value is of type object. For more details: eslint-plugin-ember/avoid-leaking-state-in-ember-objects
+2023-02-20T18:38:31.460Z [info] [./addon/components/admin-penalty-post-action.js]: SUCCESS
+2023-02-20T18:38:31.370Z [info] [./addon/components/admin-report-chart.js]: SUCCESS
+2023-02-20T18:38:31.394Z [info] [./addon/components/admin-report-counts.js]: SUCCESS
+2023-02-20T18:38:31.403Z [info] [./addon/components/admin-report-inline-table.js]: SUCCESS
+2023-02-20T18:38:31.413Z [info] [./addon/components/admin-report-table-cell.js]: SUCCESS
+2023-02-20T18:38:31.438Z [info] [./addon/components/admin-report-stacked-chart.js]: SUCCESS
+2023-02-20T18:38:31.452Z [info] [./addon/components/admin-report-storage-stats.js]: SUCCESS
+2023-02-20T18:38:31.460Z [info] [./addon/components/admin-report-per-day-counts.js]: SUCCESS
+2023-02-20T18:38:31.469Z [info] [./addon/components/admin-report-table-header.js]: SUCCESS
+2023-02-20T18:38:31.475Z [info] [./addon/components/admin-report-table-row.js]: SUCCESS
diff --git a/app/assets/javascripts/discourse/package.json b/app/assets/javascripts/discourse/package.json
index c51dec198d..37b59cca9a 100644
--- a/app/assets/javascripts/discourse/package.json
+++ b/app/assets/javascripts/discourse/package.json
@@ -20,6 +20,7 @@
"@babel/standalone": "^7.20.15",
"@discourse/backburner.js": "^2.7.1-0",
"@discourse/itsatrap": "^2.0.10",
+ "@discourse/virtual-dom": "^2.1.2-0",
"@ember-compat/tracked-built-ins": "^0.9.1",
"@ember/jquery": "^2.0.0",
"@ember/optional-features": "^2.0.0",
@@ -63,6 +64,7 @@
"ember-cli-progress-ci": "1.0.0",
"ember-cli-sri": "^2.1.1",
"ember-cli-terser": "^4.0.2",
+ "ember-decorators": "^6.1.1",
"ember-exam": "^8.0.0",
"ember-export-application-global": "^2.0.1",
"ember-load-initializers": "^2.1.1",
@@ -94,7 +96,6 @@
"terser": "^5.16.4",
"tippy.js": "^6.3.7",
"util": "^0.12.5",
- "@discourse/virtual-dom": "^2.1.2-0",
"webpack": "^5.75.0",
"wizard": "1.0.0",
"xss": "^1.0.14"
diff --git a/app/assets/javascripts/yarn.lock b/app/assets/javascripts/yarn.lock
index a44ef99c6c..5be8f60987 100644
--- a/app/assets/javascripts/yarn.lock
+++ b/app/assets/javascripts/yarn.lock
@@ -1040,6 +1040,29 @@
resolved "https://registry.yarnpkg.com/@ember-data/rfc395-data/-/rfc395-data-0.0.4.tgz#ecb86efdf5d7733a76ff14ea651a1b0ed1f8a843"
integrity sha512-tGRdvgC9/QMQSuSuJV45xoyhI0Pzjm7A9o/MVVA3HakXIImJbbzx/k/6dO9CUEQXIyS2y0fW6C1XaYOG7rY0FQ==
+"@ember-decorators/component@^6.1.1":
+ version "6.1.1"
+ resolved "https://registry.yarnpkg.com/@ember-decorators/component/-/component-6.1.1.tgz#b360dc4fa8e576ee1c840879399ef1745fd96e06"
+ integrity sha512-Cj8tY/c0MC/rsipqsiWLh3YVN72DK92edPYamD/HzvftwzC6oDwawWk8RmStiBnG9PG/vntAt41l3S7HSSA+1Q==
+ dependencies:
+ "@ember-decorators/utils" "^6.1.1"
+ ember-cli-babel "^7.1.3"
+
+"@ember-decorators/object@^6.1.1":
+ version "6.1.1"
+ resolved "https://registry.yarnpkg.com/@ember-decorators/object/-/object-6.1.1.tgz#50c922f5ac9af3ddd381cb6a43a031dfd9a70c7a"
+ integrity sha512-cb4CNR9sRoA31J3FCOFLDuR9ztM4wO9w1WlS4JeNRS7Z69SlB/XSXB/vplA3i9OOaXEy/zKWbu5ndZrHz0gvLw==
+ dependencies:
+ "@ember-decorators/utils" "^6.1.1"
+ ember-cli-babel "^7.1.3"
+
+"@ember-decorators/utils@^6.1.1":
+ version "6.1.1"
+ resolved "https://registry.yarnpkg.com/@ember-decorators/utils/-/utils-6.1.1.tgz#6b619814942b4fb3747cfa9f540c9f05283d7c5e"
+ integrity sha512-0KqnoeoLKb6AyoSU65TRF5T85wmS4uDn06oARddwNPxxf/lt5jQlh41uX3W7V/fWL9tPu8x1L1Vvpc80MN1+YA==
+ dependencies:
+ ember-cli-babel "^7.1.3"
+
"@ember/edition-utils@^1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@ember/edition-utils/-/edition-utils-1.2.0.tgz#a039f542dc14c8e8299c81cd5abba95e2459cfa6"
@@ -3761,7 +3784,7 @@ ember-cli-babel-plugin-helpers@^1.0.0, ember-cli-babel-plugin-helpers@^1.1.1:
resolved "https://registry.yarnpkg.com/ember-cli-babel-plugin-helpers/-/ember-cli-babel-plugin-helpers-1.1.1.tgz#5016b80cdef37036c4282eef2d863e1d73576879"
integrity sha512-sKvOiPNHr5F/60NLd7SFzMpYPte/nnGkq/tMIfXejfKHIhaiIkYFqX8Z9UFTKWLLn+V7NOaby6niNPZUdvKCRw==
-ember-cli-babel@^7.10.0, ember-cli-babel@^7.13.0, ember-cli-babel@^7.13.2, ember-cli-babel@^7.21.0, ember-cli-babel@^7.22.1, ember-cli-babel@^7.23.0, ember-cli-babel@^7.23.1, ember-cli-babel@^7.26.10, ember-cli-babel@^7.26.11, ember-cli-babel@^7.26.3, ember-cli-babel@^7.26.4, ember-cli-babel@^7.26.6, ember-cli-babel@^7.7.3:
+ember-cli-babel@^7.1.3, ember-cli-babel@^7.10.0, ember-cli-babel@^7.13.0, ember-cli-babel@^7.13.2, ember-cli-babel@^7.21.0, ember-cli-babel@^7.22.1, ember-cli-babel@^7.23.0, ember-cli-babel@^7.23.1, ember-cli-babel@^7.26.10, ember-cli-babel@^7.26.11, ember-cli-babel@^7.26.3, ember-cli-babel@^7.26.4, ember-cli-babel@^7.26.6, ember-cli-babel@^7.7.3:
version "7.26.11"
resolved "https://registry.yarnpkg.com/ember-cli-babel/-/ember-cli-babel-7.26.11.tgz#50da0fe4dcd99aada499843940fec75076249a9f"
integrity sha512-JJYeYjiz/JTn34q7F5DSOjkkZqy8qwFOOxXfE6pe9yEJqWGu4qErKxlz8I22JoVEQ/aBUO+OcKTpmctvykM9YA==
@@ -4124,6 +4147,15 @@ ember-compatibility-helpers@^1.1.2, ember-compatibility-helpers@^1.2.0, ember-co
fs-extra "^9.1.0"
semver "^5.4.1"
+ember-decorators@^6.1.1:
+ version "6.1.1"
+ resolved "https://registry.yarnpkg.com/ember-decorators/-/ember-decorators-6.1.1.tgz#6d770f8999cf5a413a1ee459afd520838c0fc470"
+ integrity sha512-63vZPntPn1aqMyeNRLoYjJD+8A8obd+c2iZkJflswpDRNVIsp2m7aQdSCtPt4G0U/TEq2251g+N10maHX3rnJQ==
+ dependencies:
+ "@ember-decorators/component" "^6.1.1"
+ "@ember-decorators/object" "^6.1.1"
+ ember-cli-babel "^7.7.3"
+
ember-destroyable-polyfill@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/ember-destroyable-polyfill/-/ember-destroyable-polyfill-2.0.3.tgz#1673ed66609a82268ef270a7d917ebd3647f11e1"