DEV: Convert core components to native class syntax (batch 2) (#28515)

Changes made using the ember-native-class-codemod, plus some manual tweaks
This commit is contained in:
David Taylor 2024-08-27 15:00:46 +01:00 committed by GitHub
parent 31c0a08f8a
commit 66b061a5a8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 367 additions and 369 deletions

View File

@ -1,4 +1,5 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { tagName } from "@ember-decorators/component";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
const LIST_TYPE = { const LIST_TYPE = {
@ -6,10 +7,10 @@ const LIST_TYPE = {
MUTED: "muted", MUTED: "muted",
}; };
export default Component.extend({ @tagName("")
tagName: "", export default class CategoryListItem extends Component {
category: null, category = null;
listType: LIST_TYPE.NORMAL, listType = LIST_TYPE.NORMAL;
@discourseComputed("category.isHidden", "category.hasMuted", "listType") @discourseComputed("category.isHidden", "category.hasMuted", "listType")
isHidden(isHiddenCategory, hasMuted, listType) { isHidden(isHiddenCategory, hasMuted, listType) {
@ -17,7 +18,7 @@ export default Component.extend({
(isHiddenCategory && listType === LIST_TYPE.NORMAL) || (isHiddenCategory && listType === LIST_TYPE.NORMAL) ||
(!hasMuted && listType === LIST_TYPE.MUTED) (!hasMuted && listType === LIST_TYPE.MUTED)
); );
}, }
@discourseComputed("category.isMuted", "listType") @discourseComputed("category.isMuted", "listType")
isMuted(isMutedCategory, listType) { isMuted(isMutedCategory, listType) {
@ -25,20 +26,20 @@ export default Component.extend({
(isMutedCategory && listType === LIST_TYPE.NORMAL) || (isMutedCategory && listType === LIST_TYPE.NORMAL) ||
(!isMutedCategory && listType === LIST_TYPE.MUTED) (!isMutedCategory && listType === LIST_TYPE.MUTED)
); );
}, }
@discourseComputed("topicTrackingState.messageCount") @discourseComputed("topicTrackingState.messageCount")
unreadTopicsCount() { unreadTopicsCount() {
return this.category.unreadTopicsCount; return this.category.unreadTopicsCount;
}, }
@discourseComputed("topicTrackingState.messageCount") @discourseComputed("topicTrackingState.messageCount")
newTopicsCount() { newTopicsCount() {
return this.category.newTopicsCount; return this.category.newTopicsCount;
}, }
@discourseComputed("category.path") @discourseComputed("category.path")
slugPath(categoryPath) { slugPath(categoryPath) {
return categoryPath.substring("/c/".length); return categoryPath.substring("/c/".length);
}, }
}); }

View File

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

View File

@ -1,43 +1,45 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { action } from "@ember/object"; import { action } from "@ember/object";
import { alias, equal } from "@ember/object/computed"; import { alias, equal } from "@ember/object/computed";
import { classNames } from "@ember-decorators/component";
import { observes } from "@ember-decorators/object";
import PermissionType from "discourse/models/permission-type"; import PermissionType from "discourse/models/permission-type";
import discourseComputed, { observes } from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import I18n from "discourse-i18n"; import I18n from "discourse-i18n";
const EVERYONE = "everyone"; const EVERYONE = "everyone";
export default Component.extend({ @classNames("permission-row", "row-body")
classNames: ["permission-row", "row-body"], export default class CategoryPermissionRow extends Component {
canCreate: equal("type", PermissionType.FULL), @equal("type", PermissionType.FULL) canCreate;
everyonePermissionType: alias("everyonePermission.permission_type"), @alias("everyonePermission.permission_type") everyonePermissionType;
@discourseComputed("type") @discourseComputed("type")
canReply(value) { canReply(value) {
return ( return (
value === PermissionType.CREATE_POST || value === PermissionType.FULL value === PermissionType.CREATE_POST || value === PermissionType.FULL
); );
}, }
@discourseComputed("type") @discourseComputed("type")
canReplyIcon() { canReplyIcon() {
return this.canReply ? "check-square" : "far-square"; return this.canReply ? "check-square" : "far-square";
}, }
@discourseComputed("type") @discourseComputed("type")
canCreateIcon() { canCreateIcon() {
return this.canCreate ? "check-square" : "far-square"; return this.canCreate ? "check-square" : "far-square";
}, }
@discourseComputed("type") @discourseComputed("type")
replyGranted() { replyGranted() {
return this.type <= PermissionType.CREATE_POST ? "reply-granted" : ""; return this.type <= PermissionType.CREATE_POST ? "reply-granted" : "";
}, }
@discourseComputed("type") @discourseComputed("type")
createGranted() { createGranted() {
return this.type === PermissionType.FULL ? "create-granted" : ""; return this.type === PermissionType.FULL ? "create-granted" : "";
}, }
@observes("everyonePermissionType") @observes("everyonePermissionType")
inheritFromEveryone() { inheritFromEveryone() {
@ -49,7 +51,7 @@ export default Component.extend({
if (this.everyonePermissionType < this.type) { if (this.everyonePermissionType < this.type) {
this.updatePermission(this.everyonePermissionType); this.updatePermission(this.everyonePermissionType);
} }
}, }
@discourseComputed("everyonePermissionType", "type") @discourseComputed("everyonePermissionType", "type")
replyDisabled(everyonePermissionType) { replyDisabled(everyonePermissionType) {
@ -61,14 +63,14 @@ export default Component.extend({
return true; return true;
} }
return false; return false;
}, }
@discourseComputed("replyDisabled") @discourseComputed("replyDisabled")
replyTooltip(replyDisabled) { replyTooltip(replyDisabled) {
return replyDisabled return replyDisabled
? I18n.t("category.permissions.inherited") ? I18n.t("category.permissions.inherited")
: I18n.t("category.permissions.toggle_reply"); : I18n.t("category.permissions.toggle_reply");
}, }
@discourseComputed("everyonePermissionType", "type") @discourseComputed("everyonePermissionType", "type")
createDisabled(everyonePermissionType) { createDisabled(everyonePermissionType) {
@ -80,47 +82,47 @@ export default Component.extend({
return true; return true;
} }
return false; return false;
}, }
@discourseComputed("createDisabled") @discourseComputed("createDisabled")
createTooltip(createDisabled) { createTooltip(createDisabled) {
return createDisabled return createDisabled
? I18n.t("category.permissions.inherited") ? I18n.t("category.permissions.inherited")
: I18n.t("category.permissions.toggle_full"); : I18n.t("category.permissions.toggle_full");
}, }
updatePermission(type) { updatePermission(type) {
this.category.updatePermission(this.group_name, type); this.category.updatePermission(this.group_name, type);
}, }
@action @action
removeRow(event) { removeRow(event) {
event?.preventDefault(); event?.preventDefault();
this.category.removePermission(this.group_name); this.category.removePermission(this.group_name);
}, }
actions: { @action
setPermissionReply() { setPermissionReply() {
if (this.type <= PermissionType.CREATE_POST) { if (this.type <= PermissionType.CREATE_POST) {
this.updatePermission(PermissionType.READONLY); this.updatePermission(PermissionType.READONLY);
} else { } else {
this.updatePermission(PermissionType.CREATE_POST); this.updatePermission(PermissionType.CREATE_POST);
} }
}, }
setPermissionFull() { @action
if ( setPermissionFull() {
this.group_name !== EVERYONE && if (
this.everyonePermissionType === PermissionType.FULL this.group_name !== EVERYONE &&
) { this.everyonePermissionType === PermissionType.FULL
return; ) {
} return;
}
if (this.type === PermissionType.FULL) { if (this.type === PermissionType.FULL) {
this.updatePermission(PermissionType.CREATE_POST); this.updatePermission(PermissionType.CREATE_POST);
} else { } else {
this.updatePermission(PermissionType.FULL); this.updatePermission(PermissionType.FULL);
} }
}, }
}, }
});

View File

@ -2,10 +2,11 @@ import Component from "@ember/component";
import { and } from "@ember/object/computed"; import { and } from "@ember/object/computed";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend({ export default class CategoryReadOnlyBanner extends Component {
@and("category.read_only_banner", "readOnly", "user") shouldShow;
@discourseComputed @discourseComputed
user() { user() {
return this.currentUser; return this.currentUser;
}, }
shouldShow: and("category.read_only_banner", "readOnly", "user"), }
});

View File

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

View File

@ -1,6 +1,8 @@
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({ import { tagName } from "@ember-decorators/component";
tagName: "h3",
// icon name defined here so it can be easily overridden in theme components @tagName("h3")
lockIcon: "lock", export default class CategoryTitleLink extends Component {}
});
// icon name defined on prototype so it can be easily overridden in theme components
CategoryTitleLink.prototype.lockIcon = "lock";

View File

@ -1,5 +1,6 @@
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({ import { classNames, tagName } from "@ember-decorators/component";
tagName: "span",
classNames: ["category__badges"], @tagName("span")
}); @classNames("category__badges")
export default class CategoryUnread extends Component {}

View File

@ -2,14 +2,15 @@ import Component from "@ember/component";
import { action, get } from "@ember/object"; import { action, get } from "@ember/object";
import { next } from "@ember/runloop"; import { next } from "@ember/runloop";
import { isEmpty } from "@ember/utils"; import { isEmpty } from "@ember/utils";
import { observes } from "@ember-decorators/object";
import $ from "jquery"; import $ from "jquery";
import { searchForTerm } from "discourse/lib/search"; import { searchForTerm } from "discourse/lib/search";
import { debounce, observes } from "discourse-common/utils/decorators"; import { debounce } from "discourse-common/utils/decorators";
export default Component.extend({ export default class ChooseMessage extends Component {
loading: null, loading = null;
noResults: null, noResults = null;
messages: null, messages = null;
@observes("messageTitle") @observes("messageTitle")
messageTitleChanged() { messageTitleChanged() {
@ -19,7 +20,7 @@ export default Component.extend({
selectedTopicId: null, selectedTopicId: null,
}); });
this.search(this.messageTitle); this.search(this.messageTitle);
}, }
@observes("messages") @observes("messages")
messagesChanged() { messagesChanged() {
@ -28,7 +29,7 @@ export default Component.extend({
this.set("noResults", messages.length === 0); this.set("noResults", messages.length === 0);
} }
this.set("loading", false); this.set("loading", false);
}, }
@debounce(300) @debounce(300)
search(title) { search(title) {
@ -53,7 +54,7 @@ export default Component.extend({
this.setProperties({ messages: null, loading: false }); this.setProperties({ messages: null, loading: false });
} }
}); });
}, }
@action @action
chooseMessage(message, event) { chooseMessage(message, event) {
@ -61,5 +62,5 @@ export default Component.extend({
const messageId = get(message, "id"); const messageId = get(message, "id");
this.set("selectedTopicId", messageId); this.set("selectedTopicId", messageId);
next(() => $(`#choose-message-${messageId}`).prop("checked", "true")); next(() => $(`#choose-message-${messageId}`).prop("checked", "true"));
}, }
}); }

