DEV: Convert core components to native class syntax (batch 3) (#28517)

Changes made using the ember-native-class-codemod, plus some manual tweaks
This commit is contained in:
David Taylor 2024-08-27 15:28:08 +01:00 committed by GitHub
parent 9b83ae7d55
commit 7bf3727663
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 397 additions and 370 deletions

View File

@ -1,5 +1,6 @@
import Component from "@ember/component";
import { service } from "@ember/service";
import { tagName } from "@ember-decorators/component";
import { setLogoffCallback } from "discourse/lib/ajax";
import { clearAllBodyScrollLocks } from "discourse/lib/body-scroll-lock";
import logout from "discourse/lib/logout";
@ -11,14 +12,15 @@ export function addPluginDocumentTitleCounter(counterFunction) {
pluginCounterFunctions.push(counterFunction);
}
export default Component.extend({
tagName: "",
documentTitle: service(),
dialog: service(),
_showingLogout: false,
@tagName("")
export default class DDocument extends Component {
@service documentTitle;
@service dialog;
_showingLogout = false;
didInsertElement() {
this._super(...arguments);
super.didInsertElement(...arguments);
this.documentTitle.setTitle(document.title);
document.addEventListener("visibilitychange", this._focusChanged);
@ -28,10 +30,10 @@ export default Component.extend({
this.appEvents.on("notifications:changed", this, this._updateNotifications);
setLogoffCallback(() => this.displayLogoff());
},
}
willDestroyElement() {
this._super(...arguments);
super.willDestroyElement(...arguments);
setLogoffCallback(null);
document.removeEventListener("visibilitychange", this._focusChanged);
@ -43,7 +45,7 @@ export default Component.extend({
this,
this._updateNotifications
);
},
}
_updateNotifications(opts) {
if (!this.currentUser) {
@ -56,7 +58,7 @@ export default Component.extend({
count += this.currentUser.unseen_reviewable_count;
}
this.documentTitle.updateNotificationCount(count, { forced: opts?.forced });
},
}
@bind
_focusChanged() {
@ -70,7 +72,7 @@ export default Component.extend({
} else if (!this.hasFocus) {
this.documentTitle.setFocus(true);
}
},
}
displayLogoff() {
if (this._showingLogout) {
@ -86,5 +88,5 @@ export default Component.extend({
didConfirm: () => logout(),
didCancel: () => logout(),
});
},
});
}
}

View File

@ -64,8 +64,8 @@
@aria-label={{this.placeholderTranslated}}
@disabled={{this.disabled}}
@input={{this.change}}
@focusIn={{action "focusIn"}}
@focusOut={{action "focusOut"}}
@focusIn={{this.handleFocusIn}}
@focusOut={{this.handleFocusOut}}
class="d-editor-input"
@id={{this.textAreaId}}
/>

View File

@ -3,6 +3,8 @@ import { action, computed } from "@ember/object";
import { schedule, scheduleOnce } from "@ember/runloop";
import { service } from "@ember/service";
import ItsATrap from "@discourse/itsatrap";
import { classNames } from "@ember-decorators/component";
import { observes, on } from "@ember-decorators/object";
import $ from "jquery";
import { emojiSearch, isSkinTonableEmoji } from "pretty-text/emoji";
import { translations } from "pretty-text/emoji/data";
@ -32,11 +34,7 @@ import discourseDebounce from "discourse-common/lib/debounce";
import deprecated from "discourse-common/lib/deprecated";
import { getRegister } from "discourse-common/lib/get-owner";
import { findRawTemplate } from "discourse-common/lib/raw-templates";
import discourseComputed, {
bind,
observes,
on,
} from "discourse-common/utils/decorators";
import discourseComputed, { bind } from "discourse-common/utils/decorators";
import I18n from "discourse-i18n";
function getButtonLabel(labelKey, defaultLabel) {
@ -233,39 +231,47 @@ export function onToolbarCreate(func) {
addToolbarCallback(func);
}
export default Component.extend(TextareaTextManipulation, {
emojiStore: service("emoji-store"),
modal: service(),
@classNames("d-editor")
export default class DEditor extends Component.extend(
TextareaTextManipulation
) {
@service("emoji-store") emojiStore;
@service modal;
classNames: ["d-editor"],
ready: false,
lastSel: null,
_itsatrap: null,
showLink: true,
emojiPickerIsActive: false,
emojiFilter: "",
isEditorFocused: false,
processPreview: true,
composerFocusSelector: "#reply-control .d-editor-input",
selectedFormTemplateId: computed("formTemplateIds", {
get() {
if (this._selectedFormTemplateId) {
return this._selectedFormTemplateId;
}
return this.formTemplateId || this.formTemplateIds?.[0];
ready = false;
lastSel = null;
showLink = true;
emojiPickerIsActive = false;
emojiFilter = "";
isEditorFocused = false;
processPreview = true;
composerFocusSelector = "#reply-control .d-editor-input";
morphingOptions = {
beforeAttributeUpdated: (element, attributeName) => {
// Don't morph the open attribute of <details> elements
return !(element.tagName === "DETAILS" && attributeName === "open");
},
};
set(key, value) {
return (this._selectedFormTemplateId = value);
},
}),
_itsatrap = null;
@computed("formTemplateIds")
get selectedFormTemplateId() {
if (this._selectedFormTemplateId) {
return this._selectedFormTemplateId;
}
return this.formTemplateId || this.formTemplateIds?.[0];
}
set selectedFormTemplateId(value) {
this._selectedFormTemplateId = value;
}
@action
updateSelectedFormTemplateId(formTemplateId) {
this.selectedFormTemplateId = formTemplateId;
},
}
@discourseComputed("formTemplateIds", "replyingToTopic", "editingPost")
showFormTemplateForm(formTemplateIds, replyingToTopic, editingPost) {
@ -275,7 +281,7 @@ export default Component.extend(TextareaTextManipulation, {
}
return false;
},
}
@discourseComputed("placeholder")
placeholderTranslated(placeholder) {
@ -283,7 +289,7 @@ export default Component.extend(TextareaTextManipulation, {
return I18n.t(placeholder);
}
return null;
},
}
_readyNow() {
this.set("ready", true);
@ -291,16 +297,16 @@ export default Component.extend(TextareaTextManipulation, {
if (this.autofocus) {
this._textarea.focus();
}
},
}
init() {
this._super(...arguments);
super.init(...arguments);
this.register = getRegister(this);
},
}
didInsertElement() {
this._super(...arguments);
super.didInsertElement(...arguments);
this._previewMutationObserver = this._disablePreviewTabIndex();
@ -374,14 +380,14 @@ export default Component.extend(TextareaTextManipulation, {
"indentSelection"
);
}
},
}
@bind
onBeforeInputSmartList(event) {
// This inputType is much more consistently fired in `beforeinput`
// rather than `input`.
this.handleSmartListAutocomplete = event.inputType === "insertLineBreak";
},
}
@bind
onInputSmartList() {
@ -389,7 +395,7 @@ export default Component.extend(TextareaTextManipulation, {
this.maybeContinueList();
}
this.handleSmartListAutocomplete = false;
},
}
@bind
_handlePreviewLinkClick(event) {
@ -417,7 +423,7 @@ export default Component.extend(TextareaTextManipulation, {
event.preventDefault();
return false;
}
},
}
@on("willDestroyElement")
_shutDown() {
@ -455,7 +461,7 @@ export default Component.extend(TextareaTextManipulation, {
}
this._cachedCookFunction = null;
},
}
@discourseComputed()
toolbar() {
@ -476,12 +482,12 @@ export default Component.extend(TextareaTextManipulation, {
}
return toolbar;
},
}
async cachedCookAsync(text, options) {
this._cachedCookFunction ||= await generateCookFunction(options || {});
return await this._cachedCookFunction(text);
},
}
async _updatePreview() {
if (
@ -556,14 +562,7 @@ export default Component.extend(TextareaTextManipulation, {
this.previewUpdated(previewElement, unseenMentions, unseenHashtags);
}
});
},
morphingOptions: {
beforeAttributeUpdated: (element, attributeName) => {
// Don't morph the open attribute of <details> elements
return !(element.tagName === "DETAILS" && attributeName === "open");
},
},
}
@observes("ready", "value", "processPreview")
async _watchForChanges() {
@ -577,7 +576,7 @@ export default Component.extend(TextareaTextManipulation, {
} else {
discourseDebounce(this, this._updatePreview, 30);
}
},
}
_applyHashtagAutocomplete() {
setupHashtagAutocomplete(
@ -591,7 +590,7 @@ export default Component.extend(TextareaTextManipulation, {
},
}
);
},
}
_applyEmojiAutocomplete($textarea) {
if (!this.siteSettings.enable_emoji) {
@ -713,7 +712,7 @@ export default Component.extend(TextareaTextManipulation, {
triggerRule: async (textarea) =>
!(await inCodeBlock(textarea.value, caretPosition(textarea))),
});
},
}
_applyList(sel, head, exampleKey, opts) {
if (sel.value.includes("\n")) {
@ -736,12 +735,12 @@ export default Component.extend(TextareaTextManipulation, {
this.set("value", `${preLines}${number}${post}`);
this.selectText(preLines.length, number.length);
}
},
}
_applySurround(head, tail, exampleKey, opts) {
const selected = this.getSelected();
this.applySurround(selected, head, tail, exampleKey, opts);
},
}
_toggleDirection() {
let currentDir = this._$textarea.attr("dir")
@ -750,7 +749,7 @@ export default Component.extend(TextareaTextManipulation, {
newDir = currentDir === "ltr" ? "rtl" : "ltr";
this._$textarea.attr("dir", newDir).focus();
},
}
@action
rovingButtonBar(event) {
@ -789,14 +788,14 @@ export default Component.extend(TextareaTextManipulation, {
}
return true;
},
}
@action
onEmojiPickerClose() {
if (!(this.isDestroyed || this.isDestroying)) {
this.set("emojiPickerIsActive", false);
}
},
}
newToolbarEvent(trimLeading) {
const selected = this.getSelected(trimLeading);
@ -815,105 +814,110 @@ export default Component.extend(TextareaTextManipulation, {
replaceText: (oldVal, newVal, opts) =>
this.replaceText(oldVal, newVal, opts),
};
},
}
actions: {
emoji() {
if (this.disabled) {
return;
}
@action
emoji() {
if (this.disabled) {
return;
}
this.set("emojiPickerIsActive", !this.emojiPickerIsActive);
},
this.set("emojiPickerIsActive", !this.emojiPickerIsActive);
}
toolbarButton(button) {
if (this.disabled) {
return;
}
@action
toolbarButton(button) {
if (this.disabled) {
return;
}
const toolbarEvent = this.newToolbarEvent(button.trimLeading);
if (button.sendAction) {
return button.sendAction(toolbarEvent);
} else {
button.perform(toolbarEvent);
}
},
const toolbarEvent = this.newToolbarEvent(button.trimLeading);
if (button.sendAction) {
return button.sendAction(toolbarEvent);
} else {
button.perform(toolbarEvent);
}
}
showLinkModal(toolbarEvent) {
if (this.disabled) {
return;
}
@action
showLinkModal(toolbarEvent) {
if (this.disabled) {
return;
}
let linkText = "";
this._lastSel = toolbarEvent.selected;
let linkText = "";
this._lastSel = toolbarEvent.selected;
if (this._lastSel) {
linkText = this._lastSel.value;
}
if (this._lastSel) {
linkText = this._lastSel.value;
}
this.modal.show(InsertHyperlink, {
model: {
linkText,
toolbarEvent,
},
});
},
this.modal.show(InsertHyperlink, {
model: {
linkText,
toolbarEvent,
},
});
}
formatCode() {
if (this.disabled) {
return;
}
@action
formatCode() {
if (this.disabled) {
return;
}
const sel = this.getSelected("", { lineVal: true });
const selValue = sel.value;
const hasNewLine = selValue.includes("\n");
const isBlankLine = sel.lineVal.trim().length === 0;
const isFourSpacesIndent =
this.siteSettings.code_formatting_style === FOUR_SPACES_INDENT;
const sel = this.getSelected("", { lineVal: true });
const selValue = sel.value;
const hasNewLine = selValue.includes("\n");
const isBlankLine = sel.lineVal.trim().length === 0;
const isFourSpacesIndent =
this.siteSettings.code_formatting_style === FOUR_SPACES_INDENT;
if (!hasNewLine) {
if (selValue.length === 0 && isBlankLine) {
if (isFourSpacesIndent) {
const example = I18n.t(`composer.code_text`);
this.set("value", `${sel.pre} ${example}${sel.post}`);
return this.selectText(sel.pre.length + 4, example.length);
} else {
return this.applySurround(sel, "```\n", "\n```", "paste_code_text");
}
} else {
return this.applySurround(sel, "`", "`", "code_title");
}
} else {
if (!hasNewLine) {
if (selValue.length === 0 && isBlankLine) {
if (isFourSpacesIndent) {
return this.applySurround(sel, " ", "", "code_text");
const example = I18n.t(`composer.code_text`);
this.set("value", `${sel.pre} ${example}${sel.post}`);
return this.selectText(sel.pre.length + 4, example.length);
} else {
const preNewline = sel.pre[-1] !== "\n" && sel.pre !== "" ? "\n" : "";
const postNewline = sel.post[0] !== "\n" ? "\n" : "";
return this.addText(
sel,
`${preNewline}\`\`\`\n${sel.value}\n\`\`\`${postNewline}`
);
return this.applySurround(sel, "```\n", "\n```", "paste_code_text");
}
} else {
return this.applySurround(sel, "`", "`", "code_title");
}
},
} else {
if (isFourSpacesIndent) {
return this.applySurround(sel, " ", "", "code_text");
} else {
const preNewline = sel.pre[-1] !== "\n" && sel.pre !== "" ? "\n" : "";
const postNewline = sel.post[0] !== "\n" ? "\n" : "";
return this.addText(
sel,
`${preNewline}\`\`\`\n${sel.value}\n\`\`\`${postNewline}`
);
}
}
}
insertCurrentTime() {
const sel = this.getSelected("", { lineVal: true });
const timezone = this.currentUser.user_option.timezone;
const time = moment().format("HH:mm:ss");
const date = moment().format("YYYY-MM-DD");
@action
insertCurrentTime() {
const sel = this.getSelected("", { lineVal: true });
const timezone = this.currentUser.user_option.timezone;
const time = moment().format("HH:mm:ss");
const date = moment().format("YYYY-MM-DD");
this.addText(sel, `[date=${date} time=${time} timezone="${timezone}"]`);
},
this.addText(sel, `[date=${date} time=${time} timezone="${timezone}"]`);
}
focusIn() {
this.set("isEditorFocused", true);
},
@action
handleFocusIn() {
this.set("isEditorFocused", true);
}
focusOut() {
this.set("isEditorFocused", false);
},
},
@action
handleFocusOut() {
this.set("isEditorFocused", false);
}
_disablePreviewTabIndex() {
const observer = new MutationObserver(function () {
@ -930,5 +934,5 @@ export default Component.extend(TextareaTextManipulation, {
});
return observer;
},
});
}
}

View File

@ -4,23 +4,26 @@ import { action } from "@ember/object";
import { dependentKeyCompat } from "@ember/object/compat";
import { service } from "@ember/service";
import { htmlSafe } from "@ember/template";
import { tagName } from "@ember-decorators/component";
import { setting } from "discourse/lib/computed";
import { filterTypeForMode } from "discourse/lib/filter-mode";
import { NotificationLevels } from "discourse/lib/notification-levels";
import NavItem from "discourse/models/nav-item";
import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend({
router: service(),
dialog: service(),
tagName: "",
filterMode: tracked(),
fixedCategoryPositions: setting("fixed_category_positions"),
@tagName("")
export default class DNavigation extends Component {
@service router;
@service dialog;
@tracked filterMode;
@setting("fixed_category_positions") fixedCategoryPositions;
@dependentKeyCompat
get filterType() {
return filterTypeForMode(this.filterMode);
},
}
// Should be a `readOnly` instead but some themes/plugins still pass
// the `categories` property into this component
@ -42,12 +45,12 @@ export default Component.extend({
}
return categories;
},
}
@discourseComputed("category")
showCategoryNotifications(category) {
return category && this.currentUser;
},
}
@discourseComputed("category.notification_level")
categoryNotificationLevel(notificationLevel) {
@ -60,20 +63,20 @@ export default Component.extend({
} else {
return notificationLevel;
}
},
}
// don't show tag notification menu on tag intersections
@discourseComputed("tagNotification", "additionalTags")
showTagNotifications(tagNotification, additionalTags) {
return tagNotification && !additionalTags;
},
}
@discourseComputed("category", "createTopicDisabled")
categoryReadOnlyBanner(category, createTopicDisabled) {
if (category && this.currentUser && createTopicDisabled) {
return category.read_only_banner;
}
},
}
@discourseComputed(
"createTopicDisabled",
@ -95,7 +98,7 @@ export default Component.extend({
return false;
}
return createTopicDisabled;
},
}
@discourseComputed("categoryReadOnlyBanner", "hasDraft")
createTopicClass(categoryReadOnlyBanner, hasDraft) {
@ -106,20 +109,22 @@ export default Component.extend({
classNames.push("disabled");
}
return classNames.join(" ");
},
}
@discourseComputed("hasDraft")
createTopicLabel(hasDraft) {
return hasDraft ? "topic.open_draft" : "topic.create";
},
}
@discourseComputed("category.can_edit")
showCategoryEdit: (canEdit) => canEdit,
showCategoryEdit(canEdit) {
return canEdit;
}
@discourseComputed("additionalTags", "category", "tag.id")
showToggleInfo(additionalTags, category, tagId) {
return !additionalTags && !category && tagId !== "none";
},
}
@discourseComputed(
"filterType",
@ -145,12 +150,12 @@ export default Component.extend({
siteSettings: this.siteSettings,
skipCategoriesNavItem,
});
},
}
@discourseComputed("filterType")
notCategoriesRoute(filterType) {
return filterType !== "categories";
},
}
@action
async changeTagNotificationLevel(notificationLevel) {
@ -169,30 +174,31 @@ export default Component.extend({
muted_tags: payload.muted_tags,
regular_tags: payload.regular_tags,
});
},
}
actions: {
changeCategoryNotificationLevel(notificationLevel) {
this.category.setNotification(notificationLevel);
},
@action
changeCategoryNotificationLevel(notificationLevel) {
this.category.setNotification(notificationLevel);
}
selectCategoryAdminDropdownAction(actionId) {
switch (actionId) {
case "create":
this.createCategory();
break;
case "reorder":
this.reorderCategories();
break;
}
},
@action
selectCategoryAdminDropdownAction(actionId) {
switch (actionId) {
case "create":
this.createCategory();
break;
case "reorder":
this.reorderCategories();
break;
}
}
clickCreateTopicButton() {
if (this.categoryReadOnlyBanner && !this.hasDraft) {
this.dialog.alert({ message: htmlSafe(this.categoryReadOnlyBanner) });
} else {
this.createTopic();
}
},
},
});
@action
clickCreateTopicButton() {
if (this.categoryReadOnlyBanner && !this.hasDraft) {
this.dialog.alert({ message: htmlSafe(this.categoryReadOnlyBanner) });
} else {
this.createTopic();
}
}
}

