diff --git a/app/assets/javascripts/admin/addon/components/ace-editor.js b/app/assets/javascripts/admin/addon/components/ace-editor.js index 06ed3763031..bc324978333 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 c707c99b70a..424979543e2 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,26 @@ +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"), - - init() { - this._super(...arguments); - this._reset(); - }, +@classNames("admin-backups-logs") +export default class AdminBackupsLogs extends Component { + showLoadingSpinner = false; + hasFormattedLogs = false; + noLogsMessage = I18n.t("admin.backups.logs.none"); + formattedLogs = ""; + index = 0; _reset() { this.setProperties({ formattedLogs: "", index: 0 }); - }, + } _scrollDown() { const div = this.element; div.scrollTop = div.scrollHeight; - }, + } @on("init") @observes("logs.[]") @@ -31,7 +29,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 +53,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 +74,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 892a3208e86..a99265b20cb 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,22 @@ +import { tagName } from "@ember-decorators/component"; import Component from "@ember/component"; import { action } from "@ember/object"; -export default Component.extend({ - tagName: "", - - buffer: "", - editing: false, - - init() { - this._super(...arguments); - this.set("editing", false); - }, +@tagName("") +export default class AdminEditableField extends Component { + buffer = ""; + 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 6217c6b913f..266301263d4 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,5 @@ +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 1107abeb2ca..4ef05fca32e 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 0e6d50b17d4..2542a2238ba 100644 --- a/app/assets/javascripts/admin/addon/components/admin-nav.js +++ b/app/assets/javascripts/admin/addon/components/admin-nav.js @@ -1,4 +1,5 @@ +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 32c288b248d..0931ac8e4a4 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 eb201ae0899..08314925460 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-reason.js b/app/assets/javascripts/admin/addon/components/admin-penalty-reason.js index ca6164e7630..e8d037d249b 100644 --- a/app/assets/javascripts/admin/addon/components/admin-penalty-reason.js +++ b/app/assets/javascripts/admin/addon/components/admin-penalty-reason.js @@ -1,43 +1,46 @@ +import { tagName } from "@ember-decorators/component"; +import { equal } from "@ember/object/computed"; import Component from "@ember/component"; import { action } from "@ember/object"; -import { equal } from "@ember/object/computed"; import discourseComputed from "discourse-common/utils/decorators"; import I18n from "I18n"; const CUSTOM_REASON_KEY = "custom"; -export default Component.extend({ - tagName: "", - selectedReason: CUSTOM_REASON_KEY, - customReason: "", - reasonKeys: [ +@tagName("") +export default class AdminPenaltyReason extends Component { + selectedReason = CUSTOM_REASON_KEY; + customReason = ""; + + reasonKeys = [ "not_listening_to_staff", "consuming_staff_time", "combative", "in_wrong_place", "no_constructive_purpose", CUSTOM_REASON_KEY, - ], - isCustomReason: equal("selectedReason", CUSTOM_REASON_KEY), + ]; + + @equal("selectedReason", CUSTOM_REASON_KEY) isCustomReason; @discourseComputed("reasonKeys") reasons(keys) { return keys.map((key) => { return { id: key, name: I18n.t(`admin.user.suspend_reasons.${key}`) }; }); - }, + } @action setSelectedReason(value) { this.set("selectedReason", value); this.setReason(); - }, + } @action setCustomReason(value) { this.set("customReason", value); this.setReason(); - }, + } setReason() { if (this.isCustomReason) { @@ -48,5 +51,5 @@ export default Component.extend({ I18n.t(`admin.user.suspend_reasons.${this.selectedReason}`) ); } - }, -}); + } +} 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 241927a7b7f..52996d458f3 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 1c4ad1caa3a..64f09aa0d7d 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 c956b93e359..6e3dab52366 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,6 @@ +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 03c690dbbd6..fd1b6cc68d6 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,12 @@ -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 753320cc31a..3e770da6467 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,5 @@ +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 7f039c061e1..ee48a5138f2 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,5 @@ +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 6b773957f66..b69e75141e8 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 e12bc6432f7..ee0d7d24764 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 838d8dbe1d4..89997c9afab 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,27 @@ -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 5c7cdf1e4ca..7de3ac97088 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 ff34cb94e8b..e5e275aa7ad 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,8 @@ +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 a237e93ee43..3638625f872 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 7f039c061e1..6da6a748934 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,5 @@ +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 9f60e09a257..fede9cc2d60 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,58 @@ 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; - init() { - this._super(...arguments); + @alias("model.dates_filtering") showDatesOptions; - this._reports = []; - }, + @or("showDatesOptions", "model.available_filters.length") showRefresh; - isHidden: computed("siteSettings.dashboard_hidden_reports", function () { + @and("showTrend", "model.prev_period") shouldDisplayTrend; + + endDate = null; + startDate = null; + + @or("showTimeoutError", "showExceptionError", "showNotFoundError") showError; + @equal("model.error", "not_found") showNotFoundError; + @equal("model.error", "timeout") showTimeoutError; + @equal("model.error", "exception") showExceptionError; + @notEmpty("model.data") hasData; + + _reports = []; + + @computed("siteSettings.dashboard_hidden_reports") + get isHidden() { return (this.siteSettings.dashboard_hidden_reports || "") .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 +96,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 +140,12 @@ export default Component.extend({ icon: mode === "table" ? "table" : "signal", }; }); - }, + } @discourseComputed("currentMode") modeComponent(currentMode) { return `admin-report-${currentMode.replace(/_/g, "-")}`; - }, + } @discourseComputed( "dataSourceName", @@ -178,7 +179,7 @@ export default Component.extend({ .join(":"); return reportKey; - }, + } @discourseComputed("options.chartGrouping", "model.chartData.length") chartGroupings(grouping, count) { @@ -192,7 +193,7 @@ export default Component.extend({ class: `chart-grouping ${grouping === id ? "active" : "inactive"}`, }; }); - }, + } @action onChangeDateRange(range) { @@ -200,7 +201,7 @@ export default Component.extend({ startDate: range.from, endDate: range.to, }); - }, + } @action applyFilter(id, value) { @@ -215,7 +216,7 @@ export default Component.extend({ this.send("refreshReport", { filters: customFilters, }); - }, + } @action refreshReport(options = {}) { @@ -238,7 +239,7 @@ export default Component.extend({ ? this.get("filters.customFilters") : options.filters, }); - }, + } @action exportCsv() { @@ -254,7 +255,7 @@ export default Component.extend({ } exportEntity("report", args).then(outputExportResult); - }, + } @action onChangeMode(mode) { @@ -263,7 +264,7 @@ export default Component.extend({ this.send("refreshReport", { chartGrouping: null, }); - }, + } _computeReport() { if (!this.element || this.isDestroying || this.isDestroyed) { @@ -306,7 +307,7 @@ export default Component.extend({ } this._renderReport(report, this.forcedModes, this.currentMode); - }, + } _renderReport(report, forcedModes, currentMode) { const modes = forcedModes ? forcedModes.split(",") : report.modes; @@ -317,11 +318,9 @@ export default Component.extend({ currentMode, options: this._buildOptions(currentMode, report), }); - }, + } _fetchReport() { - this._super(...arguments); - this.setProperties({ isLoading: true, rateLimitationString: null }); next(() => { @@ -349,7 +348,7 @@ export default Component.extend({ ReportLoader.enqueue(this.dataSourceName, payload.data, callback); }); - }, + } _buildPayload(facets) { let payload = { data: { facets } }; @@ -375,7 +374,7 @@ export default Component.extend({ } return payload; - }, + } _buildOptions(mode, report) { if (mode === "table") { @@ -393,7 +392,7 @@ export default Component.extend({ }) ); } - }, + } _loadReport(jsonReport) { Report.fillMissingDates(jsonReport, { filledField: "chartData" }); @@ -423,5 +422,5 @@ export default Component.extend({ } return Report.create(jsonReport); - }, -}); + } +} diff --git a/app/assets/javascripts/admin/addon/components/admin-theme-editor.js b/app/assets/javascripts/admin/addon/components/admin-theme-editor.js index de8f0635791..7d3389902c1 100644 --- a/app/assets/javascripts/admin/addon/components/admin-theme-editor.js +++ b/app/assets/javascripts/admin/addon/components/admin-theme-editor.js @@ -6,8 +6,10 @@ import { isDocumentRTL } from "discourse/lib/text-direction"; import { action } from "@ember/object"; import { next } from "@ember/runloop"; -export default Component.extend({ - warning: null, +export default class AdminThemeEditor extends Component { + warning = null; + + @fmt("fieldName", "currentTargetName", "%@|%@") editorId; @discourseComputed("theme.targets", "onlyOverridden", "showAdvanced") visibleTargets(targets, onlyOverridden, showAdvanced) { @@ -20,7 +22,7 @@ export default Component.extend({ } return target.edited; }); - }, + } @discourseComputed("currentTargetName", "onlyOverridden", "theme.fields") visibleFields(targetName, onlyOverridden, fields) { @@ -29,7 +31,7 @@ export default Component.extend({ fields = fields.filter((field) => field.edited); } return fields; - }, + } @discourseComputed("currentTargetName", "fieldName") activeSectionMode(targetName, fieldName) { @@ -43,7 +45,7 @@ export default Component.extend({ return "scss"; } return fieldName && fieldName.includes("scss") ? "scss" : "html"; - }, + } @discourseComputed("currentTargetName", "fieldName") placeholder(targetName, fieldName) { @@ -58,30 +60,27 @@ export default Component.extend({ }); } return ""; - }, + } @discourseComputed("fieldName", "currentTargetName", "theme") - activeSection: { - get(fieldName, target, model) { - return model.getField(target, fieldName); - }, - set(value, fieldName, target, model) { - model.setField(target, fieldName, value); - return value; - }, - }, + get activeSection() { + return this.model.getField(this.currentTargetName, this.fieldName); + } - editorId: fmt("fieldName", "currentTargetName", "%@|%@"), + set activeSection(value) { + this.theme.setField(this.fieldName, value); + return value; + } @discourseComputed("maximized") maximizeIcon(maximized) { return maximized ? "discourse-compress" : "discourse-expand"; - }, + } @discourseComputed("currentTargetName", "theme.targets") showAddField(currentTargetName, targets) { return targets.find((t) => t.name === currentTargetName).customNames; - }, + } @discourseComputed( "currentTargetName", @@ -90,52 +89,55 @@ export default Component.extend({ ) error(target, fieldName) { return this.theme.getError(target, fieldName); - }, + } @action toggleShowAdvanced(event) { event?.preventDefault(); this.toggleProperty("showAdvanced"); - }, + } @action toggleAddField(event) { event?.preventDefault(); this.toggleProperty("addingField"); - }, + } @action toggleMaximize(event) { event?.preventDefault(); this.toggleProperty("maximized"); next(() => this.appEvents.trigger("ace:resize")); - }, + } - actions: { - cancelAddField() { - this.set("addingField", false); - }, + @action + cancelAddField() { + this.set("addingField", false); + } - addField(name) { - if (!name) { - return; - } - name = name.replace(/[^a-zA-Z0-9-_/]/g, ""); - this.theme.setField(this.currentTargetName, name, ""); - this.setProperties({ newFieldName: "", addingField: false }); - this.fieldAdded(this.currentTargetName, name); - }, + @action + addField(name) { + if (!name) { + return; + } + name = name.replace(/[^a-zA-Z0-9-_/]/g, ""); + this.theme.setField(this.currentTargetName, name, ""); + this.setProperties({ newFieldName: "", addingField: false }); + this.fieldAdded(this.currentTargetName, name); + } - onlyOverriddenChanged(value) { - this.onlyOverriddenChanged(value); - }, + @action + onlyOverriddenChanged(value) { + this.onlyOverriddenChanged(value); + } - save() { - this.attrs.save(); - }, + @action + save() { + this.attrs.save(); + } - setWarning(message) { - this.set("warning", message); - }, - }, -}); + @action + setWarning(message) { + this.set("warning", message); + } +} 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 7de7e3d8ab5..d6bde8016d2 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 d6a3564d420..98d18997d4f 100644 --- a/app/assets/javascripts/admin/addon/components/admin-wrapper.js +++ b/app/assets/javascripts/admin/addon/components/admin-wrapper.js @@ -1,14 +1,15 @@ 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 0e6d50b17d4..aa5d4dda65c 100644 --- a/app/assets/javascripts/admin/addon/components/cancel-link.js +++ b/app/assets/javascripts/admin/addon/components/cancel-link.js @@ -1,4 +1,5 @@ +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 2974b43871a..662b6eb714b 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 87d5ddb040f..80e6cd8a167 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 6e8defb93c4..46b7559585b 100644 --- a/app/assets/javascripts/admin/addon/components/dashboard-new-features.js +++ b/app/assets/javascripts/admin/addon/components/dashboard-new-features.js @@ -1,18 +1,19 @@ +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); + constructor() { + super(...arguments); ajax("/admin/dashboard/new-features.json").then((json) => { - if (!this.element || this.isDestroying || this.isDestroyed) { + if (this.isDestroying || this.isDestroyed) { return; } @@ -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 87d5ddb040f..c4df8401e0f 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/email-styles-editor.js b/app/assets/javascripts/admin/addon/components/email-styles-editor.js index 48621b41cf3..a3d2fe55941 100644 --- a/app/assets/javascripts/admin/addon/components/email-styles-editor.js +++ b/app/assets/javascripts/admin/addon/components/email-styles-editor.js @@ -1,17 +1,19 @@ +import { action, computed } from "@ember/object"; +import { inject as service } from "@ember/service"; +import { reads } from "@ember/object/computed"; import Component from "@ember/component"; import I18n from "I18n"; import discourseComputed from "discourse-common/utils/decorators"; -import { reads } from "@ember/object/computed"; -import { inject as service } from "@ember/service"; -export default Component.extend({ - dialog: service(), - editorId: reads("fieldName"), +export default class EmailStylesEditor extends Component { + @service dialog; + + @reads("fieldName") editorId; @discourseComputed("fieldName") currentEditorMode(fieldName) { return fieldName === "css" ? "scss" : fieldName; - }, + } @discourseComputed("fieldName", "styles.html", "styles.css") resetDisabled(fieldName) { @@ -19,36 +21,36 @@ export default Component.extend({ this.get(`styles.${fieldName}`) === this.get(`styles.default_${fieldName}`) ); - }, + } - @discourseComputed("styles", "fieldName") - editorContents: { - get(styles, fieldName) { - return styles[fieldName]; - }, - set(value, styles, fieldName) { - styles.setField(fieldName, value); - return value; - }, - }, + @computed("styles", "fieldName") + get editorContents() { + return this.styles[this.fieldName]; + } - actions: { - reset() { - this.dialog.yesNoConfirm({ - message: I18n.t("admin.customize.email_style.reset_confirm", { - fieldName: I18n.t(`admin.customize.email_style.${this.fieldName}`), - }), - didConfirm: () => { - this.styles.setField( - this.fieldName, - this.styles.get(`default_${this.fieldName}`) - ); - this.notifyPropertyChange("editorContents"); - }, - }); - }, - save() { - this.attrs.save(); - }, - }, -}); + set editorContents(value) { + this.styles.setField(this.fieldName, value); + return value; + } + + @action + reset() { + this.dialog.yesNoConfirm({ + message: I18n.t("admin.customize.email_style.reset_confirm", { + fieldName: I18n.t(`admin.customize.email_style.${this.fieldName}`), + }), + didConfirm: () => { + this.styles.setField( + this.fieldName, + this.styles.get(`default_${this.fieldName}`) + ); + this.notifyPropertyChange("editorContents"); + }, + }); + } + + @action + save() { + this.attrs.save(); + } +} diff --git a/app/assets/javascripts/admin/addon/components/embeddable-host.js b/app/assets/javascripts/admin/addon/components/embeddable-host.js index 320b173bfb5..54e9d102a4a 100644 --- a/app/assets/javascripts/admin/addon/components/embeddable-host.js +++ b/app/assets/javascripts/admin/addon/components/embeddable-host.js @@ -1,85 +1,91 @@ +import { action } from "@ember/object"; +import { tagName } from "@ember-decorators/component"; +import { inject as service } from "@ember/service"; +import { or } from "@ember/object/computed"; import Category from "discourse/models/category"; import Component from "@ember/component"; import I18n from "I18n"; import { bufferedProperty } from "discourse/mixins/buffered-content"; import discourseComputed from "discourse-common/utils/decorators"; -import { inject as service } from "@ember/service"; import { isEmpty } from "@ember/utils"; -import { or } from "@ember/object/computed"; import { popupAjaxError } from "discourse/lib/ajax-error"; -export default Component.extend(bufferedProperty("host"), { - editToggled: false, - tagName: "tr", - categoryId: null, - category: null, - dialog: service(), +@tagName("tr") +export default class EmbeddableHost extends Component.extend( + bufferedProperty("host") +) { + @service dialog; + editToggled = false; + categoryId = null; + category = null; - editing: or("host.isNew", "editToggled"), + @or("host.isNew", "editToggled") editing; - init() { - this._super(...arguments); + constructor() { + super(...arguments); const host = this.host; const categoryId = host.category_id || this.site.uncategorized_category_id; const category = Category.findById(categoryId); host.set("category", category); - }, + } @discourseComputed("buffered.host", "host.isSaving") cantSave(host, isSaving) { return isSaving || isEmpty(host); - }, + } - actions: { - edit() { - this.set("categoryId", this.get("host.category.id")); - this.set("editToggled", true); - }, + @action + edit() { + this.set("categoryId", this.get("host.category.id")); + this.set("editToggled", true); + } - save() { - if (this.cantSave) { - return; - } + @action + save() { + if (this.cantSave) { + return; + } - const props = this.buffered.getProperties( - "host", - "allowed_paths", - "class_name" - ); - props.category_id = this.categoryId; + const props = this.buffered.getProperties( + "host", + "allowed_paths", + "class_name" + ); + props.category_id = this.categoryId; - const host = this.host; + const host = this.host; - host - .save(props) - .then(() => { - host.set("category", Category.findById(this.categoryId)); - this.set("editToggled", false); - }) - .catch(popupAjaxError); - }, - - delete() { - return this.dialog.confirm({ - message: I18n.t("admin.embedding.confirm_delete"), - didConfirm: () => { - return this.host.destroyRecord().then(() => { - this.deleteHost(this.host); - }); - }, - }); - }, - - cancel() { - const host = this.host; - if (host.get("isNew")) { - this.deleteHost(host); - } else { - this.rollbackBuffer(); + host + .save(props) + .then(() => { + host.set("category", Category.findById(this.categoryId)); this.set("editToggled", false); - } - }, - }, -}); + }) + .catch(popupAjaxError); + } + + @action + delete() { + return this.dialog.confirm({ + message: I18n.t("admin.embedding.confirm_delete"), + didConfirm: () => { + return this.host.destroyRecord().then(() => { + this.deleteHost(this.host); + }); + }, + }); + } + + @action + cancel() { + const host = this.host; + if (host.get("isNew")) { + this.deleteHost(host); + } else { + this.rollbackBuffer(); + this.set("editToggled", false); + } + } +} diff --git a/app/assets/javascripts/admin/addon/components/embedding-setting.js b/app/assets/javascripts/admin/addon/components/embedding-setting.js index f571d47cf61..ab6e91fa6a3 100644 --- a/app/assets/javascripts/admin/addon/components/embedding-setting.js +++ b/app/assets/javascripts/admin/addon/components/embedding-setting.js @@ -1,33 +1,33 @@ +import { classNames } from "@ember-decorators/component"; +import { computed } from "@ember/object"; import Component from "@ember/component"; import discourseComputed from "discourse-common/utils/decorators"; import { dasherize } from "@ember/string"; -export default Component.extend({ - classNames: ["embed-setting"], - +@classNames("embed-setting") +export default class EmbeddingSetting extends Component { @discourseComputed("field") inputId(field) { return dasherize(field); - }, + } @discourseComputed("field") translationKey(field) { return `admin.embedding.${field}`; - }, + } @discourseComputed("type") isCheckbox(type) { return type === "checkbox"; - }, + } - @discourseComputed("value") - checked: { - get(value) { - return !!value; - }, - set(value) { - this.set("value", value); - return value; - }, - }, -}); + @computed("value") + get checked() { + return !!this.value; + } + + set(value) { + this.set("value", value); + return value; + } +} 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 3f2810383d0..40363b874d8 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 8b886047689..0096ce0a575 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,5 @@ +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 87d5ddb040f..ef9b83f7803 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 21cfaf6b154..5f0331fac5c 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 cfbd2f82f98..8618e4044b4 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 b8d8823109d..459dc5dc673 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,5 @@ +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 02a52405645..42c5f128116 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, "