View File

@ -1,30 +1,34 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { htmlSafe } from "@ember/template"; import { htmlSafe } from "@ember/template";
import {
attributeBindings,
classNameBindings,
tagName,
} from "@ember-decorators/component";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import I18n from "discourse-i18n"; import I18n from "discourse-i18n";
export default Component.extend({ @tagName("button")
tagName: "button", @attributeBindings("style", "title")
attributeBindings: ["style", "title"], @classNameBindings(":colorpicker", "isUsed:used-color:unused-color")
classNameBindings: [":colorpicker", "isUsed:used-color:unused-color"], export default class ColorPickerChoice extends Component {
@discourseComputed("color", "usedColors") @discourseComputed("color", "usedColors")
isUsed(color, usedColors) { isUsed(color, usedColors) {
return (usedColors || []).includes(color.toUpperCase()); return (usedColors || []).includes(color.toUpperCase());
}, }
@discourseComputed("isUsed") @discourseComputed("isUsed")
title(isUsed) { title(isUsed) {
return isUsed ? I18n.t("category.already_used") : null; return isUsed ? I18n.t("category.already_used") : null;
}, }
@discourseComputed("color") @discourseComputed("color")
style(color) { style(color) {
return htmlSafe(`background-color: #${color};`); return htmlSafe(`background-color: #${color};`);
}, }
click(e) { click(e) {
e.preventDefault(); e.preventDefault();
this.selectColor(this.color); this.selectColor(this.color);
}, }
}); }

View File

@ -1,10 +1,11 @@
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({ import { action } from "@ember/object";
classNames: "colors-container", import { classNames } from "@ember-decorators/component";
actions: { @classNames("colors-container")
selectColor(color) { export default class ColorPicker extends Component {
this.set("value", color); @action
}, selectColor(color) {
}, this.set("value", color);
}); }
}

View File