View File

@ -1,5 +1,5 @@
import { TextArea } from "@ember/legacy-built-in-components";
import { attributeBindings } from "@ember-decorators/component";
export default TextArea.extend({
attributeBindings: ["aria-label"],
});
@attributeBindings("aria-label")
export default class DTextarea extends TextArea {}

View File

@ -1,10 +1,12 @@
/* global Pikaday:true */
import Component from "@ember/component";
import { action } from "@ember/object";
import { action, computed } from "@ember/object";
import { schedule } from "@ember/runloop";
import { classNames } from "@ember-decorators/component";
import { on } from "@ember-decorators/object";
import { Promise } from "rsvp";
import loadScript from "discourse/lib/load-script";
import discourseComputed, { on } from "discourse-common/utils/decorators";
import discourseComputed from "discourse-common/utils/decorators";
import I18n from "discourse-i18n";
function isInputDateSupported() {
@ -15,24 +17,23 @@ function isInputDateSupported() {
return input.value !== value;
}
export default Component.extend({
classNames: ["d-date-input"],
date: null,
_picker: null,
@classNames("d-date-input")
export default class DateInput extends Component {
date = null;
useNativePicker = isInputDateSupported();
_picker = null;
@discourseComputed("site.mobileView")
inputType() {
return this.useNativePicker ? "date" : "text";
},
useNativePicker: isInputDateSupported(),
}
click(event) {
event.stopPropagation();
},
}
didInsertElement() {
this._super(...arguments);
super.didInsertElement(...arguments);
schedule("afterRender", () => {
if (!this.element || this.isDestroying || this.isDestroying) {
@ -58,10 +59,10 @@ export default Component.extend({
}
});
});
},
}
didUpdateAttrs() {
this._super(...arguments);
super.didUpdateAttrs(...arguments);
if (this._picker && this.date) {
const parsedDate =
@ -81,7 +82,7 @@ export default Component.extend({
if (this._picker && !this.date) {
this._picker.setDate(null);
}
},
}
_loadPikadayPicker(container) {
return loadScript("/javascripts/pikaday.js").then(() => {
@ -107,7 +108,7 @@ export default Component.extend({
return new Pikaday({ ...defaultOptions, ...this._opts() });
});
},
}
_loadNativePicker(container) {
const wrapper = container || this.element;
@ -131,7 +132,7 @@ export default Component.extend({
}
return Promise.resolve(picker);
},
}
_handleSelection(value) {
if (!this.element || this.isDestroying || this.isDestroyed) {
@ -141,7 +142,7 @@ export default Component.extend({
if (this.onChange) {
this.onChange(value ? moment(value) : null);
}
},
}
@on("willDestroyElement")
_destroy() {
@ -149,26 +150,23 @@ export default Component.extend({
this._picker.destroy();
this._picker = null;
}
},
}
@discourseComputed("_placeholder")
placeholder: {
get(_placeholder) {
return _placeholder || I18n.t("dates.placeholder");
},
@computed("_placeholder")
get placeholder() {
return this._placeholder || I18n.t("dates.placeholder");
}
set(value) {
this.set("_placeholder", value);
return value;
},
},
set placeholder(value) {
this.set("_placeholder", value);
}
_opts() {
return null;
},
}
@action
onChangeDate(event) {
this._handleSelection(event.target.value);
},
});
}
}

View File

@ -1,11 +1,11 @@
import DatePicker from "discourse/components/date-picker";
export default DatePicker.extend({
export default class DatePickerFuture extends DatePicker {
_opts() {
return {
defaultDate: this.defaultDate || moment().add(1, "day").toDate(),
setDefaultDate: !!this.defaultDate,
minDate: this.minDate || moment().toDate(),
};
},
});
}
}

