DEV: Convert core components to native class syntax (batch 9) (#28604)
Changes made using the ember-native-class-codemod, plus some manual tweaks
This commit is contained in:
parent
2e5502c417
commit
8cc6b214dd
|
@ -1,38 +1,40 @@
|
|||
import Component from "@ember/component";
|
||||
import { alias } from "@ember/object/computed";
|
||||
import { tagName } from "@ember-decorators/component";
|
||||
import UppyUploadMixin from "discourse/mixins/uppy-upload";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import I18n from "discourse-i18n";
|
||||
|
||||
export default Component.extend(UppyUploadMixin, {
|
||||
id: "uppy-backup-uploader",
|
||||
tagName: "span",
|
||||
type: "backup",
|
||||
@tagName("span")
|
||||
export default class UppyBackupUploader extends Component.extend(
|
||||
UppyUploadMixin
|
||||
) {
|
||||
id = "uppy-backup-uploader";
|
||||
type = "backup";
|
||||
uploadRootPath = "/admin/backups";
|
||||
uploadUrl = "/admin/backups/upload";
|
||||
|
||||
uploadRootPath: "/admin/backups",
|
||||
uploadUrl: "/admin/backups/upload",
|
||||
// local backups
|
||||
@alias("localBackupStorage") useChunkedUploads;
|
||||
|
||||
// direct s3 backups
|
||||
@discourseComputed("localBackupStorage")
|
||||
useMultipartUploadsIfAvailable(localBackupStorage) {
|
||||
return !localBackupStorage && this.siteSettings.enable_direct_s3_uploads;
|
||||
},
|
||||
|
||||
// local backups
|
||||
useChunkedUploads: alias("localBackupStorage"),
|
||||
}
|
||||
|
||||
@discourseComputed("uploading", "uploadProgress")
|
||||
uploadButtonText(uploading, progress) {
|
||||
return uploading
|
||||
? I18n.t("admin.backups.upload.uploading_progress", { progress })
|
||||
: I18n.t("admin.backups.upload.label");
|
||||
},
|
||||
}
|
||||
|
||||
validateUploadedFilesOptions() {
|
||||
return { skipValidation: true };
|
||||
},
|
||||
}
|
||||
|
||||
uploadDone(responseData) {
|
||||
this.done(responseData.file_name);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import { or } from "@ember/object/computed";
|
|||
import { next } from "@ember/runloop";
|
||||
import { htmlSafe } from "@ember/template";
|
||||
import { isEmpty } from "@ember/utils";
|
||||
import { classNames } from "@ember-decorators/component";
|
||||
import { on } from "@ember-decorators/object";
|
||||
import $ from "jquery";
|
||||
import lightbox, {
|
||||
cleanupLightboxes,
|
||||
|
@ -12,24 +14,26 @@ import lightbox, {
|
|||
import { authorizesOneOrMoreExtensions } from "discourse/lib/uploads";
|
||||
import UppyUploadMixin from "discourse/mixins/uppy-upload";
|
||||
import { getURLWithCDN } from "discourse-common/lib/get-url";
|
||||
import discourseComputed, { on } from "discourse-common/utils/decorators";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import I18n from "discourse-i18n";
|
||||
|
||||
export default Component.extend(UppyUploadMixin, {
|
||||
classNames: ["image-uploader"],
|
||||
disabled: or("notAllowed", "uploading", "processing"),
|
||||
@classNames("image-uploader")
|
||||
export default class UppyImageUploader extends Component.extend(
|
||||
UppyUploadMixin
|
||||
) {
|
||||
@or("notAllowed", "uploading", "processing") disabled;
|
||||
|
||||
@discourseComputed("siteSettings.enable_experimental_lightbox")
|
||||
experimentalLightboxEnabled(experimentalLightboxEnabled) {
|
||||
return experimentalLightboxEnabled;
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("disabled", "notAllowed")
|
||||
disabledReason(disabled, notAllowed) {
|
||||
if (disabled && notAllowed) {
|
||||
return I18n.t("post.errors.no_uploads_authorized");
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed(
|
||||
"currentUser.staff",
|
||||
|
@ -40,12 +44,12 @@ export default Component.extend(UppyUploadMixin, {
|
|||
this.currentUser?.staff,
|
||||
this.siteSettings
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("imageUrl", "placeholderUrl")
|
||||
showingPlaceholder(imageUrl, placeholderUrl) {
|
||||
return !imageUrl && placeholderUrl;
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("placeholderUrl")
|
||||
placeholderStyle(url) {
|
||||
|
@ -53,7 +57,7 @@ export default Component.extend(UppyUploadMixin, {
|
|||
return htmlSafe("");
|
||||
}
|
||||
return htmlSafe(`background-image: url(${url})`);
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("imageUrl")
|
||||
imageCDNURL(url) {
|
||||
|
@ -62,12 +66,12 @@ export default Component.extend(UppyUploadMixin, {
|
|||
}
|
||||
|
||||
return getURLWithCDN(url);
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("imageCDNURL")
|
||||
backgroundStyle(url) {
|
||||
return htmlSafe(`background-image: url(${url})`);
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("imageUrl")
|
||||
imageBaseName(imageUrl) {
|
||||
|
@ -75,17 +79,17 @@ export default Component.extend(UppyUploadMixin, {
|
|||
return;
|
||||
}
|
||||
return imageUrl.split("/").slice(-1)[0];
|
||||
},
|
||||
}
|
||||
|
||||
validateUploadedFilesOptions() {
|
||||
return { imagesOnly: true };
|
||||
},
|
||||
}
|
||||
|
||||
_uppyReady() {
|
||||
this._onPreProcessComplete(() => {
|
||||
this.set("processing", false);
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
uploadDone(upload) {
|
||||
this.setProperties({
|
||||
|
@ -103,7 +107,7 @@ export default Component.extend(UppyUploadMixin, {
|
|||
} else {
|
||||
this.set("imageUrl", upload.url);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@on("didRender")
|
||||
_applyLightbox() {
|
||||
|
@ -115,7 +119,7 @@ export default Component.extend(UppyUploadMixin, {
|
|||
} else {
|
||||
next(() => lightbox(this.element, this.siteSettings));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@on("willDestroyElement")
|
||||
_closeOnRemoval() {
|
||||
|
@ -126,26 +130,25 @@ export default Component.extend(UppyUploadMixin, {
|
|||
$.magnificPopup.instance.close();
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@action
|
||||
toggleLightbox() {
|
||||
$(this.element.querySelector("a.lightbox"))?.magnificPopup("open");
|
||||
},
|
||||
}
|
||||
|
||||
actions: {
|
||||
trash() {
|
||||
// uppy needs to be reset to allow for more uploads
|
||||
this._reset();
|
||||
@action
|
||||
trash() {
|
||||
// uppy needs to be reset to allow for more uploads
|
||||
this._reset();
|
||||
|
||||
// the value of the property used for imageUrl should be cleared
|
||||
// in this callback. this should be done in cases where imageUrl
|
||||
// is bound to a computed property of the parent component.
|
||||
if (this.onUploadDeleted) {
|
||||
this.onUploadDeleted();
|
||||
} else {
|
||||
this.setProperties({ imageUrl: null });
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
// the value of the property used for imageUrl should be cleared
|
||||
// in this callback. this should be done in cases where imageUrl
|
||||
// is bound to a computed property of the parent component.
|
||||
if (this.onUploadDeleted) {
|
||||
this.onUploadDeleted();
|
||||
} else {
|
||||
this.setProperties({ imageUrl: null });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import Component from "@ember/component";
|
||||
import { tagName } from "@ember-decorators/component";
|
||||
import autoGroupFlairForUser from "discourse/lib/avatar-flair";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
|
||||
export default Component.extend({
|
||||
tagName: "",
|
||||
|
||||
@tagName("")
|
||||
export default class UserAvatarFlair extends Component {
|
||||
@discourseComputed("user")
|
||||
flair(user) {
|
||||
if (!user || !user.flair_group_id) {
|
||||
|
@ -29,5 +29,5 @@ export default Component.extend({
|
|||
flairColor: autoFlairAttrs.flair_color,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -143,7 +143,7 @@
|
|||
{{#if this.showFilter}}
|
||||
<li>
|
||||
<DButton
|
||||
@action={{fn (action "filterPosts") this.user}}
|
||||
@action={{fn this.handleFilterPosts this.user}}
|
||||
@icon="filter"
|
||||
@translatedLabel={{this.filterPostsLabel}}
|
||||
class="btn-default"
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
import Component from "@ember/component";
|
||||
import EmberObject, { action, set } from "@ember/object";
|
||||
import EmberObject, { action, computed, set } from "@ember/object";
|
||||
import { alias, and, gt, gte, not, or } from "@ember/object/computed";
|
||||
import { dasherize } from "@ember/string";
|
||||
import { isEmpty } from "@ember/utils";
|
||||
import { propertyNotEqual, setting } from "discourse/lib/computed";
|
||||
import {
|
||||
attributeBindings,
|
||||
classNameBindings,
|
||||
classNames,
|
||||
} from "@ember-decorators/component";
|
||||
import { observes } from "@ember-decorators/object";
|
||||
import { setting } from "discourse/lib/computed";
|
||||
import { durationTiny } from "discourse/lib/formatter";
|
||||
import { wantsNewWindow } from "discourse/lib/intercept-click";
|
||||
import { prioritizeNameInUx } from "discourse/lib/settings";
|
||||
|
@ -14,85 +20,97 @@ import CardContentsBase from "discourse/mixins/card-contents-base";
|
|||
import CleansUp from "discourse/mixins/cleans-up";
|
||||
import User from "discourse/models/user";
|
||||
import { getURLWithCDN } from "discourse-common/lib/get-url";
|
||||
import discourseComputed, { observes } from "discourse-common/utils/decorators";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import I18n from "discourse-i18n";
|
||||
|
||||
export default Component.extend(CardContentsBase, CanCheckEmails, CleansUp, {
|
||||
elementId: "user-card",
|
||||
classNames: "user-card",
|
||||
avatarSelector: "[data-user-card]",
|
||||
avatarDataAttrKey: "userCard",
|
||||
mentionSelector: "a.mention",
|
||||
classNameBindings: [
|
||||
"visible:show",
|
||||
"showBadges",
|
||||
"user.card_background_upload_url::no-bg",
|
||||
"isFixed:fixed",
|
||||
"usernameClass",
|
||||
"primaryGroup",
|
||||
],
|
||||
attributeBindings: ["labelledBy:aria-labelledby"],
|
||||
allowBackgrounds: setting("allow_profile_backgrounds"),
|
||||
showBadges: setting("enable_badges"),
|
||||
@classNames("user-card")
|
||||
@classNameBindings(
|
||||
"visible:show",
|
||||
"showBadges",
|
||||
"user.card_background_upload_url::no-bg",
|
||||
"isFixed:fixed",
|
||||
"usernameClass",
|
||||
"primaryGroup"
|
||||
)
|
||||
@attributeBindings("labelledBy:aria-labelledby")
|
||||
export default class UserCardContents extends Component.extend(
|
||||
CardContentsBase,
|
||||
CanCheckEmails,
|
||||
CleansUp
|
||||
) {
|
||||
elementId = "user-card";
|
||||
avatarSelector = "[data-user-card]";
|
||||
avatarDataAttrKey = "userCard";
|
||||
mentionSelector = "a.mention";
|
||||
|
||||
postStream: alias("topic.postStream"),
|
||||
enoughPostsForFiltering: gte("topicPostCount", 2),
|
||||
showFilter: and(
|
||||
"viewingTopic",
|
||||
"postStream.hasNoFilters",
|
||||
"enoughPostsForFiltering"
|
||||
),
|
||||
showName: propertyNotEqual("user.name", "user.username"),
|
||||
hasUserFilters: gt("postStream.userFilters.length", 0),
|
||||
showMoreBadges: gt("moreBadgesCount", 0),
|
||||
showDelete: and("viewingAdmin", "showName", "user.canBeDeleted"),
|
||||
linkWebsite: not("user.isBasic"),
|
||||
@setting("allow_profile_backgrounds") allowBackgrounds;
|
||||
@setting("enable_badges") showBadges;
|
||||
@setting("display_local_time_in_user_card") showUserLocalTime;
|
||||
|
||||
@alias("topic.postStream") postStream;
|
||||
|
||||
@gte("topicPostCount", 2) enoughPostsForFiltering;
|
||||
|
||||
@and("viewingTopic", "postStream.hasNoFilters", "enoughPostsForFiltering")
|
||||
showFilter;
|
||||
|
||||
@gt("postStream.userFilters.length", 0) hasUserFilters;
|
||||
@gt("moreBadgesCount", 0) showMoreBadges;
|
||||
@and("viewingAdmin", "showName", "user.canBeDeleted") showDelete;
|
||||
@not("user.isBasic") linkWebsite;
|
||||
@or("user.suspend_reason", "user.bio_excerpt") isSuspendedOrHasBio;
|
||||
@and("user.staged", "canCheckEmails") showCheckEmail;
|
||||
|
||||
user = null;
|
||||
|
||||
// If inside a topic
|
||||
topicPostCount = null;
|
||||
|
||||
@and(
|
||||
"user.featured_topic",
|
||||
"siteSettings.allow_featured_topic_on_user_profiles"
|
||||
)
|
||||
showFeaturedTopic;
|
||||
|
||||
@computed("user.name", "user.username")
|
||||
get showName() {
|
||||
return this.user.name !== this.user.username;
|
||||
}
|
||||
|
||||
@discourseComputed("user")
|
||||
labelledBy(user) {
|
||||
return user ? "discourse-user-card-title" : null;
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("user")
|
||||
hasLocaleOrWebsite(user) {
|
||||
return user.location || user.website_name || this.userTimezone;
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("user.status")
|
||||
hasStatus() {
|
||||
return this.siteSettings.enable_user_status && this.user.status;
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("user.status.emoji")
|
||||
userStatusEmoji(emoji) {
|
||||
return emojiUnescape(escapeExpression(`:${emoji}:`));
|
||||
},
|
||||
|
||||
isSuspendedOrHasBio: or("user.suspend_reason", "user.bio_excerpt"),
|
||||
showCheckEmail: and("user.staged", "canCheckEmails"),
|
||||
|
||||
user: null,
|
||||
|
||||
// If inside a topic
|
||||
topicPostCount: null,
|
||||
|
||||
showFeaturedTopic: and(
|
||||
"user.featured_topic",
|
||||
"siteSettings.allow_featured_topic_on_user_profiles"
|
||||
),
|
||||
|
||||
showUserLocalTime: setting("display_local_time_in_user_card"),
|
||||
}
|
||||
|
||||
@discourseComputed("user.staff")
|
||||
staff: (isStaff) => (isStaff ? "staff" : ""),
|
||||
staff(isStaff) {
|
||||
return isStaff ? "staff" : "";
|
||||
}
|
||||
|
||||
@discourseComputed("user.trust_level")
|
||||
newUser: (trustLevel) => (trustLevel === 0 ? "new-user" : ""),
|
||||
newUser(trustLevel) {
|
||||
return trustLevel === 0 ? "new-user" : "";
|
||||
}
|
||||
|
||||
@discourseComputed("user.name")
|
||||
nameFirst(name) {
|
||||
return prioritizeNameInUx(name);
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("user")
|
||||
userTimezone(user) {
|
||||
|
@ -100,20 +118,22 @@ export default Component.extend(CardContentsBase, CanCheckEmails, CleansUp, {
|
|||
return;
|
||||
}
|
||||
return user.get("user_option.timezone");
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("userTimezone")
|
||||
formattedUserLocalTime(timezone) {
|
||||
return moment.tz(timezone).format(I18n.t("dates.time"));
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("username")
|
||||
usernameClass: (username) => (username ? `user-card-${username}` : ""),
|
||||
usernameClass(username) {
|
||||
return username ? `user-card-${username}` : "";
|
||||
}
|
||||
|
||||
@discourseComputed("username", "topicPostCount")
|
||||
filterPostsLabel(username, count) {
|
||||
return I18n.t("topic.filter_to", { username, count });
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("user.user_fields.@each.value")
|
||||
publicUserFields() {
|
||||
|
@ -130,25 +150,27 @@ export default Component.extend(CardContentsBase, CanCheckEmails, CleansUp, {
|
|||
})
|
||||
.compact();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("user.trust_level")
|
||||
removeNoFollow(trustLevel) {
|
||||
return trustLevel > 2 && !this.siteSettings.tl3_links_no_follow;
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("user.badge_count", "user.featured_user_badges.length")
|
||||
moreBadgesCount: (badgeCount, badgeLength) => badgeCount - badgeLength,
|
||||
moreBadgesCount(badgeCount, badgeLength) {
|
||||
return badgeCount - badgeLength;
|
||||
}
|
||||
|
||||
@discourseComputed("user.time_read", "user.recent_time_read")
|
||||
showRecentTimeRead(timeRead, recentTimeRead) {
|
||||
return timeRead !== recentTimeRead && recentTimeRead !== 0;
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("user.recent_time_read")
|
||||
recentTimeRead(recentTimeReadSeconds) {
|
||||
return durationTiny(recentTimeReadSeconds);
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("showRecentTimeRead", "user.time_read", "recentTimeRead")
|
||||
timeReadTooltip(showRecent, timeRead, recentTimeRead) {
|
||||
|
@ -162,7 +184,7 @@ export default Component.extend(CardContentsBase, CanCheckEmails, CleansUp, {
|
|||
time_read: durationTiny(timeRead),
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@observes("user.card_background_upload_url")
|
||||
addBackground() {
|
||||
|
@ -177,17 +199,17 @@ export default Component.extend(CardContentsBase, CanCheckEmails, CleansUp, {
|
|||
const url = this.get("user.card_background_upload_url");
|
||||
const bg = isEmpty(url) ? "" : `url(${getURLWithCDN(url)})`;
|
||||
this.element.style.backgroundImage = bg;
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("user.primary_group_name")
|
||||
primaryGroup(primaryGroup) {
|
||||
return `group-${primaryGroup}`;
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("user.profile_hidden", "user.inactive")
|
||||
contentHidden(profileHidden, inactive) {
|
||||
return profileHidden || inactive;
|
||||
},
|
||||
}
|
||||
|
||||
async _showCallback(username) {
|
||||
this.setProperties({ visible: true, loading: true });
|
||||
|
@ -215,7 +237,7 @@ export default Component.extend(CardContentsBase, CanCheckEmails, CleansUp, {
|
|||
} finally {
|
||||
this.set("loading", null);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_close() {
|
||||
this.user?.statusManager.stopTrackingStatus();
|
||||
|
@ -225,12 +247,12 @@ export default Component.extend(CardContentsBase, CanCheckEmails, CleansUp, {
|
|||
topicPostCount: null,
|
||||
});
|
||||
|
||||
this._super(...arguments);
|
||||
},
|
||||
super._close(...arguments);
|
||||
}
|
||||
|
||||
cleanUp() {
|
||||
this._close();
|
||||
},
|
||||
}
|
||||
|
||||
@action
|
||||
handleShowUser(event) {
|
||||
|
@ -243,36 +265,40 @@ export default Component.extend(CardContentsBase, CanCheckEmails, CleansUp, {
|
|||
// refactoring this to a glimmer component.
|
||||
this.showUser(this.user);
|
||||
this._close();
|
||||
},
|
||||
}
|
||||
|
||||
actions: {
|
||||
close() {
|
||||
this._close();
|
||||
},
|
||||
@action
|
||||
close() {
|
||||
this._close();
|
||||
}
|
||||
|
||||
composePM(user, post) {
|
||||
this._close();
|
||||
this.composePrivateMessage(user, post);
|
||||
},
|
||||
@action
|
||||
composePM(user, post) {
|
||||
this._close();
|
||||
this.composePrivateMessage(user, post);
|
||||
}
|
||||
|
||||
cancelFilter() {
|
||||
this.postStream.cancelFilter();
|
||||
this.postStream.refresh();
|
||||
this._close();
|
||||
},
|
||||
@action
|
||||
cancelFilter() {
|
||||
this.postStream.cancelFilter();
|
||||
this.postStream.refresh();
|
||||
this._close();
|
||||
}
|
||||
|
||||
filterPosts() {
|
||||
this.filterPosts(this.user);
|
||||
this._close();
|
||||
},
|
||||
@action
|
||||
handleFilterPosts() {
|
||||
this.filterPosts(this.user);
|
||||
this._close();
|
||||
}
|
||||
|
||||
deleteUser() {
|
||||
this.user.delete();
|
||||
this._close();
|
||||
},
|
||||
@action
|
||||
deleteUser() {
|
||||
this.user.delete();
|
||||
this._close();
|
||||
}
|
||||
|
||||
checkEmail(user) {
|
||||
user.checkEmail();
|
||||
},
|
||||
},
|
||||
});
|
||||
@action
|
||||
checkEmail(user) {
|
||||
user.checkEmail();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
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: "",
|
||||
|
||||
@tagName("")
|
||||
export default class UserFlagPercentage extends Component {
|
||||
@discourseComputed("percentage")
|
||||
showPercentage(percentage) {
|
||||
return percentage.total >= 3;
|
||||
},
|
||||
}
|
||||
|
||||
// We do a little logic to choose which icon to display and which text
|
||||
@discourseComputed("agreed", "disagreed", "ignored")
|
||||
|
@ -51,5 +51,5 @@ export default Component.extend({
|
|||
});
|
||||
|
||||
return result;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,34 +1,39 @@
|
|||
import Component from "@ember/component";
|
||||
import { alias } from "@ember/object/computed";
|
||||
import {
|
||||
attributeBindings,
|
||||
classNameBindings,
|
||||
} from "@ember-decorators/component";
|
||||
import { prioritizeNameInUx } from "discourse/lib/settings";
|
||||
import { userPath } from "discourse/lib/url";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
|
||||
export default Component.extend({
|
||||
classNameBindings: [":user-info", "size"],
|
||||
attributeBindings: ["data-username"],
|
||||
size: "small",
|
||||
"data-username": alias("user.username"),
|
||||
includeLink: true,
|
||||
includeAvatar: true,
|
||||
@classNameBindings(":user-info", "size")
|
||||
@attributeBindings("dataUsername:data-username")
|
||||
export default class UserInfo extends Component {
|
||||
size = "small";
|
||||
includeLink = true;
|
||||
includeAvatar = true;
|
||||
|
||||
@alias("user.username") dataUsername;
|
||||
|
||||
didInsertElement() {
|
||||
this._super(...arguments);
|
||||
super.didInsertElement(...arguments);
|
||||
this.user?.statusManager?.trackStatus();
|
||||
},
|
||||
}
|
||||
|
||||
willDestroyElement() {
|
||||
this._super(...arguments);
|
||||
super.willDestroyElement(...arguments);
|
||||
this.user?.statusManager?.stopTrackingStatus();
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("user.username")
|
||||
userPath(username) {
|
||||
return userPath(username);
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("user.name")
|
||||
nameFirst(name) {
|
||||
return prioritizeNameInUx(name);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import Component from "@ember/component";
|
||||
import { alias } from "@ember/object/computed";
|
||||
export default Component.extend({
|
||||
tagName: "a",
|
||||
attributeBindings: ["href", "data-user-card"],
|
||||
href: alias("user.path"),
|
||||
"data-user-card": alias("user.username"),
|
||||
});
|
||||
import { attributeBindings, tagName } from "@ember-decorators/component";
|
||||
|
||||
@tagName("a")
|
||||
@attributeBindings("href", "dataUserCard:data-user-card")
|
||||
export default class UserLink extends Component {
|
||||
@alias("user.path") href;
|
||||
@alias("user.username") dataUserCard;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import Component from "@ember/component";
|
||||
import { tagName } from "@ember-decorators/component";
|
||||
import { i18n } from "discourse/lib/computed";
|
||||
|
||||
export default Component.extend({
|
||||
tagName: "",
|
||||
dayLabel: i18n("day", "user.notification_schedule.%@"),
|
||||
});
|
||||
@tagName("")
|
||||
export default class UserNotificationScheduleDay extends Component {
|
||||
@i18n("day", "user.notification_schedule.%@") dayLabel;
|
||||
}
|
||||
|
|
|
@ -13,41 +13,41 @@ const DAYS = [
|
|||
"sunday",
|
||||
];
|
||||
|
||||
const Day = EmberObject.extend({
|
||||
id: null,
|
||||
startTimeOptions: null,
|
||||
model: null,
|
||||
class Day extends EmberObject {
|
||||
id = null;
|
||||
startTimeOptions = null;
|
||||
model = null;
|
||||
|
||||
@action
|
||||
onChangeStartTime(val) {
|
||||
this.startingTimeChangedForDay(val);
|
||||
},
|
||||
}
|
||||
|
||||
@action
|
||||
onChangeEndTime(val) {
|
||||
this.set(`model.user_notification_schedule.day_${this.id}_end_time`, val);
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed(
|
||||
"model.user_notification_schedule.day_{0,1,2,3,4,5,6}_start_time"
|
||||
)
|
||||
startTimeValue(schedule) {
|
||||
return schedule[`day_${this.id}_start_time`];
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed(
|
||||
"model.user_notification_schedule.day_{0,1,2,3,4,5,6}_start_time"
|
||||
)
|
||||
endTimeOptions(schedule) {
|
||||
return this.buildEndTimeOptionsFor(schedule[`day_${this.id}_start_time`]);
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed(
|
||||
"model.user_notification_schedule.day_{0,1,2,3,4,5,6}_end_time"
|
||||
)
|
||||
endTimeValue(schedule) {
|
||||
return schedule[`day_${this.id}_end_time`];
|
||||
},
|
||||
}
|
||||
|
||||
startingTimeChangedForDay(val) {
|
||||
val = parseInt(val, 10);
|
||||
|
@ -61,7 +61,7 @@ const Day = EmberObject.extend({
|
|||
val + 30
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
buildEndTimeOptionsFor(startTime) {
|
||||
startTime = parseInt(startTime, 10);
|
||||
|
@ -72,14 +72,14 @@ const Day = EmberObject.extend({
|
|||
includeNone: false,
|
||||
showMidnight: true,
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default Component.extend({
|
||||
days: null,
|
||||
export default class UserNotificationSchedule extends Component {
|
||||
days = null;
|
||||
|
||||
didInsertElement() {
|
||||
this._super(...arguments);
|
||||
super.didInsertElement(...arguments);
|
||||
this.set(
|
||||
"startTimeOptions",
|
||||
this.buildTimeOptions(0, {
|
||||
|
@ -101,7 +101,7 @@ export default Component.extend({
|
|||
})
|
||||
);
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
buildTimeOptions(startAt, opts = { includeNone: false, showMidnight: true }) {
|
||||
let timeOptions = [];
|
||||
|
@ -135,5 +135,5 @@ export default Component.extend({
|
|||
});
|
||||
}
|
||||
return timeOptions;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import Component from "@ember/component";
|
||||
|
||||
export default Component.extend({});
|
||||
export default class UserProfileAvatar extends Component {}
|
||||
|
|
|
@ -1,39 +1,40 @@
|
|||
import Component from "@ember/component";
|
||||
import { computed } from "@ember/object";
|
||||
import { classNameBindings, tagName } from "@ember-decorators/component";
|
||||
import { propertyEqual } from "discourse/lib/computed";
|
||||
import { userPath } from "discourse/lib/url";
|
||||
import { actionDescription } from "discourse/widgets/post-small-action";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
|
||||
export default Component.extend({
|
||||
tagName: "li",
|
||||
@tagName("li")
|
||||
@classNameBindings(
|
||||
":user-stream-item",
|
||||
":item", // DEPRECATED: 'item' class
|
||||
"hidden",
|
||||
"item.deleted:deleted",
|
||||
"moderatorAction"
|
||||
)
|
||||
export default class UserStreamItem extends Component {
|
||||
@propertyEqual("item.post_type", "site.post_types.moderator_action")
|
||||
moderatorAction;
|
||||
|
||||
classNameBindings: [
|
||||
":user-stream-item",
|
||||
":item", // DEPRECATED: 'item' class
|
||||
"hidden",
|
||||
"item.deleted:deleted",
|
||||
"moderatorAction",
|
||||
],
|
||||
|
||||
hidden: computed("item.hidden", function () {
|
||||
return (
|
||||
this.get("item.hidden") && !(this.currentUser && this.currentUser.staff)
|
||||
);
|
||||
}),
|
||||
moderatorAction: propertyEqual(
|
||||
"item.post_type",
|
||||
"site.post_types.moderator_action"
|
||||
),
|
||||
actionDescription: actionDescription(
|
||||
@actionDescription(
|
||||
"item.action_code",
|
||||
"item.created_at",
|
||||
"item.action_code_who",
|
||||
"item.action_code_path"
|
||||
),
|
||||
)
|
||||
actionDescription;
|
||||
|
||||
@computed("item.hidden")
|
||||
get hidden() {
|
||||
return (
|
||||
this.get("item.hidden") && !(this.currentUser && this.currentUser.staff)
|
||||
);
|
||||
}
|
||||
|
||||
@discourseComputed("item.draft_username", "item.username")
|
||||
userUrl(draftUsername, username) {
|
||||
return userPath((draftUsername || username).toLowerCase());
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import Component from "@ember/component";
|
||||
import { on } from "@ember/object/evented";
|
||||
import { action } from "@ember/object";
|
||||
import { getOwner } from "@ember/owner";
|
||||
import { later } from "@ember/runloop";
|
||||
import { service } from "@ember/service";
|
||||
import { classNames, tagName } from "@ember-decorators/component";
|
||||
import { on } from "@ember-decorators/object";
|
||||
import $ from "jquery";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import ClickTrack from "discourse/lib/click-track";
|
||||
|
@ -13,13 +15,18 @@ import Draft from "discourse/models/draft";
|
|||
import Post from "discourse/models/post";
|
||||
import I18n from "discourse-i18n";
|
||||
|
||||
export default Component.extend(LoadMore, {
|
||||
tagName: "ul",
|
||||
dialog: service(),
|
||||
composer: service(),
|
||||
_lastDecoratedElement: null,
|
||||
@tagName("ul")
|
||||
@classNames("user-stream")
|
||||
export default class UserStream extends Component.extend(LoadMore) {
|
||||
@service dialog;
|
||||
@service composer;
|
||||
|
||||
_initialize: on("init", function () {
|
||||
loading = false;
|
||||
eyelineSelector = ".user-stream .item";
|
||||
_lastDecoratedElement = null;
|
||||
|
||||
@on("init")
|
||||
_initialize() {
|
||||
const filter = this.get("stream.filter");
|
||||
if (filter) {
|
||||
this.set("classNames", [
|
||||
|
@ -27,13 +34,10 @@ export default Component.extend(LoadMore, {
|
|||
"filter-" + filter.toString().replace(",", "-"),
|
||||
]);
|
||||
}
|
||||
}),
|
||||
}
|
||||
|
||||
loading: false,
|
||||
eyelineSelector: ".user-stream .item",
|
||||
classNames: ["user-stream"],
|
||||
|
||||
_inserted: on("didInsertElement", function () {
|
||||
@on("didInsertElement")
|
||||
_inserted() {
|
||||
$(this.element).on(
|
||||
"click.details-disabled",
|
||||
"details.disabled",
|
||||
|
@ -44,15 +48,16 @@ export default Component.extend(LoadMore, {
|
|||
});
|
||||
this._updateLastDecoratedElement();
|
||||
this.appEvents.trigger("decorate-non-stream-cooked-element", this.element);
|
||||
}),
|
||||
}
|
||||
|
||||
// This view is being removed. Shut down operations
|
||||
_destroyed: on("willDestroyElement", function () {
|
||||
@on("willDestroyElement")
|
||||
_destroyed() {
|
||||
$(this.element).off("click.details-disabled", "details.disabled");
|
||||
|
||||
// Unbind link tracking
|
||||
$(this.element).off("click.discourse-redirect", ".excerpt a");
|
||||
}),
|
||||
}
|
||||
|
||||
_updateLastDecoratedElement() {
|
||||
const nodes = this.element.querySelectorAll(".user-stream-item");
|
||||
|
@ -64,89 +69,88 @@ export default Component.extend(LoadMore, {
|
|||
return;
|
||||
}
|
||||
this._lastDecoratedElement = lastElement;
|
||||
},
|
||||
}
|
||||
|
||||
actions: {
|
||||
removeBookmark(userAction) {
|
||||
const stream = this.stream;
|
||||
Post.updateBookmark(userAction.get("post_id"), false)
|
||||
.then(() => {
|
||||
stream.remove(userAction);
|
||||
@action
|
||||
removeBookmark(userAction) {
|
||||
const stream = this.stream;
|
||||
Post.updateBookmark(userAction.get("post_id"), false)
|
||||
.then(() => {
|
||||
stream.remove(userAction);
|
||||
})
|
||||
.catch(popupAjaxError);
|
||||
}
|
||||
|
||||
@action
|
||||
resumeDraft(item) {
|
||||
if (this.composer.get("model.viewOpen")) {
|
||||
this.composer.close();
|
||||
}
|
||||
if (item.get("postUrl")) {
|
||||
DiscourseURL.routeTo(item.get("postUrl"));
|
||||
} else {
|
||||
Draft.get(item.draft_key)
|
||||
.then((d) => {
|
||||
const draft = d.draft || item.data;
|
||||
if (!draft) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.composer.open({
|
||||
draft,
|
||||
draftKey: item.draft_key,
|
||||
draftSequence: d.draft_sequence,
|
||||
});
|
||||
})
|
||||
.catch(popupAjaxError);
|
||||
},
|
||||
.catch((error) => {
|
||||
popupAjaxError(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
resumeDraft(item) {
|
||||
if (this.composer.get("model.viewOpen")) {
|
||||
this.composer.close();
|
||||
}
|
||||
if (item.get("postUrl")) {
|
||||
DiscourseURL.routeTo(item.get("postUrl"));
|
||||
} else {
|
||||
Draft.get(item.draft_key)
|
||||
.then((d) => {
|
||||
const draft = d.draft || item.data;
|
||||
if (!draft) {
|
||||
return;
|
||||
@action
|
||||
removeDraft(draft) {
|
||||
const stream = this.stream;
|
||||
|
||||
this.dialog.yesNoConfirm({
|
||||
message: I18n.t("drafts.remove_confirmation"),
|
||||
didConfirm: () => {
|
||||
Draft.clear(draft.draft_key, draft.sequence)
|
||||
.then(() => {
|
||||
stream.remove(draft);
|
||||
if (draft.draft_key === NEW_TOPIC_KEY) {
|
||||
this.currentUser.set("has_topic_draft", false);
|
||||
}
|
||||
|
||||
this.composer.open({
|
||||
draft,
|
||||
draftKey: item.draft_key,
|
||||
draftSequence: d.draft_sequence,
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
popupAjaxError(error);
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
removeDraft(draft) {
|
||||
const stream = this.stream;
|
||||
@action
|
||||
loadMore() {
|
||||
if (this.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.dialog.yesNoConfirm({
|
||||
message: I18n.t("drafts.remove_confirmation"),
|
||||
didConfirm: () => {
|
||||
Draft.clear(draft.draft_key, draft.sequence)
|
||||
.then(() => {
|
||||
stream.remove(draft);
|
||||
if (draft.draft_key === NEW_TOPIC_KEY) {
|
||||
this.currentUser.set("has_topic_draft", false);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
popupAjaxError(error);
|
||||
});
|
||||
},
|
||||
this.set("loading", true);
|
||||
const stream = this.stream;
|
||||
stream.findItems().then(() => {
|
||||
this.set("loading", false);
|
||||
|
||||
// The next elements are not rendered on the page yet, we need to
|
||||
// wait for that before trying to decorate them.
|
||||
later(() => {
|
||||
let element = this._lastDecoratedElement?.nextElementSibling;
|
||||
while (element) {
|
||||
this.trigger("user-stream:new-item-inserted", element);
|
||||
this.appEvents.trigger("decorate-non-stream-cooked-element", element);
|
||||
element = element.nextElementSibling;
|
||||
}
|
||||
this._updateLastDecoratedElement();
|
||||
});
|
||||
},
|
||||
|
||||
loadMore() {
|
||||
if (this.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.set("loading", true);
|
||||
const stream = this.stream;
|
||||
stream.findItems().then(() => {
|
||||
this.set("loading", false);
|
||||
|
||||
// The next elements are not rendered on the page yet, we need to
|
||||
// wait for that before trying to decorate them.
|
||||
later(() => {
|
||||
let element = this._lastDecoratedElement?.nextElementSibling;
|
||||
while (element) {
|
||||
this.trigger("user-stream:new-item-inserted", element);
|
||||
this.appEvents.trigger(
|
||||
"decorate-non-stream-cooked-element",
|
||||
element
|
||||
);
|
||||
element = element.nextElementSibling;
|
||||
}
|
||||
this._updateLastDecoratedElement();
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import Component from "@ember/component";
|
||||
import { tagName } from "@ember-decorators/component";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
|
||||
export default Component.extend({
|
||||
tagName: "",
|
||||
|
||||
@tagName("")
|
||||
export default class UserSummaryCategorySearch extends Component {
|
||||
@discourseComputed("user", "category")
|
||||
searchParams() {
|
||||
return `@${this.get("user.username")} #${this.get("category.slug")}`;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Component from "@ember/component";
|
||||
export default Component.extend({
|
||||
tagName: "li",
|
||||
});
|
||||
import { tagName } from "@ember-decorators/component";
|
||||
|
||||
@tagName("li")
|
||||
export default class UserSummaryTopic extends Component {}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import Component from "@ember/component";
|
||||
import { tagName } from "@ember-decorators/component";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
|
||||
// should be kept in sync with 'UserSummary::MAX_SUMMARY_RESULTS'
|
||||
const MAX_SUMMARY_RESULTS = 6;
|
||||
|
||||
export default Component.extend({
|
||||
tagName: "",
|
||||
|
||||
@tagName("")
|
||||
export default class UserSummaryTopicsList extends Component {
|
||||
@discourseComputed("items.length")
|
||||
hasMore(length) {
|
||||
return length >= MAX_SUMMARY_RESULTS;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Component from "@ember/component";
|
||||
export default Component.extend({
|
||||
tagName: "li",
|
||||
});
|
||||
import { tagName } from "@ember-decorators/component";
|
||||
|
||||
@tagName("li")
|
||||
export default class UserSummaryUser extends Component {}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import Component from "@ember/component";
|
||||
|
||||
export default Component.extend({});
|
||||
export default class UserSummaryUsersList extends Component {}
|
||||
|
|
Loading…
Reference in New Issue