@ -1,6 +1,7 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { alias } from "@ember/object/computed"; import { alias } from "@ember/object/computed";
import { htmlSafe } from "@ember/template"; import { htmlSafe } from "@ember/template";
import { classNames } from "@ember-decorators/component";
import { import {
CREATE_SHARED_DRAFT, CREATE_SHARED_DRAFT,
CREATE_TOPIC, CREATE_TOPIC,
@ -21,10 +22,10 @@ const TITLES = {
[EDIT_SHARED_DRAFT]: "composer.edit_shared_draft", [EDIT_SHARED_DRAFT]: "composer.edit_shared_draft",
}; };
export default Component.extend({ @classNames("composer-action-title")
classNames: ["composer-action-title"], export default class ComposerActionTitle extends Component {
options: alias("model.replyOptions"), @alias("model.replyOptions") options;
action: alias("model.action"), @alias("model.action") action;
// Note we update when some other attributes like tag/category change to allow // Note we update when some other attributes like tag/category change to allow
// text customizations to use those. // text customizations to use those.
@ -57,7 +58,7 @@ export default Component.extend({
); );
} }
} }
}, }
_formatEditUserPost(userAvatar, userLink, postLink, originalUser) { _formatEditUserPost(userAvatar, userLink, postLink, originalUser) {
let editTitle = ` let editTitle = `
@ -75,7 +76,7 @@ export default Component.extend({
} }
return htmlSafe(editTitle); return htmlSafe(editTitle);
}, }
_formatReplyToTopic(link) { _formatReplyToTopic(link) {
return htmlSafe( return htmlSafe(
@ -83,12 +84,12 @@ export default Component.extend({
"model.topic.id" "model.topic.id"
)}">${link.anchor}</a>` )}">${link.anchor}</a>`
); );
}, }
_formatReplyToUserPost(avatar, link) { _formatReplyToUserPost(avatar, link) {
const htmlLink = `<a class="user-link" href="${link.href}">${escape( const htmlLink = `<a class="user-link" href="${link.href}">${escape(
link.anchor link.anchor
)}</a>`; )}</a>`;
return htmlSafe(`${avatar}${htmlLink}`); return htmlSafe(`${avatar}${htmlLink}`);
}, }
}); }

View File

@ -1,15 +1,14 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { cancel, schedule, throttle } from "@ember/runloop"; import { cancel, schedule, throttle } from "@ember/runloop";
import { classNameBindings } from "@ember-decorators/component";
import { observes } from "@ember-decorators/object";
import { headerOffset } from "discourse/lib/offset-calculator"; import { headerOffset } from "discourse/lib/offset-calculator";
import positioningWorkaround from "discourse/lib/safari-hacks"; import positioningWorkaround from "discourse/lib/safari-hacks";
import { isiPad } from "discourse/lib/utilities"; import { isiPad } from "discourse/lib/utilities";
import Composer from "discourse/models/composer"; import Composer from "discourse/models/composer";
import discourseDebounce from "discourse-common/lib/debounce"; import discourseDebounce from "discourse-common/lib/debounce";
import discourseLater from "discourse-common/lib/later"; import discourseLater from "discourse-common/lib/later";
import discourseComputed, { import discourseComputed, { bind } from "discourse-common/utils/decorators";
bind,
observes,
} from "discourse-common/utils/decorators";
const START_DRAG_EVENTS = ["touchstart", "mousedown"]; const START_DRAG_EVENTS = ["touchstart", "mousedown"];
const DRAG_EVENTS = ["touchmove", "mousemove"]; const DRAG_EVENTS = ["touchmove", "mousemove"];
@ -21,37 +20,36 @@ function mouseYPos(e) {
return e.clientY || (e.touches && e.touches[0] && e.touches[0].clientY); return e.clientY || (e.touches && e.touches[0] && e.touches[0].clientY);
} }
export default Component.extend({ @classNameBindings(
elementId: "reply-control", "composer.creatingPrivateMessage:private-message",
"composeState",
classNameBindings: [ "composer.loading",
"composer.creatingPrivateMessage:private-message", "prefixedComposerAction",
"composeState", "composer.canEditTitle:edit-title",
"composer.loading", "composer.createdPost:created-post",
"prefixedComposerAction", "composer.creatingTopic:topic",
"composer.canEditTitle:edit-title", "composer.whisper:composing-whisper",
"composer.createdPost:created-post", "composer.sharedDraft:composing-shared-draft",
"composer.creatingTopic:topic", "showPreview:show-preview:hide-preview",
"composer.whisper:composing-whisper", "currentUserPrimaryGroupClass"
"composer.sharedDraft:composing-shared-draft", )
"showPreview:show-preview:hide-preview", export default class ComposerBody extends Component {
"currentUserPrimaryGroupClass", elementId = "reply-control";
],
@discourseComputed("composer.action") @discourseComputed("composer.action")
prefixedComposerAction(action) { prefixedComposerAction(action) {
return action ? `composer-action-${action}` : ""; return action ? `composer-action-${action}` : "";
}, }
@discourseComputed("currentUser.primary_group_name") @discourseComputed("currentUser.primary_group_name")
currentUserPrimaryGroupClass(primaryGroupName) { currentUserPrimaryGroupClass(primaryGroupName) {
return primaryGroupName && `group-${primaryGroupName}`; return primaryGroupName && `group-${primaryGroupName}`;
}, }
@discourseComputed("composer.composeState") @discourseComputed("composer.composeState")
composeState(composeState) { composeState(composeState) {
return composeState || Composer.CLOSED; return composeState || Composer.CLOSED;
}, }
keyUp() { keyUp() {
this.typed(); this.typed();
@ -68,14 +66,14 @@ export default Component.extend({
} }
this.appEvents.trigger("composer:find-similar"); this.appEvents.trigger("composer:find-similar");
}, 1000); }, 1000);
}, }
@observes("composeState") @observes("composeState")
disableFullscreen() { disableFullscreen() {
if (this.composeState !== Composer.OPEN && positioningWorkaround.blur) { if (this.composeState !== Composer.OPEN && positioningWorkaround.blur) {
positioningWorkaround.blur(); positioningWorkaround.blur();
} }
}, }
setupComposerResizeEvents() { setupComposerResizeEvents() {
this.origComposerSize = 0; this.origComposerSize = 0;
@ -88,7 +86,7 @@ export default Component.extend({
passive: false, passive: false,
}); });
}); });
}, }
@bind @bind
performDragHandler() { performDragHandler() {
@ -112,14 +110,14 @@ export default Component.extend({
); );
this._triggerComposerResized(); this._triggerComposerResized();
}, }
@observes("composeState", "composer.{action,canEditTopicFeaturedLink}") @observes("composeState", "composer.{action,canEditTopicFeaturedLink}")
_triggerComposerResized() { _triggerComposerResized() {
schedule("afterRender", () => { schedule("afterRender", () => {
discourseDebounce(this, this.composerResized, 300); discourseDebounce(this, this.composerResized, 300);
}); });
}, }
composerResized() { composerResized() {
if (!this.element || this.isDestroying || this.isDestroyed) { if (!this.element || this.isDestroying || this.isDestroyed) {
@ -127,7 +125,7 @@ export default Component.extend({
} }
this.appEvents.trigger("composer:resized"); this.appEvents.trigger("composer:resized");
}, }
@bind @bind
startDragHandler(event) { startDragHandler(event) {
@ -145,7 +143,7 @@ export default Component.extend({
}); });
this.appEvents.trigger("composer:resize-started"); this.appEvents.trigger("composer:resize-started");
}, }
@bind @bind
endDragHandler() { endDragHandler() {
@ -161,16 +159,16 @@ export default Component.extend({
this.element.classList.remove("clear-transitions"); this.element.classList.remove("clear-transitions");
this.element.focus(); this.element.focus();
}, }
@bind @bind
throttledPerformDrag(event) { throttledPerformDrag(event) {
event.preventDefault(); event.preventDefault();
throttle(this, this.performDragHandler, event, THROTTLE_RATE); throttle(this, this.performDragHandler, event, THROTTLE_RATE);
}, }
didInsertElement() { didInsertElement() {
this._super(...arguments); super.didInsertElement(...arguments);
this.setupComposerResizeEvents(); this.setupComposerResizeEvents();
@ -188,10 +186,10 @@ export default Component.extend({
}); });
positioningWorkaround(this.element); positioningWorkaround(this.element);
}, }
willDestroyElement() { willDestroyElement() {
this._super(...arguments); super.willDestroyElement(...arguments);
START_DRAG_EVENTS.forEach((startDragEvent) => { START_DRAG_EVENTS.forEach((startDragEvent) => {
this.element this.element
@ -200,11 +198,11 @@ export default Component.extend({
}); });
cancel(this._lastKeyTimeout); cancel(this._lastKeyTimeout);
}, }
click() { click() {
this.openIfDraft(); this.openIfDraft();
}, }
keyDown(e) { keyDown(e) {
if (e.key === "Escape") { if (e.key === "Escape") {
@ -220,5 +218,5 @@ export default Component.extend({
e.preventDefault(); e.preventDefault();
this.save(undefined, e); this.save(undefined, e);
} }
}, }
}); }

View File

@ -4,9 +4,9 @@
@previewUpdated={{action "previewUpdated"}} @previewUpdated={{action "previewUpdated"}}
@markdownOptions={{this.markdownOptions}} @markdownOptions={{this.markdownOptions}}
@extraButtons={{action "extraButtons"}} @extraButtons={{action "extraButtons"}}
@importQuote={{action "importQuote"}} @importQuote={{this.importQuote}}
@showUploadModal={{this.showUploadModal}} @showUploadModal={{this.showUploadModal}}
@togglePreview={{action "togglePreview"}} @togglePreview={{this.togglePreview}}
@processPreview={{this.processPreview}} @processPreview={{this.processPreview}}
@validation={{this.validation}} @validation={{this.validation}}
@loading={{this.composer.loading}} @loading={{this.composer.loading}}

View File

@ -1,8 +1,10 @@
import Component from "@ember/component"; import Component from "@ember/component";
import EmberObject, { computed } from "@ember/object"; import EmberObject, { action, computed } from "@ember/object";
import { alias } from "@ember/object/computed"; import { alias } from "@ember/object/computed";
import { getOwner } from "@ember/owner"; import { getOwner } from "@ember/owner";
import { next, schedule, throttle } from "@ember/runloop"; import { next, schedule, throttle } from "@ember/runloop";
import { classNameBindings } from "@ember-decorators/component";
import { observes } from "@ember-decorators/object";
import { BasePlugin } from "@uppy/core"; import { BasePlugin } from "@uppy/core";
import $ from "jquery"; import $ from "jquery";
import { resolveAllShortUrls } from "pretty-text/upload-short-url"; import { resolveAllShortUrls } from "pretty-text/upload-short-url";
@ -39,7 +41,6 @@ import { findRawTemplate } from "discourse-common/lib/raw-templates";
import discourseComputed, { import discourseComputed, {
bind, bind,
debounce, debounce,
observes,
on, on,
} from "discourse-common/utils/decorators"; } from "discourse-common/utils/decorators";
import I18n from "discourse-i18n"; import I18n from "discourse-i18n";
@ -109,32 +110,32 @@ export function addApiImageWrapperButtonClickEvent(fn) {
const DEBOUNCE_FETCH_MS = 450; const DEBOUNCE_FETCH_MS = 450;
const DEBOUNCE_JIT_MS = 2000; const DEBOUNCE_JIT_MS = 2000;
export default Component.extend(ComposerUploadUppy, { @classNameBindings("showToolbar:toolbar-visible", ":wmd-controls")
classNameBindings: ["showToolbar:toolbar-visible", ":wmd-controls"], export default class ComposerEditor extends Component.extend(
ComposerUploadUppy
) {
editorClass = ".d-editor";
fileUploadElementId = "file-uploader";
mobileFileUploaderId = "mobile-file-upload";
composerEventPrefix = "composer";
uploadType = "composer";
uppyId = "composer-editor-uppy";
composerModelContentKey = "reply";
editorInputClass = ".d-editor-input";
shouldBuildScrollMap = true;
scrollMap = null;
processPreview = true;
uploadMarkdownResolvers = uploadMarkdownResolvers;
uploadPreProcessors = uploadPreProcessors;
uploadHandlers = uploadHandlers;
editorClass: ".d-editor", @alias("composer") composerModel;
fileUploadElementId: "file-uploader",
mobileFileUploaderId: "mobile-file-upload",
composerEventPrefix: "composer",
uploadType: "composer",
uppyId: "composer-editor-uppy",
composerModel: alias("composer"),
composerModelContentKey: "reply",
editorInputClass: ".d-editor-input",
shouldBuildScrollMap: true,
scrollMap: null,
processPreview: true,
uploadMarkdownResolvers,
uploadPreProcessors,
uploadHandlers,
init() { init() {
this._super(...arguments); super.init(...arguments);
this.warnedCannotSeeMentions = []; this.warnedCannotSeeMentions = [];
this.warnedGroupMentions = []; this.warnedGroupMentions = [];
}, }
@discourseComputed("composer.requiredCategoryMissing") @discourseComputed("composer.requiredCategoryMissing")
replyPlaceholder(requiredCategoryMissing) { replyPlaceholder(requiredCategoryMissing) {
@ -149,19 +150,19 @@ export default Component.extend(ComposerUploadUppy, {
: "reply_placeholder_no_images"; : "reply_placeholder_no_images";
return `composer.${key}`; return `composer.${key}`;
} }
}, }
@discourseComputed @discourseComputed
showLink() { showLink() {
return this.currentUser && this.currentUser.link_posting_access !== "none"; return this.currentUser && this.currentUser.link_posting_access !== "none";
}, }
@observes("focusTarget") @observes("focusTarget")
setFocus() { setFocus() {
if (this.focusTarget === "editor") { if (this.focusTarget === "editor") {
putCursorAtEnd(this.element.querySelector("textarea")); putCursorAtEnd(this.element.querySelector("textarea"));
} }
}, }
@discourseComputed @discourseComputed
markdownOptions() { markdownOptions() {
@ -204,7 +205,7 @@ export default Component.extend(ComposerUploadUppy, {
this.site.hashtag_configurations["topic-composer"], this.site.hashtag_configurations["topic-composer"],
hashtagIcons: this.site.hashtag_icons, hashtagIcons: this.site.hashtag_icons,
}; };
}, }
@bind @bind
_afterMentionComplete(value) { _afterMentionComplete(value) {
@ -216,7 +217,7 @@ export default Component.extend(ComposerUploadUppy, {
input?.blur(); input?.blur();
input?.focus(); input?.focus();
}); });
}, }
@on("didInsertElement") @on("didInsertElement")
_composerEditorInit() { _composerEditorInit() {
@ -266,7 +267,7 @@ export default Component.extend(ComposerUploadUppy, {
} }
this.appEvents.trigger(`${this.composerEventPrefix}:will-open`); this.appEvents.trigger(`${this.composerEventPrefix}:will-open`);
}, }
@discourseComputed( @discourseComputed(
"composer.reply", "composer.reply",
@ -313,7 +314,7 @@ export default Component.extend(ComposerUploadUppy, {
lastShownAt: lastValidatedAt, lastShownAt: lastValidatedAt,
}); });
} }
}, }
@computed("composer.{creatingTopic,editingFirstPost,creatingSharedDraft}") @computed("composer.{creatingTopic,editingFirstPost,creatingSharedDraft}")
get _isNewTopic() { get _isNewTopic() {
@ -322,11 +323,11 @@ export default Component.extend(ComposerUploadUppy, {
this.composer.editingFirstPost || this.composer.editingFirstPost ||
this.composer.creatingSharedDraft this.composer.creatingSharedDraft
); );
}, }
_resetShouldBuildScrollMap() { _resetShouldBuildScrollMap() {
this.set("shouldBuildScrollMap", true); this.set("shouldBuildScrollMap", true);
}, }
@bind @bind
_handleInputInteraction(event) { _handleInputInteraction(event) {
@ -338,7 +339,7 @@ export default Component.extend(ComposerUploadUppy, {
preview.removeEventListener("scroll", this._handleInputOrPreviewScroll); preview.removeEventListener("scroll", this._handleInputOrPreviewScroll);
event.target.addEventListener("scroll", this._handleInputOrPreviewScroll); event.target.addEventListener("scroll", this._handleInputOrPreviewScroll);
}, }
@bind @bind
_handleInputOrPreviewScroll(event) { _handleInputOrPreviewScroll(event) {
@ -347,7 +348,7 @@ export default Component.extend(ComposerUploadUppy, {
$(event.target), $(event.target),
$(this.element.querySelector(".d-editor-preview-wrapper")) $(this.element.querySelector(".d-editor-preview-wrapper"))
); );
}, }
@bind @bind
_handlePreviewInteraction(event) { _handlePreviewInteraction(event) {
@ -356,7 +357,7 @@ export default Component.extend(ComposerUploadUppy, {
?.removeEventListener("scroll", this._handleInputOrPreviewScroll); ?.removeEventListener("scroll", this._handleInputOrPreviewScroll);
event.target?.addEventListener("scroll", this._handleInputOrPreviewScroll); event.target?.addEventListener("scroll", this._handleInputOrPreviewScroll);
}, }
_syncScroll($callback, $input, $preview) { _syncScroll($callback, $input, $preview) {
if (!this.scrollMap || this.shouldBuildScrollMap) { if (!this.scrollMap || this.shouldBuildScrollMap) {
@ -365,7 +366,7 @@ export default Component.extend(ComposerUploadUppy, {
} }
throttle(this, $callback, $input, $preview, this.scrollMap, 20); throttle(this, $callback, $input, $preview, this.scrollMap, 20);
}, }
// Adapted from https://github.com/markdown-it/markdown-it.github.io // Adapted from https://github.com/markdown-it/markdown-it.github.io
_buildScrollMap($input, $preview) { _buildScrollMap($input, $preview) {
@ -452,7 +453,7 @@ export default Component.extend(ComposerUploadUppy, {
} }
return scrollMap; return scrollMap;
}, }
@bind @bind
_throttledSyncEditorAndPreviewScroll(event) { _throttledSyncEditorAndPreviewScroll(event) {
@ -465,7 +466,7 @@ export default Component.extend(ComposerUploadUppy, {
$preview, $preview,
20 20
); );
}, }
_syncEditorAndPreviewScroll($input, $preview) { _syncEditorAndPreviewScroll($input, $preview) {
if (!$input) { if (!$input) {
@ -490,7 +491,7 @@ export default Component.extend(ComposerUploadUppy, {
const factor = previewHeight / inputHeight; const factor = previewHeight / inputHeight;
const desired = scrollPosition * factor; const desired = scrollPosition * factor;
$preview.scrollTop(desired + 50); $preview.scrollTop(desired + 50);
}, }
_renderMentions(preview, unseen) { _renderMentions(preview, unseen) {
unseen ||= linkSeenMentions(preview, this.siteSettings); unseen ||= linkSeenMentions(preview, this.siteSettings);
@ -500,7 +501,7 @@ export default Component.extend(ComposerUploadUppy, {
this._warnMentionedGroups(preview); this._warnMentionedGroups(preview);
this._warnCannotSeeMention(preview); this._warnCannotSeeMention(preview);
} }
}, }
@debounce(DEBOUNCE_FETCH_MS) @debounce(DEBOUNCE_FETCH_MS)
_renderUnseenMentions(preview, unseen) { _renderUnseenMentions(preview, unseen) {
@ -514,7 +515,7 @@ export default Component.extend(ComposerUploadUppy, {
this._warnCannotSeeMention(preview); this._warnCannotSeeMention(preview);
this._warnHereMention(response.here_count); this._warnHereMention(response.here_count);
}); });
}, }
_renderHashtags(preview, unseen) { _renderHashtags(preview, unseen) {
const context = this.site.hashtag_configurations["topic-composer"]; const context = this.site.hashtag_configurations["topic-composer"];
@ -522,14 +523,14 @@ export default Component.extend(ComposerUploadUppy, {
if (unseen.length > 0) { if (unseen.length > 0) {
this._renderUnseenHashtags(preview, unseen, context); this._renderUnseenHashtags(preview, unseen, context);
} }
}, }
@debounce(DEBOUNCE_FETCH_MS) @debounce(DEBOUNCE_FETCH_MS)
_renderUnseenHashtags(preview, unseen, context) { _renderUnseenHashtags(preview, unseen, context) {
fetchUnseenHashtagsInContext(context, unseen).then(() => fetchUnseenHashtagsInContext(context, unseen).then(() =>
linkSeenHashtagsInContext(context, preview) linkSeenHashtagsInContext(context, preview)
); );
}, }
@debounce(DEBOUNCE_FETCH_MS) @debounce(DEBOUNCE_FETCH_MS)
_refreshOneboxes(preview) { _refreshOneboxes(preview) {
@ -549,15 +550,15 @@ export default Component.extend(ComposerUploadUppy, {
if (refresh && loaded > 0) { if (refresh && loaded > 0) {
post.set("refreshedPost", true); post.set("refreshedPost", true);
} }
}, }
_expandShortUrls(preview) { _expandShortUrls(preview) {
resolveAllShortUrls(ajax, this.siteSettings, preview); resolveAllShortUrls(ajax, this.siteSettings, preview);
}, }
_decorateCookedElement(preview) { _decorateCookedElement(preview) {
this.appEvents.trigger("decorate-non-stream-cooked-element", preview); this.appEvents.trigger("decorate-non-stream-cooked-element", preview);
}, }
@debounce(DEBOUNCE_JIT_MS) @debounce(DEBOUNCE_JIT_MS)
_warnMentionedGroups(preview) { _warnMentionedGroups(preview) {
@ -581,7 +582,7 @@ export default Component.extend(ComposerUploadUppy, {
}); });
}); });
}); });
}, }
// add a delay to allow for typing, so you don't open the warning right away // add a delay to allow for typing, so you don't open the warning right away
// previously we would warn after @bob even if you were about to mention @bob2 // previously we would warn after @bob even if you were about to mention @bob2
@ -620,7 +621,7 @@ export default Component.extend(ComposerUploadUppy, {
isGroup: true, isGroup: true,
}); });
}); });
}, }
_warnHereMention(hereCount) { _warnHereMention(hereCount) {
if (!hereCount || hereCount === 0) { if (!hereCount || hereCount === 0) {
@ -628,7 +629,7 @@ export default Component.extend(ComposerUploadUppy, {
} }
this.hereMention(hereCount); this.hereMention(hereCount);
}, }
@bind @bind
_handleImageScaleButtonClick(event) { _handleImageScaleButtonClick(event) {
@ -665,7 +666,7 @@ export default Component.extend(ComposerUploadUppy, {
event.preventDefault(); event.preventDefault();
return; return;
}, }
resetImageControls(buttonWrapper) { resetImageControls(buttonWrapper) {
const imageResize = buttonWrapper.querySelector(".scale-btn-container"); const imageResize = buttonWrapper.querySelector(".scale-btn-container");
@ -684,7 +685,7 @@ export default Component.extend(ComposerUploadUppy, {
readonlyContainer.removeAttribute("hidden"); readonlyContainer.removeAttribute("hidden");
buttonWrapper.removeAttribute("editing"); buttonWrapper.removeAttribute("editing");
editContainer.setAttribute("hidden", "true"); editContainer.setAttribute("hidden", "true");
}, }
commitAltText(buttonWrapper) { commitAltText(buttonWrapper) {
const index = parseInt(buttonWrapper.getAttribute("data-image-index"), 10); const index = parseInt(buttonWrapper.getAttribute("data-image-index"), 10);
@ -704,7 +705,7 @@ export default Component.extend(ComposerUploadUppy, {
); );
this.resetImageControls(buttonWrapper); this.resetImageControls(buttonWrapper);
}, }
@bind @bind
_handleAltTextInputKeypress(event) { _handleAltTextInputKeypress(event) {
@ -720,7 +721,7 @@ export default Component.extend(ComposerUploadUppy, {
const buttonWrapper = event.target.closest(".button-wrapper"); const buttonWrapper = event.target.closest(".button-wrapper");
this.commitAltText(buttonWrapper); this.commitAltText(buttonWrapper);
} }
}, }
@bind @bind
_handleAltTextEditButtonClick(event) { _handleAltTextEditButtonClick(event) {
@ -750,7 +751,7 @@ export default Component.extend(ComposerUploadUppy, {
editContainer.removeAttribute("hidden"); editContainer.removeAttribute("hidden");
editContainerInput.focus(); editContainerInput.focus();
event.preventDefault(); event.preventDefault();
}, }
@bind @bind
_handleAltTextOkButtonClick(event) { _handleAltTextOkButtonClick(event) {
@ -760,7 +761,7 @@ export default Component.extend(ComposerUploadUppy, {
const buttonWrapper = event.target.closest(".button-wrapper"); const buttonWrapper = event.target.closest(".button-wrapper");
this.commitAltText(buttonWrapper); this.commitAltText(buttonWrapper);
}, }
@bind @bind
_handleAltTextCancelButtonClick(event) { _handleAltTextCancelButtonClick(event) {
@ -770,7 +771,7 @@ export default Component.extend(ComposerUploadUppy, {
const buttonWrapper = event.target.closest(".button-wrapper"); const buttonWrapper = event.target.closest(".button-wrapper");
this.resetImageControls(buttonWrapper); this.resetImageControls(buttonWrapper);
}, }
@bind @bind
_handleImageDeleteButtonClick(event) { _handleImageDeleteButtonClick(event) {
@ -789,7 +790,7 @@ export default Component.extend(ComposerUploadUppy, {
"", "",
{ regex: IMAGE_MARKDOWN_REGEX, index } { regex: IMAGE_MARKDOWN_REGEX, index }
); );
}, }
@bind @bind
_handleImageGridButtonClick(event) { _handleImageGridButtonClick(event) {
@ -818,7 +819,7 @@ export default Component.extend(ComposerUploadUppy, {
"grid_surround", "grid_surround",
{ useBlockMode: true } { useBlockMode: true }
); );
}, }
_registerImageAltTextButtonClick(preview) { _registerImageAltTextButtonClick(preview) {
preview.addEventListener("click", this._handleAltTextCancelButtonClick); preview.addEventListener("click", this._handleAltTextCancelButtonClick);
@ -832,7 +833,7 @@ export default Component.extend(ComposerUploadUppy, {
apiImageWrapperBtnEvents.forEach((fn) => apiImageWrapperBtnEvents.forEach((fn) =>
preview.addEventListener("click", fn) preview.addEventListener("click", fn)
); );
}, }
@on("willDestroyElement") @on("willDestroyElement")
_composerClosed() { _composerClosed() {
@ -870,17 +871,18 @@ export default Component.extend(ComposerUploadUppy, {
apiImageWrapperBtnEvents.forEach((fn) => apiImageWrapperBtnEvents.forEach((fn) =>
preview?.removeEventListener("click", fn) preview?.removeEventListener("click", fn)
); );
}, }
@action
onExpandPopupMenuOptions(toolbarEvent) { onExpandPopupMenuOptions(toolbarEvent) {
const selected = toolbarEvent.selected; const selected = toolbarEvent.selected;
toolbarEvent.selectText(selected.start, selected.end - selected.start); toolbarEvent.selectText(selected.start, selected.end - selected.start);
this.storeToolbarState(toolbarEvent); this.storeToolbarState(toolbarEvent);
}, }
showPreview() { showPreview() {
this.send("togglePreview"); this.send("togglePreview");
}, }
_isInQuote(element) { _isInQuote(element) {
let parent = element.parentElement; let parent = element.parentElement;
@ -893,18 +895,18 @@ export default Component.extend(ComposerUploadUppy, {
} }
return false; return false;
}, }
_isPreviewRoot(element) { _isPreviewRoot(element) {
return ( return (
element.tagName === "DIV" && element.tagName === "DIV" &&
element.classList.contains("d-editor-preview") element.classList.contains("d-editor-preview")
); );
}, }
_isQuote(element) { _isQuote(element) {
return element.tagName === "ASIDE" && element.classList.contains("quote"); return element.tagName === "ASIDE" && element.classList.contains("quote");
}, }
_cursorIsOnEmptyLine() { _cursorIsOnEmptyLine() {
const textArea = this.element.querySelector(".d-editor-input"); const textArea = this.element.querySelector(".d-editor-input");
@ -916,7 +918,7 @@ export default Component.extend(ComposerUploadUppy, {
} else { } else {
return false; return false;
} }
}, }
_findMatchingUploadHandler(fileName) { _findMatchingUploadHandler(fileName) {
return this.uploadHandlers.find((handler) => { return this.uploadHandlers.find((handler) => {
@ -924,62 +926,50 @@ export default Component.extend(ComposerUploadUppy, {
const regex = new RegExp(`\\.(${ext})$`, "i"); const regex = new RegExp(`\\.(${ext})$`, "i");
return regex.test(fileName); return regex.test(fileName);
}); });
}, }
actions: { @action
importQuote(toolbarEvent) { extraButtons(toolbar) {
this.importQuote(toolbarEvent); toolbar.addButton({
}, id: "quote",
group: "fontStyles",
icon: "far-comment",
sendAction: this.importQuote,
title: "composer.quote_post_title",
unshift: true,
});
onExpandPopupMenuOptions(toolbarEvent) { if (this.allowUpload && this.uploadIcon && this.site.desktopView) {
this.onExpandPopupMenuOptions(toolbarEvent);
},
togglePreview() {
this.togglePreview();
},
extraButtons(toolbar) {
toolbar.addButton({ toolbar.addButton({
id: "quote", id: "upload",
group: "fontStyles", group: "insertions",
icon: "far-comment", icon: this.uploadIcon,
sendAction: this.importQuote, title: "upload",
title: "composer.quote_post_title", sendAction: this.showUploadModal,
unshift: true,
}); });
}
if (this.allowUpload && this.uploadIcon && this.site.desktopView) { toolbar.addButton({
toolbar.addButton({ id: "options",
id: "upload", group: "extras",
group: "insertions", icon: "cog",
icon: this.uploadIcon, title: "composer.options",
title: "upload", sendAction: this.onExpandPopupMenuOptions.bind(this),
sendAction: this.showUploadModal, popupMenu: true,
}); });
} }
toolbar.addButton({ @action
id: "options", previewUpdated(preview, unseenMentions, unseenHashtags) {
group: "extras", this._renderMentions(preview, unseenMentions);
icon: "cog", this._renderHashtags(preview, unseenHashtags);
title: "composer.options", this._refreshOneboxes(preview);
sendAction: this.onExpandPopupMenuOptions.bind(this), this._expandShortUrls(preview);
popupMenu: true,
});
},
previewUpdated(preview, unseenMentions, unseenHashtags) { if (!this.siteSettings.enable_diffhtml_preview) {
this._renderMentions(preview, unseenMentions); this._decorateCookedElement(preview);
this._renderHashtags(preview, unseenHashtags); }
this._refreshOneboxes(preview);
this._expandShortUrls(preview);
if (!this.siteSettings.enable_diffhtml_preview) { this.afterRefresh(preview);
this._decorateCookedElement(preview); }
} }
this.afterRefresh(preview);
},
},
});

View File

@ -1,23 +1,12 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { getOwner } from "@ember/owner"; import { getOwner } from "@ember/owner";
import deprecated from "discourse-common/lib/deprecated"; import { classNameBindings } from "@ember-decorators/component";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend({ @classNameBindings(":composer-popup", "message.extraClass")
classNameBindings: [":composer-popup", "message.extraClass"], export default class ComposerMessage extends Component {
@discourseComputed("message.templateName") @discourseComputed("message.templateName")
layout(templateName) { layout(templateName) {
return getOwner(this).lookup(`template:composer/${templateName}`); return getOwner(this).lookup(`template:composer/${templateName}`);
}, }
}
actions: {
closeMessage() {
deprecated(
'You should use `action=(closeMessage message)` instead of `action=(action "closeMessage")`',
{ id: "discourse.composer-message.closeMessage" }
);
this.closeMessage(this.message);
},
},
});

View File

@ -2,23 +2,26 @@ import Component from "@ember/component";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
import { alias, or } from "@ember/object/computed"; import { alias, or } from "@ember/object/computed";
import { next, schedule } from "@ember/runloop"; import { next, schedule } from "@ember/runloop";
import { classNames } from "@ember-decorators/component";
import { observes } from "@ember-decorators/object";
import { load } from "pretty-text/oneboxer"; import { load } from "pretty-text/oneboxer";
import { lookupCache } from "pretty-text/oneboxer-cache"; import { lookupCache } from "pretty-text/oneboxer-cache";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import putCursorAtEnd from "discourse/lib/put-cursor-at-end"; import putCursorAtEnd from "discourse/lib/put-cursor-at-end";
import { isTesting } from "discourse-common/config/environment"; import { isTesting } from "discourse-common/config/environment";
import discourseDebounce from "discourse-common/lib/debounce"; import discourseDebounce from "discourse-common/lib/debounce";
import discourseComputed, { observes } from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import I18n from "discourse-i18n"; import I18n from "discourse-i18n";
export default Component.extend({ @classNames("title-input")
classNames: ["title-input"], export default class ComposerTitle extends Component {
watchForLink: alias("composer.canEditTopicFeaturedLink"), @alias("composer.canEditTopicFeaturedLink") watchForLink;
disabled: or("composer.loading", "composer.disableTitleInput"), @or("composer.loading", "composer.disableTitleInput") disabled;
isTitleFocused: false,
isTitleFocused = false;
didInsertElement() { didInsertElement() {
this._super(...arguments); super.didInsertElement(...arguments);
const titleInput = this.element.querySelector("input"); const titleInput = this.element.querySelector("input");
this._focusHandler = () => this.set("isTitleFocused", true); this._focusHandler = () => this.set("isTitleFocused", true);
@ -34,17 +37,17 @@ export default Component.extend({
if (this.get("composer.titleLength") > 0) { if (this.get("composer.titleLength") > 0) {
discourseDebounce(this, this._titleChanged, 10); discourseDebounce(this, this._titleChanged, 10);
} }
}, }
willDestroyElement() { willDestroyElement() {
this._super(...arguments); super.willDestroyElement(...arguments);
const titleInput = this.element.querySelector("input"); const titleInput = this.element.querySelector("input");
if (titleInput) { if (titleInput) {
titleInput.removeEventListener("focus", this._focusHandler); titleInput.removeEventListener("focus", this._focusHandler);
titleInput.removeEventListener("blur", this._blurHandler); titleInput.removeEventListener("blur", this._blurHandler);
} }
}, }
@discourseComputed( @discourseComputed(
"composer.titleLength", "composer.titleLength",
@ -83,14 +86,14 @@ export default Component.extend({
lastShownAt: lastValidatedAt, lastShownAt: lastValidatedAt,
}); });
} }
}, }
@discourseComputed("watchForLink") @discourseComputed("watchForLink")
titleMaxLength(watchForLink) { titleMaxLength(watchForLink) {
// maxLength gets in the way of pasting long links, so don't use it if featured links are allowed. // maxLength gets in the way of pasting long links, so don't use it if featured links are allowed.
// Validation will display a message if titles are too long. // Validation will display a message if titles are too long.
return watchForLink ? null : this.siteSettings.max_topic_title_length; return watchForLink ? null : this.siteSettings.max_topic_title_length;
}, }
@observes("composer.titleLength", "watchForLink") @observes("composer.titleLength", "watchForLink")
_titleChanged() { _titleChanged() {
@ -110,14 +113,14 @@ export default Component.extend({
} else { } else {
discourseDebounce(this, this._checkForUrl, 500); discourseDebounce(this, this._checkForUrl, 500);
} }
}, }
@observes("composer.replyLength") @observes("composer.replyLength")
_clearFeaturedLink() { _clearFeaturedLink() {
if (this.watchForLink && this.bodyIsDefault()) { if (this.watchForLink && this.bodyIsDefault()) {
this.set("composer.featuredLink", null); this.set("composer.featuredLink", null);
} }
}, }
_checkForUrl() { _checkForUrl() {
if (!this.element || this.isDestroying || this.isDestroyed) { if (!this.element || this.isDestroying || this.isDestroyed) {
@ -169,7 +172,7 @@ export default Component.extend({
}); });
} }
} }
}, }
_updatePost(html) { _updatePost(html) {
if (html) { if (html) {
@ -207,13 +210,13 @@ export default Component.extend({
} }
} }
} }
}, }
changeTitle(val) { changeTitle(val) {
if (val && val.length > 0) { if (val && val.length > 0) {
this.set("composer.title", val.trim()); this.set("composer.title", val.trim());
} }
}, }
@discourseComputed("composer.title", "composer.titleLength") @discourseComputed("composer.title", "composer.titleLength")
isAbsoluteUrl(title, titleLength) { isAbsoluteUrl(title, titleLength) {
@ -222,7 +225,7 @@ export default Component.extend({
/^(https?:)?\/\/[\w\.\-]+/i.test(title) && /^(https?:)?\/\/[\w\.\-]+/i.test(title) &&
!/\s/.test(title) !/\s/.test(title)
); );
}, }
bodyIsDefault() { bodyIsDefault() {
const reply = this.get("composer.reply") || ""; const reply = this.get("composer.reply") || "";
@ -230,5 +233,5 @@ export default Component.extend({
reply.length === 0 || reply.length === 0 ||
reply === (this.get("composer.category.topic_template") || "") reply === (this.get("composer.category.topic_template") || "")
); );
}, }
}); }

View File

@ -1,20 +1,20 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { tagName } from "@ember-decorators/component";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend({ @tagName("")
tagName: "", export default class ComposerToggles extends Component {
@discourseComputed("composeState") @discourseComputed("composeState")
toggleTitle(composeState) { toggleTitle(composeState) {
return composeState === "draft" || composeState === "saving" return composeState === "draft" || composeState === "saving"
? "composer.abandon" ? "composer.abandon"
: "composer.collapse"; : "composer.collapse";
}, }
@discourseComputed("showToolbar") @discourseComputed("showToolbar")
toggleToolbarTitle(showToolbar) { toggleToolbarTitle(showToolbar) {
return showToolbar ? "composer.hide_toolbar" : "composer.show_toolbar"; return showToolbar ? "composer.hide_toolbar" : "composer.show_toolbar";
}, }
@discourseComputed("composeState") @discourseComputed("composeState")
fullscreenTitle(composeState) { fullscreenTitle(composeState) {
@ -23,14 +23,14 @@ export default Component.extend({
: composeState === "fullscreen" : composeState === "fullscreen"
? "composer.exit_fullscreen" ? "composer.exit_fullscreen"
: "composer.enter_fullscreen"; : "composer.enter_fullscreen";
}, }
@discourseComputed("composeState") @discourseComputed("composeState")
toggleIcon(composeState) { toggleIcon(composeState) {
return composeState === "draft" || composeState === "saving" return composeState === "draft" || composeState === "saving"
? "times" ? "times"
: "chevron-down"; : "chevron-down";
}, }
@discourseComputed("composeState") @discourseComputed("composeState")
fullscreenIcon(composeState) { fullscreenIcon(composeState) {
@ -39,7 +39,7 @@ export default Component.extend({
: composeState === "fullscreen" : composeState === "fullscreen"
? "discourse-compress" ? "discourse-compress"
: "discourse-expand"; : "discourse-expand";
}, }
@discourseComputed("disableTextarea") @discourseComputed("disableTextarea")
showFullScreenButton(disableTextarea) { showFullScreenButton(disableTextarea) {
@ -47,5 +47,5 @@ export default Component.extend({
return false; return false;
} }
return !disableTextarea; return !disableTextarea;
}, }
}); }

View File

@ -1,19 +1,17 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { action } from "@ember/object";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend({ export default class ComposerUserSelector extends Component {
init() { _groups = [];
this._super(...arguments);
this.set("_groups", []);
},
didInsertElement() { didInsertElement() {
this._super(...arguments); super.didInsertElement(...arguments);
if (this.focusTarget === "usernames") { if (this.focusTarget === "usernames") {
this.element.querySelector(".select-kit .select-kit-header").focus(); this.element.querySelector(".select-kit .select-kit-header").focus();
} }
}, }
@discourseComputed("recipients") @discourseComputed("recipients")
splitRecipients(recipients) { splitRecipients(recipients) {
@ -21,7 +19,7 @@ export default Component.extend({
return recipients; return recipients;
} }
return recipients ? recipients.split(",").filter(Boolean) : []; return recipients ? recipients.split(",").filter(Boolean) : [];
}, }
_updateGroups(selected, newGroups) { _updateGroups(selected, newGroups) {
const groups = []; const groups = [];
@ -39,13 +37,12 @@ export default Component.extend({
_groups: groups, _groups: groups,
hasGroups: groups.length > 0, hasGroups: groups.length > 0,
}); });
}, }
actions: { @action
updateRecipients(selected, content) { updateRecipients(selected, content) {
const newGroups = content.filterBy("isGroup").mapBy("id"); const newGroups = content.filterBy("isGroup").mapBy("id");
this._updateGroups(selected, newGroups); this._updateGroups(selected, newGroups);
this.set("recipients", selected.join(",")); this.set("recipients", selected.join(","));
}, }
}, }
});

View File

@ -1,11 +1,10 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { classNameBindings, classNames } from "@ember-decorators/component";
import I18n from "discourse-i18n"; import I18n from "discourse-i18n";
export default Component.extend({
classNames: ["conditional-loading-section"],
classNameBindings: ["isLoading"], @classNames("conditional-loading-section")
@classNameBindings("isLoading")
isLoading: false, export default class ConditionalLoadingSection extends Component {
isLoading = false;
title: I18n.t("conditional_loading_section.loading"), title = I18n.t("conditional_loading_section.loading");
}); }

View File

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

View File

@ -1,12 +1,13 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { action } from "@ember/object"; import { action } from "@ember/object";
import { tagName } from "@ember-decorators/component";
import discourseDebounce from "discourse-common/lib/debounce"; import discourseDebounce from "discourse-common/lib/debounce";
import { bind } from "discourse-common/utils/decorators"; import { bind } from "discourse-common/utils/decorators";
export default Component.extend({ @tagName("")
tagName: "", export default class CopyButton extends Component {
copyIcon: "copy", copyIcon = "copy";
copyClass: "btn-primary", copyClass = "btn-primary";
@bind @bind
_restoreButton() { _restoreButton() {
@ -16,7 +17,7 @@ export default Component.extend({
this.set("copyIcon", "copy"); this.set("copyIcon", "copy");
this.set("copyClass", "btn-primary"); this.set("copyClass", "btn-primary");
}, }
@action @action
copy() { copy() {
@ -36,5 +37,5 @@ export default Component.extend({
discourseDebounce(this._restoreButton, 3000); discourseDebounce(this._restoreButton, 3000);
} catch (err) {} } catch (err) {}
}, }
}); }

View File

@ -1,38 +1,41 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { action } from "@ember/object"; import { action } from "@ember/object";
import { tagName } from "@ember-decorators/component";
import UppyUploadMixin from "discourse/mixins/uppy-upload"; import UppyUploadMixin from "discourse/mixins/uppy-upload";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend(UppyUploadMixin, { @tagName("div")
id: "create-invite-uploader", export default class CreateInviteUploader extends Component.extend(
tagName: "div", UppyUploadMixin
type: "csv", ) {
autoStartUploads: false, id = "create-invite-uploader";
uploadUrl: "/invites/upload_csv", type = "csv";
preventDirectS3Uploads: true, autoStartUploads = false;
fileInputSelector: "#csv-file", uploadUrl = "/invites/upload_csv";
preventDirectS3Uploads = true;
fileInputSelector = "#csv-file";
validateUploadedFilesOptions() { validateUploadedFilesOptions() {
return { bypassNewUserRestriction: true, csvOnly: true }; return { bypassNewUserRestriction: true, csvOnly: true };
}, }
@discourseComputed("filesAwaitingUpload", "uploading") @discourseComputed("filesAwaitingUpload", "uploading")
submitDisabled(filesAwaitingUpload, uploading) { submitDisabled(filesAwaitingUpload, uploading) {
return !filesAwaitingUpload || uploading; return !filesAwaitingUpload || uploading;
}, }
uploadDone() { uploadDone() {
this.set("uploaded", true); this.set("uploaded", true);
}, }
@action @action
startUpload() { startUpload() {
this._startUpload(); this._startUpload();
}, }
@action @action
setElement(element) { setElement(element) {
this.set("fileInputEl", element); this.set("fileInputEl", element);
this._initialize(); this._initialize();
}, }
}); }

View File

@ -1,6 +1,8 @@
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({ import { tagName } from "@ember-decorators/component";
tagName: "",
label: "topic.create", @tagName("")
btnClass: "btn-default", export default class CreateTopicButton extends Component {
}); label = "topic.create";
btnClass = "btn-default";
}

View File

@ -4,11 +4,11 @@ import { hbs } from "ember-cli-htmlbars";
import { getCustomHTML } from "discourse/helpers/custom-html"; import { getCustomHTML } from "discourse/helpers/custom-html";
import deprecated from "discourse-common/lib/deprecated"; import deprecated from "discourse-common/lib/deprecated";
export default Component.extend({ export default class CustomHtml extends Component {
triggerAppEvent: null, triggerAppEvent = null;
init() { init() {
this._super(...arguments); super.init(...arguments);
const name = this.name; const name = this.name;
const html = getCustomHTML(name); const html = getCustomHTML(name);
@ -25,19 +25,19 @@ export default Component.extend({
this.set("layout", template); this.set("layout", template);
} }
} }
}, }
didInsertElement() { didInsertElement() {
this._super(...arguments); super.didInsertElement(...arguments);
if (this.triggerAppEvent === "true") { if (this.triggerAppEvent === "true") {
this.appEvents.trigger(`inserted-custom-html:${this.name}`); this.appEvents.trigger(`inserted-custom-html:${this.name}`);
} }
}, }
willDestroyElement() { willDestroyElement() {
this._super(...arguments); super.willDestroyElement(...arguments);
if (this.triggerAppEvent === "true") { if (this.triggerAppEvent === "true") {
this.appEvents.trigger(`destroyed-custom-html:${this.name}`); this.appEvents.trigger(`destroyed-custom-html:${this.name}`);
} }
}, }
}); }