View File

@ -1,6 +1,6 @@
import DatePicker from "discourse/components/date-picker";
export default DatePicker.extend({
export default class DatePickerPast extends DatePicker {
_opts() {
return {
defaultDate:
@ -8,5 +8,5 @@ export default DatePicker.extend({
setDefaultDate: !!this.defaultDate,
maxDate: new Date(),
};
},
});
}
}

View File

@ -1,21 +1,24 @@
import Component from "@ember/component";
import { schedule } from "@ember/runloop";
/* global Pikaday:true */
import Component from "@ember/component";
import { computed } from "@ember/object";
import { schedule } from "@ember/runloop";
import { classNames } from "@ember-decorators/component";
import { on } from "@ember-decorators/object";
import loadScript from "discourse/lib/load-script";
import discourseComputed, { on } from "discourse-common/utils/decorators";
import discourseComputed from "discourse-common/utils/decorators";
import I18n from "discourse-i18n";
const DATE_FORMAT = "YYYY-MM-DD";
export default Component.extend({
classNames: ["date-picker-wrapper"],
_picker: null,
value: null,
@classNames("date-picker-wrapper")
export default class DatePicker extends Component {
value = null;
_picker = null;
@discourseComputed("site.mobileView")
inputType(mobileView) {
return mobileView ? "date" : "text";
},
}
@on("didInsertElement")
_loadDatePicker() {
@ -25,7 +28,7 @@ export default Component.extend({
const container = document.getElementById(this.containerId);
this._loadPikadayPicker(container);
}
},
}
_loadPikadayPicker(container) {
loadScript("/javascripts/pikaday.js").then(() => {
@ -49,7 +52,7 @@ export default Component.extend({
this._picker = new Pikaday(Object.assign(options, this._opts()));
});
});
},
}
_loadNativePicker() {
const picker = this.element.querySelector("input.date-picker");
@ -61,7 +64,7 @@ export default Component.extend({
/* do nothing for native */
};
this._picker = picker;
},
}
_handleSelection(value) {
const formattedDate = moment(value).format(DATE_FORMAT);
@ -73,7 +76,7 @@ export default Component.extend({
if (this.onSelect) {
this.onSelect(formattedDate);
}
},
}
@on("willDestroyElement")
_destroy() {
@ -81,21 +84,18 @@ export default Component.extend({
this._picker.destroy();
this._picker = null;
}
},
}
@discourseComputed("_placeholder")
placeholder: {
get(_placeholder) {
return _placeholder || I18n.t("dates.placeholder");
},
@computed("_placeholder")
get placeholder() {
return this._placeholder || I18n.t("dates.placeholder");
}
set(value) {
this.set("_placeholder", value);
return value;
},
},
set placeholder(value) {
this.set("_placeholder", value);
}
_opts() {
return null;
},
});
}
}

View File

@ -1,16 +1,17 @@
import Component from "@ember/component";
import { action } from "@ember/object";
import { classNames } from "@ember-decorators/component";
export default Component.extend({
classNames: ["d-date-time-input-range"],
from: null,
to: null,
onChangeTo: null,
onChangeFrom: null,
toTimeFirst: false,
showToTime: true,
showFromTime: true,
clearable: false,
@classNames("d-date-time-input-range")
export default class DateTimeInputRange extends Component {
from = null;
to = null;
onChangeTo = null;
onChangeFrom = null;
toTimeFirst = false;
showToTime = true;
showFromTime = true;
clearable = false;
@action
onChangeRanges(options, value) {
@ -42,5 +43,5 @@ export default Component.extend({
const newState = { ...state, ...diff };
this.onChange(newState);
}
},
});
}
}

View File

@ -1,25 +1,28 @@
import Component from "@ember/component";
import { action, computed } from "@ember/object";
import { classNames } from "@ember-decorators/component";
export default Component.extend({
classNames: ["d-date-time-input"],
date: null,
relativeDate: null,
showTime: true,
clearable: false,
@classNames("d-date-time-input")
export default class DateTimeInput extends Component {
date = null;
relativeDate = null;
showTime = true;
clearable = false;
hours: computed("date", "showTime", function () {
@computed("date", "showTime")
get hours() {
return this.date && this.get("showTime") ? this.date.hours() : null;
}),
}
minutes: computed("date", "showTime", function () {
@computed("date", "showTime")
get minutes() {
return this.date && this.get("showTime") ? this.date.minutes() : null;
}),
}
@action
onClear() {
this.onChange(null);
},
}
@action
onChangeTime(time) {
@ -43,7 +46,7 @@ export default Component.extend({
)
);
}
},
}
@action
onChangeDate(date) {
@ -64,10 +67,10 @@ export default Component.extend({
this.resolvedTimezone
)
);
},
}
@computed("timezone")
get resolvedTimezone() {
return this.timezone || moment.tz.guess();
},
});
}
}

View File

@ -1,10 +1,15 @@
import Component from "@ember/component";
import {
classNameBindings,
classNames,
tagName,
} from "@ember-decorators/component";
import { propertyEqual } from "discourse/lib/computed";
export default Component.extend({
tagName: "div",
classNames: ["directory-table__row"],
classNameBindings: ["me"],
me: propertyEqual("item.user.id", "currentUser.id"),
columns: null,
});
@tagName("div")
@classNames("directory-table__row")
@classNameBindings("me")
export default class DirectoryItem extends Component {
@propertyEqual("item.user.id", "currentUser.id") me;
columns = null;
}

View File

@ -1,11 +1,11 @@
import Component from "@ember/component";
import { action } from "@ember/object";
export default Component.extend({
_table: null,
export default class DirectoryTable extends Component {
_table = null;
didInsertElement() {
this._super(...arguments);
super.didInsertElement(...arguments);
this.setProperties({
_table: this.element.querySelector(".directory-table"),
_columnCount: this.showTimeRead
@ -14,7 +14,7 @@ export default Component.extend({
});
this._table.style.gridTemplateColumns = `minmax(15em, 3fr) repeat(${this._columnCount}, minmax(max-content, 1fr))`;
},
}
@action
setActiveHeader(header) {
@ -28,5 +28,5 @@ export default Component.extend({
if (scrollPixels > 0) {
this._table.scrollLeft = scrollPixels;
}
},
});
}
}

View File

@ -3,10 +3,10 @@ import { action } from "@ember/object";
import { readOnly } from "@ember/object/computed";
import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend({
hide: false,
export default class DiscourseBanner extends Component {
hide = false;
banner: readOnly("site.banner"),
@readOnly("site.banner") banner;
@discourseComputed("banner.html")
content(bannerHtml) {
@ -16,7 +16,7 @@ export default Component.extend({
el.removeAttribute("id");
});
return newDiv.innerHTML;
},
}
@discourseComputed("currentUser.dismissed_banner_key", "banner.key", "hide")
visible(dismissedBannerKey, bannerKey, hide) {
@ -31,7 +31,7 @@ export default Component.extend({
}
return !hide && bannerKey && dismissedBannerKey !== bannerKey;
},
}
@action
dismiss() {
@ -44,10 +44,10 @@ export default Component.extend({
value: this.get("banner.key"),
});
}
},
}
didInsertElement() {
this._super(...arguments);
super.didInsertElement(...arguments);
this.appEvents.trigger("decorate-non-stream-cooked-element", this.element);
},
});
}
}

View File

@ -1,16 +1,16 @@
import Component from "@ember/component";
import { tagName } from "@ember-decorators/component";
import discourseComputed from "discourse-common/utils/decorators";
import I18n from "discourse-i18n";
export default Component.extend({
tagName: "span",
@tagName("span")
export default class DiscourseLinkedText extends Component {
@discourseComputed("text", "textParams")
translatedText(text) {
if (text) {
return I18n.t(...arguments);
}
},
}
click(event) {
if (event.target.tagName.toUpperCase() === "A") {
@ -18,5 +18,5 @@ export default Component.extend({
}
return false;
},
});
}
}

View File

@ -1,5 +1,6 @@
import Component from "@ember/component";
import { classNames, tagName } from "@ember-decorators/component";
let componentArgs = { tagName: "div", classNames: ["discourse-root"] };
export default Component.extend(componentArgs);
@tagName("div")
@classNames("discourse-root")
export default class DiscourseRoot extends Component {}

View File

@ -1,19 +1,23 @@
import Component from "@ember/component";
import {
attributeBindings,
classNameBindings,
tagName,
} from "@ember-decorators/component";
import getURL from "discourse-common/lib/get-url";
import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend({
tagName: "a",
classNameBindings: [":discourse-tag", "style", "tagClass"],
attributeBindings: ["href"],
@tagName("a")
@classNameBindings(":discourse-tag", "style", "tagClass")
@attributeBindings("href")
export default class DiscourseTagBound extends Component {
@discourseComputed("tagRecord.id")
tagClass(tagRecordId) {
return "tag-" + tagRecordId;
},
}
@discourseComputed("tagRecord.id")
href(tagRecordId) {
return getURL("/tag/" + tagRecordId);
},
});
}
}

View File

@ -3,26 +3,28 @@ import { alias } from "@ember/object/computed";
import { getOwner } from "@ember/owner";
import { schedule, scheduleOnce } from "@ember/runloop";
import { isBlank } from "@ember/utils";
import { classNameBindings } from "@ember-decorators/component";
import { observes } from "@ember-decorators/object";
import $ from "jquery";
import ClickTrack from "discourse/lib/click-track";
import { highlightPost } from "discourse/lib/utilities";
import Scrolling from "discourse/mixins/scrolling";
import { bind, observes } from "discourse-common/utils/decorators";
import { bind } from "discourse-common/utils/decorators";
export default Component.extend(Scrolling, {
userFilters: alias("topic.userFilters"),
classNameBindings: [
"multiSelect",
"topic.archetype",
"topic.is_warning",
"topic.category.read_restricted:read_restricted",
"topic.deleted:deleted-topic",
],
menuVisible: true,
SHORT_POST: 1200,
@classNameBindings(
"multiSelect",
"topic.archetype",
"topic.is_warning",
"topic.category.read_restricted:read_restricted",
"topic.deleted:deleted-topic"
)
export default class DiscourseTopic extends Component.extend(Scrolling) {
@alias("topic.userFilters") userFilters;
@alias("topic.postStream") postStream;
postStream: alias("topic.postStream"),
dockAt: 0,
menuVisible = true;
SHORT_POST = 1200;
dockAt = 0;
@observes("enteredAt")
_enteredTopic() {
@ -33,22 +35,22 @@ export default Component.extend(Scrolling, {
schedule("afterRender", this.scrolled);
this.set("lastEnteredAt", this.enteredAt);
}
},
}
_highlightPost(postNumber, options = {}) {
if (isBlank(options.jump) || options.jump !== false) {
scheduleOnce("afterRender", null, highlightPost, postNumber);
}
},
}
init() {
this._super(...arguments);
super.init(...arguments);
this.appEvents.on("discourse:focus-changed", this, "gotFocus");
this.appEvents.on("post:highlight", this, "_highlightPost");
},
}
didInsertElement() {
this._super(...arguments);
super.didInsertElement(...arguments);
this.bindScrolling();
window.addEventListener("resize", this.scrolled);
@ -57,31 +59,31 @@ export default Component.extend(Scrolling, {
".cooked a, a.track-link",
(e) => ClickTrack.trackClick(e, getOwner(this))
);
},
}
willDestroy() {
this._super(...arguments);
super.willDestroy(...arguments);
// this happens after route exit, stuff could have trickled in
this.appEvents.off("discourse:focus-changed", this, "gotFocus");
this.appEvents.off("post:highlight", this, "_highlightPost");
},
}
willDestroyElement() {
this._super(...arguments);
super.willDestroyElement(...arguments);
this.unbindScrolling();
window.removeEventListener("resize", this.scrolled);
// Unbind link tracking
$(this.element).off("click.discourse-redirect", ".cooked a, a.track-link");
},
}
gotFocus(hasFocus) {
if (hasFocus) {
this.scrolled();
}
},
}
// The user has scrolled the window, or it is finished rendering and ready for processing.
@bind
@ -95,5 +97,5 @@ export default Component.extend(Scrolling, {
// Trigger a scrolled event
this.appEvents.trigger("topic:scrolled", offset);
},
});
}
}

View File

@ -1,39 +1,40 @@
import Component from "@ember/component";
import { action } from "@ember/object";
import { service } from "@ember/service";
import { classNames } from "@ember-decorators/component";
import { observes, on } from "@ember-decorators/object";
import $ from "jquery";
import { applyBehaviorTransformer } from "discourse/lib/transformer";
import LoadMore from "discourse/mixins/load-more";
import { observes, on } from "discourse-common/utils/decorators";
export default Component.extend(LoadMore, {
classNames: ["contents"],
eyelineSelector: ".topic-list-item",
appEvents: service(),
documentTitle: service(),
@classNames("contents")
export default class DiscoveryTopicsList extends Component.extend(LoadMore) {
@service appEvents;
@service documentTitle;
eyelineSelector = ".topic-list-item";
@on("didInsertElement")
_monitorTrackingState() {
this.stateChangeCallbackId = this.topicTrackingState.onStateChange(() =>
this._updateTrackingTopics()
);
},
}
@on("willDestroyElement")
_removeTrackingStateChangeMonitor() {
if (this.stateChangeCallbackId) {
this.topicTrackingState.offStateChange(this.stateChangeCallbackId);
}
},
}
_updateTrackingTopics() {
this.topicTrackingState.updateTopics(this.model.topics);
},
}
@observes("incomingCount")
_updateTitle() {
this.documentTitle.updateContextCount(this.incomingCount);
},
}
@action
loadMore() {
@ -58,5 +59,5 @@ export default Component.extend(LoadMore, {
},
{ model: this.model }
);
},
});
}
}