mirror of
https://github.com/discourse/discourse.git
synced 2025-05-05 01:04:37 +08:00
DEV: Convert core components to native class syntax (batch 6) (#28598)
Changes made using the ember-native-class-codemod, plus some manual tweaks
This commit is contained in:
parent
77d4b3304e
commit
c4428715b5
@ -1,14 +1,14 @@
|
|||||||
import Component from "@ember/component";
|
import Component from "@ember/component";
|
||||||
|
import { tagName } from "@ember-decorators/component";
|
||||||
|
import { observes, on } from "@ember-decorators/object";
|
||||||
import highlightSearch from "discourse/lib/highlight-search";
|
import highlightSearch from "discourse/lib/highlight-search";
|
||||||
import { observes, on } from "discourse-common/utils/decorators";
|
|
||||||
|
|
||||||
export default Component.extend({
|
|
||||||
tagName: "span",
|
|
||||||
|
|
||||||
|
@tagName("span")
|
||||||
|
export default class HighlightSearch extends Component {
|
||||||
@on("didInsertElement")
|
@on("didInsertElement")
|
||||||
@observes("highlight")
|
@observes("highlight")
|
||||||
_highlightOnInsert() {
|
_highlightOnInsert() {
|
||||||
const term = this.highlight;
|
const term = this.highlight;
|
||||||
highlightSearch(this.element, term);
|
highlightSearch(this.element, term);
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
import { on } from "@ember-decorators/object";
|
||||||
import TextField from "discourse/components/text-field";
|
import TextField from "discourse/components/text-field";
|
||||||
import { on } from "discourse-common/utils/decorators";
|
|
||||||
|
|
||||||
export default TextField.extend({
|
export default class HoneypotInput extends TextField {
|
||||||
@on("init")
|
@on("init")
|
||||||
_init() {
|
_init() {
|
||||||
// Chrome autocomplete is buggy per:
|
// Chrome autocomplete is buggy per:
|
||||||
@ -13,5 +13,5 @@ export default TextField.extend({
|
|||||||
} else {
|
} else {
|
||||||
this.set("type", "password");
|
this.set("type", "password");
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
@ -4,12 +4,12 @@ import {
|
|||||||
shouldOpenInNewTab,
|
shouldOpenInNewTab,
|
||||||
} from "discourse/lib/click-track";
|
} from "discourse/lib/click-track";
|
||||||
|
|
||||||
export default Component.extend({
|
export default class HtmlWithLinks extends Component {
|
||||||
click(event) {
|
click(event) {
|
||||||
if (event?.target?.tagName === "A") {
|
if (event?.target?.tagName === "A") {
|
||||||
if (shouldOpenInNewTab(event.target.href)) {
|
if (shouldOpenInNewTab(event.target.href)) {
|
||||||
openLinkInNewTab(event, event.target);
|
openLinkInNewTab(event, event.target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
import Component from "@ember/component";
|
import Component from "@ember/component";
|
||||||
export default Component.extend({
|
import { action } from "@ember/object";
|
||||||
tagName: "div",
|
import { tagName } from "@ember-decorators/component";
|
||||||
items: null,
|
|
||||||
actions: {
|
@tagName("div")
|
||||||
removeIgnoredUser(item) {
|
export default class IgnoredUserListItem extends Component {
|
||||||
this.onRemoveIgnoredUser(item);
|
items = null;
|
||||||
},
|
|
||||||
},
|
@action
|
||||||
});
|
removeIgnoredUser(item) {
|
||||||
|
this.onRemoveIgnoredUser(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,22 +1,23 @@
|
|||||||
import Component from "@ember/component";
|
import Component from "@ember/component";
|
||||||
|
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";
|
||||||
import I18n from "discourse-i18n";
|
import I18n from "discourse-i18n";
|
||||||
|
|
||||||
export default Component.extend(UppyUploadMixin, {
|
@tagName("span")
|
||||||
type: "avatar",
|
export default class ImagesUploader extends Component.extend(UppyUploadMixin) {
|
||||||
tagName: "span",
|
type = "avatar";
|
||||||
|
|
||||||
@discourseComputed("uploadingOrProcessing")
|
@discourseComputed("uploadingOrProcessing")
|
||||||
uploadButtonText(uploadingOrProcessing) {
|
uploadButtonText(uploadingOrProcessing) {
|
||||||
return uploadingOrProcessing ? I18n.t("uploading") : I18n.t("upload");
|
return uploadingOrProcessing ? I18n.t("uploading") : I18n.t("upload");
|
||||||
},
|
}
|
||||||
|
|
||||||
validateUploadedFilesOptions() {
|
validateUploadedFilesOptions() {
|
||||||
return { imagesOnly: true };
|
return { imagesOnly: true };
|
||||||
},
|
}
|
||||||
|
|
||||||
uploadDone(upload) {
|
uploadDone(upload) {
|
||||||
this.done(upload);
|
this.done(upload);
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
@ -9,32 +9,44 @@ import Group from "discourse/models/group";
|
|||||||
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({
|
export default class InvitePanel extends Component {
|
||||||
tagName: null,
|
@readOnly("currentUser.staff") isStaff;
|
||||||
groupIds: null,
|
@readOnly("currentUser.admin") isAdmin;
|
||||||
allGroups: null,
|
@alias("inviteModel.id") topicId;
|
||||||
|
@equal("inviteModel.archetype", "private_message") isPM;
|
||||||
|
@and("isStaff", "siteSettings.must_approve_users") showApprovalMessage;
|
||||||
|
|
||||||
isStaff: readOnly("currentUser.staff"),
|
// eg: visible only to specific group members
|
||||||
isAdmin: readOnly("currentUser.admin"),
|
@and("invitingToTopic", "inviteModel.category.read_restricted")
|
||||||
|
isPrivateTopic;
|
||||||
|
|
||||||
|
// scope to allowed usernames
|
||||||
|
@alias("invitingToTopic") allowExistingMembers;
|
||||||
|
|
||||||
|
@i18n("invite.custom_message_placeholder") customMessagePlaceholder;
|
||||||
|
|
||||||
|
groupIds = null;
|
||||||
|
allGroups = null;
|
||||||
|
|
||||||
// invitee is either a user, group or email
|
// invitee is either a user, group or email
|
||||||
invitee: null,
|
invitee = null;
|
||||||
isInviteeGroup: false,
|
|
||||||
hasCustomMessage: false,
|
isInviteeGroup = false;
|
||||||
customMessage: null,
|
hasCustomMessage = false;
|
||||||
inviteIcon: "envelope",
|
customMessage = null;
|
||||||
invitingExistingUserToTopic: false,
|
inviteIcon = "envelope";
|
||||||
|
invitingExistingUserToTopic = false;
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this._super(...arguments);
|
super.init(...arguments);
|
||||||
this.setDefaultSelectedGroups();
|
this.setDefaultSelectedGroups();
|
||||||
this.setGroupOptions();
|
this.setGroupOptions();
|
||||||
},
|
}
|
||||||
|
|
||||||
willDestroyElement() {
|
willDestroyElement() {
|
||||||
this._super(...arguments);
|
super.willDestroyElement(...arguments);
|
||||||
this.reset();
|
this.reset();
|
||||||
},
|
}
|
||||||
|
|
||||||
@discourseComputed(
|
@discourseComputed(
|
||||||
"isAdmin",
|
"isAdmin",
|
||||||
@ -81,7 +93,7 @@ export default Component.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
}
|
||||||
|
|
||||||
@discourseComputed(
|
@discourseComputed(
|
||||||
"isAdmin",
|
"isAdmin",
|
||||||
@ -125,49 +137,36 @@ export default Component.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
}
|
||||||
|
|
||||||
@discourseComputed("inviteModel.saving")
|
@discourseComputed("inviteModel.saving")
|
||||||
buttonTitle(saving) {
|
buttonTitle(saving) {
|
||||||
return saving ? "topic.inviting" : "topic.invite_reply.action";
|
return saving ? "topic.inviting" : "topic.invite_reply.action";
|
||||||
},
|
}
|
||||||
|
|
||||||
// We are inviting to a topic if the topic isn't the current user.
|
// We are inviting to a topic if the topic isn't the current user.
|
||||||
// The current user would mean we are inviting to the forum in general.
|
// The current user would mean we are inviting to the forum in general.
|
||||||
@discourseComputed("inviteModel")
|
@discourseComputed("inviteModel")
|
||||||
invitingToTopic(inviteModel) {
|
invitingToTopic(inviteModel) {
|
||||||
return inviteModel !== this.currentUser;
|
return inviteModel !== this.currentUser;
|
||||||
},
|
}
|
||||||
|
|
||||||
@discourseComputed("inviteModel", "inviteModel.details.can_invite_via_email")
|
@discourseComputed("inviteModel", "inviteModel.details.can_invite_via_email")
|
||||||
canInviteViaEmail(inviteModel, canInviteViaEmail) {
|
canInviteViaEmail(inviteModel, canInviteViaEmail) {
|
||||||
return inviteModel === this.currentUser ? true : canInviteViaEmail;
|
return inviteModel === this.currentUser ? true : canInviteViaEmail;
|
||||||
},
|
}
|
||||||
|
|
||||||
@discourseComputed("isPM", "canInviteViaEmail")
|
@discourseComputed("isPM", "canInviteViaEmail")
|
||||||
showCopyInviteButton(isPM, canInviteViaEmail) {
|
showCopyInviteButton(isPM, canInviteViaEmail) {
|
||||||
return canInviteViaEmail && !isPM;
|
return canInviteViaEmail && !isPM;
|
||||||
},
|
}
|
||||||
|
|
||||||
topicId: alias("inviteModel.id"),
|
|
||||||
|
|
||||||
// eg: visible only to specific group members
|
|
||||||
isPrivateTopic: and(
|
|
||||||
"invitingToTopic",
|
|
||||||
"inviteModel.category.read_restricted"
|
|
||||||
),
|
|
||||||
|
|
||||||
isPM: equal("inviteModel.archetype", "private_message"),
|
|
||||||
|
|
||||||
// scope to allowed usernames
|
|
||||||
allowExistingMembers: alias("invitingToTopic"),
|
|
||||||
|
|
||||||
@discourseComputed("isAdmin", "inviteModel.group_users")
|
@discourseComputed("isAdmin", "inviteModel.group_users")
|
||||||
isGroupOwnerOrAdmin(isAdmin, groupUsers) {
|
isGroupOwnerOrAdmin(isAdmin, groupUsers) {
|
||||||
return (
|
return (
|
||||||
isAdmin || (groupUsers && groupUsers.some((groupUser) => groupUser.owner))
|
isAdmin || (groupUsers && groupUsers.some((groupUser) => groupUser.owner))
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
|
|
||||||
// Show Groups? (add invited user to private group)
|
// Show Groups? (add invited user to private group)
|
||||||
@discourseComputed(
|
@discourseComputed(
|
||||||
@ -192,12 +191,12 @@ export default Component.extend({
|
|||||||
!isPM &&
|
!isPM &&
|
||||||
(emailValid(invitee) || isPrivateTopic || !invitingToTopic)
|
(emailValid(invitee) || isPrivateTopic || !invitingToTopic)
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
|
|
||||||
@discourseComputed("invitee")
|
@discourseComputed("invitee")
|
||||||
showCustomMessage(invitee) {
|
showCustomMessage(invitee) {
|
||||||
return this.inviteModel === this.currentUser || emailValid(invitee);
|
return this.inviteModel === this.currentUser || emailValid(invitee);
|
||||||
},
|
}
|
||||||
|
|
||||||
// Instructional text for the modal.
|
// Instructional text for the modal.
|
||||||
@discourseComputed(
|
@discourseComputed(
|
||||||
@ -243,12 +242,12 @@ export default Component.extend({
|
|||||||
// inviting to forum
|
// inviting to forum
|
||||||
return I18n.t("topic.invite_reply.to_forum");
|
return I18n.t("topic.invite_reply.to_forum");
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
@discourseComputed("isPrivateTopic")
|
@discourseComputed("isPrivateTopic")
|
||||||
showGroupsClass(isPrivateTopic) {
|
showGroupsClass(isPrivateTopic) {
|
||||||
return isPrivateTopic ? "required" : "optional";
|
return isPrivateTopic ? "required" : "optional";
|
||||||
},
|
}
|
||||||
|
|
||||||
@discourseComputed("isPM", "invitee", "invitingExistingUserToTopic")
|
@discourseComputed("isPM", "invitee", "invitingExistingUserToTopic")
|
||||||
successMessage(isPM, invitee, invitingExistingUserToTopic) {
|
successMessage(isPM, invitee, invitingExistingUserToTopic) {
|
||||||
@ -265,7 +264,7 @@ export default Component.extend({
|
|||||||
} else {
|
} else {
|
||||||
return I18n.t("topic.invite_reply.success_username");
|
return I18n.t("topic.invite_reply.success_username");
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
@discourseComputed("isPM", "ajaxError")
|
@discourseComputed("isPM", "ajaxError")
|
||||||
errorMessage(isPM, ajaxError) {
|
errorMessage(isPM, ajaxError) {
|
||||||
@ -275,18 +274,14 @@ export default Component.extend({
|
|||||||
return isPM
|
return isPM
|
||||||
? I18n.t("topic.invite_private.error")
|
? I18n.t("topic.invite_private.error")
|
||||||
: I18n.t("topic.invite_reply.error");
|
: I18n.t("topic.invite_reply.error");
|
||||||
},
|
}
|
||||||
|
|
||||||
@discourseComputed("canInviteViaEmail")
|
@discourseComputed("canInviteViaEmail")
|
||||||
placeholderKey(canInviteViaEmail) {
|
placeholderKey(canInviteViaEmail) {
|
||||||
return canInviteViaEmail
|
return canInviteViaEmail
|
||||||
? "topic.invite_private.email_or_username_placeholder"
|
? "topic.invite_private.email_or_username_placeholder"
|
||||||
: "topic.invite_reply.username_placeholder";
|
: "topic.invite_reply.username_placeholder";
|
||||||
},
|
}
|
||||||
|
|
||||||
showApprovalMessage: and("isStaff", "siteSettings.must_approve_users"),
|
|
||||||
|
|
||||||
customMessagePlaceholder: i18n("invite.custom_message_placeholder"),
|
|
||||||
|
|
||||||
// Reset the modal to allow a new user to be invited.
|
// Reset the modal to allow a new user to be invited.
|
||||||
reset() {
|
reset() {
|
||||||
@ -305,17 +300,17 @@ export default Component.extend({
|
|||||||
finished: false,
|
finished: false,
|
||||||
inviteLink: null,
|
inviteLink: null,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
|
|
||||||
setDefaultSelectedGroups() {
|
setDefaultSelectedGroups() {
|
||||||
this.set("groupIds", []);
|
this.set("groupIds", []);
|
||||||
},
|
}
|
||||||
|
|
||||||
setGroupOptions() {
|
setGroupOptions() {
|
||||||
Group.findAll().then((groups) => {
|
Group.findAll().then((groups) => {
|
||||||
this.set("allGroups", groups.filterBy("automatic", false));
|
this.set("allGroups", groups.filterBy("automatic", false));
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
createInvite() {
|
createInvite() {
|
||||||
@ -367,7 +362,7 @@ export default Component.extend({
|
|||||||
})
|
})
|
||||||
.catch(onerror);
|
.catch(onerror);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
generateInviteLink() {
|
generateInviteLink() {
|
||||||
@ -401,7 +396,7 @@ export default Component.extend({
|
|||||||
}
|
}
|
||||||
model.setProperties({ saving: false, error: true });
|
model.setProperties({ saving: false, error: true });
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
showCustomMessageBox() {
|
showCustomMessageBox() {
|
||||||
@ -421,14 +416,14 @@ export default Component.extend({
|
|||||||
} else {
|
} else {
|
||||||
this.set("customMessage", null);
|
this.set("customMessage", null);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
searchContact() {
|
searchContact() {
|
||||||
getNativeContact(this.capabilities, ["email"], false).then((result) => {
|
getNativeContact(this.capabilities, ["email"], false).then((result) => {
|
||||||
this.set("invitee", result[0].email[0]);
|
this.set("invitee", result[0].email[0]);
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
updateInvitee(selected, content) {
|
updateInvitee(selected, content) {
|
||||||
@ -448,5 +443,5 @@ export default Component.extend({
|
|||||||
isInviteeGroup: false,
|
isInviteeGroup: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
import Component from "@ember/component";
|
import Component from "@ember/component";
|
||||||
|
import {
|
||||||
|
attributeBindings,
|
||||||
|
classNameBindings,
|
||||||
|
} from "@ember-decorators/component";
|
||||||
import {
|
import {
|
||||||
navigateToTopic,
|
navigateToTopic,
|
||||||
showEntrance,
|
showEntrance,
|
||||||
} from "discourse/components/topic-list-item";
|
} from "discourse/components/topic-list-item";
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
|
|
||||||
export default Component.extend({
|
@attributeBindings("topic.id:data-topic-id")
|
||||||
attributeBindings: ["topic.id:data-topic-id"],
|
@classNameBindings(":latest-topic-list-item", "unboundClassNames")
|
||||||
classNameBindings: [":latest-topic-list-item", "unboundClassNames"],
|
export default class LatestTopicListItem extends Component {
|
||||||
|
showEntrance = showEntrance;
|
||||||
showEntrance,
|
navigateToTopic = navigateToTopic;
|
||||||
navigateToTopic,
|
|
||||||
|
|
||||||
click(e) {
|
click(e) {
|
||||||
// for events undefined has a different meaning than false
|
// for events undefined has a different meaning than false
|
||||||
@ -19,10 +22,10 @@ export default Component.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this.unhandledRowClick(e, this.topic);
|
return this.unhandledRowClick(e, this.topic);
|
||||||
},
|
}
|
||||||
|
|
||||||
// Can be overwritten by plugins to handle clicks on other parts of the row
|
// Can be overwritten by plugins to handle clicks on other parts of the row
|
||||||
unhandledRowClick() {},
|
unhandledRowClick() {}
|
||||||
|
|
||||||
@discourseComputed("topic")
|
@discourseComputed("topic")
|
||||||
unboundClassNames(topic) {
|
unboundClassNames(topic) {
|
||||||
@ -45,5 +48,5 @@ export default Component.extend({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return classes.join(" ");
|
return classes.join(" ");
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
@ -2,8 +2,8 @@ import Component from "@ember/component";
|
|||||||
import { schedule } from "@ember/runloop";
|
import { schedule } from "@ember/runloop";
|
||||||
import $ from "jquery";
|
import $ from "jquery";
|
||||||
|
|
||||||
export default Component.extend({
|
export default class LinkToInput extends Component {
|
||||||
showInput: false,
|
showInput = false;
|
||||||
|
|
||||||
click() {
|
click() {
|
||||||
this.onClick();
|
this.onClick();
|
||||||
@ -13,5 +13,5 @@ export default Component.extend({
|
|||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
@ -2,10 +2,10 @@ import Component from "@ember/component";
|
|||||||
import { getOwner } from "@ember/owner";
|
import { getOwner } from "@ember/owner";
|
||||||
import ClickTrack from "discourse/lib/click-track";
|
import ClickTrack from "discourse/lib/click-track";
|
||||||
|
|
||||||
export default Component.extend({
|
export default class LinksRedirect extends Component {
|
||||||
click(event) {
|
click(event) {
|
||||||
if (event?.target?.tagName === "A") {
|
if (event?.target?.tagName === "A") {
|
||||||
return ClickTrack.trackClick(event, getOwner(this));
|
return ClickTrack.trackClick(event, getOwner(this));
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import Component from "@ember/component";
|
import Component from "@ember/component";
|
||||||
|
import { action } from "@ember/object";
|
||||||
import LoadMore from "discourse/mixins/load-more";
|
import LoadMore from "discourse/mixins/load-more";
|
||||||
|
|
||||||
export default Component.extend(LoadMore, {
|
export default class LoadMoreComponent extends Component.extend(LoadMore) {
|
||||||
init() {
|
init() {
|
||||||
this._super(...arguments);
|
super.init(...arguments);
|
||||||
|
|
||||||
this.set("eyelineSelector", this.selector);
|
this.set("eyelineSelector", this.selector);
|
||||||
},
|
}
|
||||||
|
|
||||||
actions: {
|
@action
|
||||||
loadMore() {
|
loadMore() {
|
||||||
this.action();
|
this.action();
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
});
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import Component from "@ember/component";
|
import Component from "@ember/component";
|
||||||
|
import { classNameBindings } from "@ember-decorators/component";
|
||||||
import { isWebauthnSupported } from "discourse/lib/webauthn";
|
import { isWebauthnSupported } from "discourse/lib/webauthn";
|
||||||
import { findAll } from "discourse/models/login-method";
|
import { findAll } from "discourse/models/login-method";
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
|
|
||||||
export default Component.extend({
|
@classNameBindings("hidden")
|
||||||
elementId: "login-buttons",
|
export default class LoginButtons extends Component {
|
||||||
classNameBindings: ["hidden"],
|
elementId = "login-buttons";
|
||||||
|
|
||||||
@discourseComputed(
|
@discourseComputed(
|
||||||
"buttons.length",
|
"buttons.length",
|
||||||
@ -14,12 +15,12 @@ export default Component.extend({
|
|||||||
)
|
)
|
||||||
hidden(buttonsCount, showLoginWithEmailLink, showPasskeysButton) {
|
hidden(buttonsCount, showLoginWithEmailLink, showPasskeysButton) {
|
||||||
return buttonsCount === 0 && !showLoginWithEmailLink && !showPasskeysButton;
|
return buttonsCount === 0 && !showLoginWithEmailLink && !showPasskeysButton;
|
||||||
},
|
}
|
||||||
|
|
||||||
@discourseComputed
|
@discourseComputed
|
||||||
buttons() {
|
buttons() {
|
||||||
return findAll();
|
return findAll();
|
||||||
},
|
}
|
||||||
|
|
||||||
@discourseComputed
|
@discourseComputed
|
||||||
showPasskeysButton() {
|
showPasskeysButton() {
|
||||||
@ -29,5 +30,5 @@ export default Component.extend({
|
|||||||
this.context === "login" &&
|
this.context === "login" &&
|
||||||
isWebauthnSupported()
|
isWebauthnSupported()
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
import Component from "@ember/component";
|
import Component from "@ember/component";
|
||||||
|
import { classNameBindings, tagName } from "@ember-decorators/component";
|
||||||
import { showEntrance } from "discourse/components/topic-list-item";
|
import { showEntrance } from "discourse/components/topic-list-item";
|
||||||
|
|
||||||
export default Component.extend({
|
@tagName("tr")
|
||||||
tagName: "tr",
|
@classNameBindings(":category-topic-link", "topic.archived", "topic.visited")
|
||||||
classNameBindings: [
|
export default class MobileCategoryTopic extends Component {
|
||||||
":category-topic-link",
|
click = showEntrance;
|
||||||
"topic.archived",
|
}
|
||||||
"topic.visited",
|
|
||||||
],
|
|
||||||
click: showEntrance,
|
|
||||||
});
|
|
||||||
|
@ -2,10 +2,16 @@ import Component from "@ember/component";
|
|||||||
import { action } from "@ember/object";
|
import { action } from "@ember/object";
|
||||||
import { next } from "@ember/runloop";
|
import { next } from "@ember/runloop";
|
||||||
import { service } from "@ember/service";
|
import { service } from "@ember/service";
|
||||||
|
import { classNames, tagName } from "@ember-decorators/component";
|
||||||
|
import { on } from "@ember-decorators/object";
|
||||||
import $ from "jquery";
|
import $ from "jquery";
|
||||||
import { on } from "discourse-common/utils/decorators";
|
|
||||||
|
|
||||||
export default Component.extend({
|
@tagName("ul")
|
||||||
|
@classNames("mobile-nav")
|
||||||
|
export default class MobileNav extends Component {
|
||||||
|
@service router;
|
||||||
|
selectedHtml = null;
|
||||||
|
|
||||||
@on("init")
|
@on("init")
|
||||||
_init() {
|
_init() {
|
||||||
if (this.site.desktopView) {
|
if (this.site.desktopView) {
|
||||||
@ -15,19 +21,12 @@ export default Component.extend({
|
|||||||
this.set("classNames", classes);
|
this.set("classNames", classes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
tagName: "ul",
|
|
||||||
selectedHtml: null,
|
|
||||||
|
|
||||||
classNames: ["mobile-nav"],
|
|
||||||
|
|
||||||
router: service(),
|
|
||||||
|
|
||||||
currentRouteChanged() {
|
currentRouteChanged() {
|
||||||
this.set("expanded", false);
|
this.set("expanded", false);
|
||||||
next(() => this._updateSelectedHtml());
|
next(() => this._updateSelectedHtml());
|
||||||
},
|
}
|
||||||
|
|
||||||
_updateSelectedHtml() {
|
_updateSelectedHtml() {
|
||||||
if (!this.element || this.isDestroying || this.isDestroyed) {
|
if (!this.element || this.isDestroying || this.isDestroyed) {
|
||||||
@ -38,19 +37,19 @@ export default Component.extend({
|
|||||||
if (active && active.innerHTML) {
|
if (active && active.innerHTML) {
|
||||||
this.set("selectedHtml", active.innerHTML);
|
this.set("selectedHtml", active.innerHTML);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
didInsertElement() {
|
didInsertElement() {
|
||||||
this._super(...arguments);
|
super.didInsertElement(...arguments);
|
||||||
|
|
||||||
this._updateSelectedHtml();
|
this._updateSelectedHtml();
|
||||||
this.router.on("routeDidChange", this, this.currentRouteChanged);
|
this.router.on("routeDidChange", this, this.currentRouteChanged);
|
||||||
},
|
}
|
||||||
|
|
||||||
willDestroyElement() {
|
willDestroyElement() {
|
||||||
this._super(...arguments);
|
super.willDestroyElement(...arguments);
|
||||||
this.router.off("routeDidChange", this, this.currentRouteChanged);
|
this.router.off("routeDidChange", this, this.currentRouteChanged);
|
||||||
},
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
toggleExpanded(event) {
|
toggleExpanded(event) {
|
||||||
@ -74,5 +73,5 @@ export default Component.extend({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
@ -33,18 +33,18 @@ export function resetWidgetCleanCallbacks() {
|
|||||||
_cleanCallbacks = {};
|
_cleanCallbacks = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Component.extend({
|
export default class MountWidget extends Component {
|
||||||
_tree: null,
|
dirtyKeys = null;
|
||||||
_rootNode: null,
|
_tree = null;
|
||||||
_timeout: null,
|
_rootNode = null;
|
||||||
_widgetClass: null,
|
_timeout = null;
|
||||||
_renderCallback: null,
|
_widgetClass = null;
|
||||||
_childEvents: null,
|
_renderCallback = null;
|
||||||
_dispatched: null,
|
_childEvents = null;
|
||||||
dirtyKeys: null,
|
_dispatched = null;
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this._super(...arguments);
|
super.init(...arguments);
|
||||||
const name = this.widget;
|
const name = this.widget;
|
||||||
|
|
||||||
if (name === "post-cooked") {
|
if (name === "post-cooked") {
|
||||||
@ -81,19 +81,19 @@ export default Component.extend({
|
|||||||
this._childComponents = ArrayProxy.create({ content: [] });
|
this._childComponents = ArrayProxy.create({ content: [] });
|
||||||
this._dispatched = [];
|
this._dispatched = [];
|
||||||
this.dirtyKeys = new DirtyKeys(name);
|
this.dirtyKeys = new DirtyKeys(name);
|
||||||
},
|
}
|
||||||
|
|
||||||
didInsertElement() {
|
didInsertElement() {
|
||||||
this._super(...arguments);
|
super.didInsertElement(...arguments);
|
||||||
WidgetClickHook.setupDocumentCallback();
|
WidgetClickHook.setupDocumentCallback();
|
||||||
|
|
||||||
this._rootNode = document.createElement("div");
|
this._rootNode = document.createElement("div");
|
||||||
this.element.appendChild(this._rootNode);
|
this.element.appendChild(this._rootNode);
|
||||||
this._timeout = scheduleOnce("render", this, this.rerenderWidget);
|
this._timeout = scheduleOnce("render", this, this.rerenderWidget);
|
||||||
},
|
}
|
||||||
|
|
||||||
willClearRender() {
|
willClearRender() {
|
||||||
this._super(...arguments);
|
super.willClearRender(...arguments);
|
||||||
const callbacks = _cleanCallbacks[this.widget];
|
const callbacks = _cleanCallbacks[this.widget];
|
||||||
if (callbacks) {
|
if (callbacks) {
|
||||||
callbacks.forEach((cb) => cb(this._tree));
|
callbacks.forEach((cb) => cb(this._tree));
|
||||||
@ -105,29 +105,27 @@ export default Component.extend({
|
|||||||
traverseCustomWidgets(this._tree, (w) => w.destroy());
|
traverseCustomWidgets(this._tree, (w) => w.destroy());
|
||||||
this._rootNode = patch(this._rootNode, diff(this._tree, null));
|
this._rootNode = patch(this._rootNode, diff(this._tree, null));
|
||||||
this._tree = null;
|
this._tree = null;
|
||||||
},
|
}
|
||||||
|
|
||||||
willDestroyElement() {
|
willDestroyElement() {
|
||||||
this._super(...arguments);
|
super.willDestroyElement(...arguments);
|
||||||
this._dispatched.forEach((evt) => {
|
this._dispatched.forEach((evt) => {
|
||||||
const [eventName, caller] = evt;
|
const [eventName, caller] = evt;
|
||||||
this.appEvents.off(eventName, this, caller);
|
this.appEvents.off(eventName, this, caller);
|
||||||
});
|
});
|
||||||
cancel(this._timeout);
|
cancel(this._timeout);
|
||||||
},
|
}
|
||||||
|
|
||||||
afterRender() {},
|
afterRender() {}
|
||||||
|
beforePatch() {}
|
||||||
beforePatch() {},
|
afterPatch() {}
|
||||||
|
|
||||||
afterPatch() {},
|
|
||||||
|
|
||||||
eventDispatched(eventName, key, refreshArg) {
|
eventDispatched(eventName, key, refreshArg) {
|
||||||
key = typeof key === "function" ? key(refreshArg) : key;
|
key = typeof key === "function" ? key(refreshArg) : key;
|
||||||
const onRefresh = camelize(eventName.replace(/:/, "-"));
|
const onRefresh = camelize(eventName.replace(/:/, "-"));
|
||||||
this.dirtyKeys.keyDirty(key, { onRefresh, refreshArg });
|
this.dirtyKeys.keyDirty(key, { onRefresh, refreshArg });
|
||||||
this.queueRerender();
|
this.queueRerender();
|
||||||
},
|
}
|
||||||
|
|
||||||
dispatch(eventName, key) {
|
dispatch(eventName, key) {
|
||||||
this._childEvents.push(eventName);
|
this._childEvents.push(eventName);
|
||||||
@ -136,7 +134,7 @@ export default Component.extend({
|
|||||||
this.eventDispatched(eventName, key, refreshArg);
|
this.eventDispatched(eventName, key, refreshArg);
|
||||||
this._dispatched.push([eventName, caller]);
|
this._dispatched.push([eventName, caller]);
|
||||||
this.appEvents.on(eventName, this, caller);
|
this.appEvents.on(eventName, this, caller);
|
||||||
},
|
}
|
||||||
|
|
||||||
queueRerender(callback) {
|
queueRerender(callback) {
|
||||||
if (callback && !this._renderCallback) {
|
if (callback && !this._renderCallback) {
|
||||||
@ -144,9 +142,9 @@ export default Component.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
scheduleOnce("render", this, this.rerenderWidget);
|
scheduleOnce("render", this, this.rerenderWidget);
|
||||||
},
|
}
|
||||||
|
|
||||||
buildArgs() {},
|
buildArgs() {}
|
||||||
|
|
||||||
rerenderWidget() {
|
rerenderWidget() {
|
||||||
cancel(this._timeout);
|
cancel(this._timeout);
|
||||||
@ -190,18 +188,18 @@ export default Component.extend({
|
|||||||
console.log(Date.now() - t0);
|
console.log(Date.now() - t0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
mountChildComponent(info) {
|
mountChildComponent(info) {
|
||||||
this._childComponents.pushObject(info);
|
this._childComponents.pushObject(info);
|
||||||
},
|
}
|
||||||
|
|
||||||
unmountChildComponent(info) {
|
unmountChildComponent(info) {
|
||||||
this._childComponents.removeObject(info);
|
this._childComponents.removeObject(info);
|
||||||
},
|
}
|
||||||
|
|
||||||
didUpdateAttrs() {
|
didUpdateAttrs() {
|
||||||
this._super(...arguments);
|
super.didUpdateAttrs(...arguments);
|
||||||
this.queueRerender();
|
this.queueRerender();
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
@ -1,28 +1,34 @@
|
|||||||
import { tracked } from "@glimmer/tracking";
|
import { tracked } from "@glimmer/tracking";
|
||||||
import Component from "@ember/component";
|
import Component from "@ember/component";
|
||||||
import { dependentKeyCompat } from "@ember/object/compat";
|
import { dependentKeyCompat } from "@ember/object/compat";
|
||||||
|
import {
|
||||||
|
attributeBindings,
|
||||||
|
classNameBindings,
|
||||||
|
tagName,
|
||||||
|
} from "@ember-decorators/component";
|
||||||
import { filterTypeForMode } from "discourse/lib/filter-mode";
|
import { filterTypeForMode } from "discourse/lib/filter-mode";
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
|
|
||||||
export default Component.extend({
|
@tagName("li")
|
||||||
tagName: "li",
|
@classNameBindings(
|
||||||
classNameBindings: [
|
"active",
|
||||||
"active",
|
"content.hasIcon:has-icon",
|
||||||
"content.hasIcon:has-icon",
|
"content.classNames",
|
||||||
"content.classNames",
|
"isHidden:hidden",
|
||||||
"isHidden:hidden",
|
"content.name"
|
||||||
"content.name",
|
)
|
||||||
],
|
@attributeBindings("content.title:title")
|
||||||
attributeBindings: ["content.title:title"],
|
export default class NavigationItem extends Component {
|
||||||
hidden: false,
|
@tracked filterMode;
|
||||||
activeClass: "",
|
|
||||||
hrefLink: null,
|
hidden = false;
|
||||||
filterMode: tracked(),
|
activeClass = "";
|
||||||
|
hrefLink = null;
|
||||||
|
|
||||||
@dependentKeyCompat
|
@dependentKeyCompat
|
||||||
get filterType() {
|
get filterType() {
|
||||||
return filterTypeForMode(this.filterMode);
|
return filterTypeForMode(this.filterMode);
|
||||||
},
|
}
|
||||||
|
|
||||||
@discourseComputed("content.filterType", "filterType", "content.active")
|
@discourseComputed("content.filterType", "filterType", "content.active")
|
||||||
active(contentFilterType, filterType, active) {
|
active(contentFilterType, filterType, active) {
|
||||||
@ -30,7 +36,7 @@ export default Component.extend({
|
|||||||
return active;
|
return active;
|
||||||
}
|
}
|
||||||
return contentFilterType === filterType;
|
return contentFilterType === filterType;
|
||||||
},
|
}
|
||||||
|
|
||||||
@discourseComputed("content.count", "content.name")
|
@discourseComputed("content.count", "content.name")
|
||||||
isHidden(count, name) {
|
isHidden(count, name) {
|
||||||
@ -42,10 +48,10 @@ export default Component.extend({
|
|||||||
(name === "new" || name === "unread") &&
|
(name === "new" || name === "unread") &&
|
||||||
count < 1
|
count < 1
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
|
|
||||||
didReceiveAttrs() {
|
didReceiveAttrs() {
|
||||||
this._super(...arguments);
|
super.didReceiveAttrs(...arguments);
|
||||||
const content = this.content;
|
const content = this.content;
|
||||||
|
|
||||||
let href = content.get("href");
|
let href = content.get("href");
|
||||||
@ -87,5 +93,5 @@ export default Component.extend({
|
|||||||
this.set("hrefLink", href);
|
this.set("hrefLink", href);
|
||||||
|
|
||||||
this.set("activeClass", this.active ? "active" : "");
|
this.set("activeClass", this.active ? "active" : "");
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
|
import { computed } from "@ember/object";
|
||||||
|
import { classNameBindings } from "@ember-decorators/component";
|
||||||
import TextField from "discourse/components/text-field";
|
import TextField from "discourse/components/text-field";
|
||||||
import { allowOnlyNumericInput } from "discourse/lib/utilities";
|
import { allowOnlyNumericInput } from "discourse/lib/utilities";
|
||||||
import deprecated from "discourse-common/lib/deprecated";
|
import deprecated from "discourse-common/lib/deprecated";
|
||||||
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 TextField.extend({
|
@classNameBindings("invalid")
|
||||||
classNameBindings: ["invalid"],
|
export default class NumberField extends TextField {
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this._super(...arguments);
|
super.init(...arguments);
|
||||||
deprecated(
|
deprecated(
|
||||||
`NumberField component is deprecated. Use native <input> elements instead.\ne.g. <input {{on "input" (with-event-value (fn (mut this.value)))}} type="number" value={{this.value}} />`,
|
`NumberField component is deprecated. Use native <input> elements instead.\ne.g. <input {{on "input" (with-event-value (fn (mut this.value)))}} type="number" value={{this.value}} />`,
|
||||||
{
|
{
|
||||||
@ -17,46 +18,47 @@ export default TextField.extend({
|
|||||||
dropFrom: "3.3.0",
|
dropFrom: "3.3.0",
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
|
|
||||||
keyDown: function (event) {
|
keyDown(event) {
|
||||||
allowOnlyNumericInput(event, this._minNumber && this._minNumber < 0);
|
allowOnlyNumericInput(event, this._minNumber && this._minNumber < 0);
|
||||||
},
|
}
|
||||||
|
|
||||||
get _minNumber() {
|
get _minNumber() {
|
||||||
if (!this.get("min")) {
|
if (!this.get("min")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return parseInt(this.get("min"), 10);
|
return parseInt(this.get("min"), 10);
|
||||||
},
|
}
|
||||||
|
|
||||||
get _maxNumber() {
|
get _maxNumber() {
|
||||||
if (!this.get("max")) {
|
if (!this.get("max")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return parseInt(this.get("max"), 10);
|
return parseInt(this.get("max"), 10);
|
||||||
},
|
}
|
||||||
|
|
||||||
@discourseComputed("number")
|
@computed("number")
|
||||||
value: {
|
get value() {
|
||||||
get(number) {
|
if (this.number === null) {
|
||||||
return parseInt(number, 10);
|
return "";
|
||||||
},
|
}
|
||||||
set(value) {
|
return parseInt(this.number, 10);
|
||||||
const num = parseInt(value, 10);
|
}
|
||||||
if (isNaN(num)) {
|
|
||||||
this.set("invalid", true);
|
set value(value) {
|
||||||
return value;
|
const num = parseInt(value, 10);
|
||||||
} else {
|
if (isNaN(num)) {
|
||||||
this.set("invalid", false);
|
this.set("invalid", true);
|
||||||
this.set("number", num);
|
this.set("number", null);
|
||||||
return num.toString();
|
} else {
|
||||||
}
|
this.set("invalid", false);
|
||||||
},
|
this.set("number", num);
|
||||||
},
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@discourseComputed("placeholderKey")
|
@discourseComputed("placeholderKey")
|
||||||
placeholder(key) {
|
placeholder(key) {
|
||||||
return key ? I18n.t(key) : "";
|
return key ? I18n.t(key) : "";
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
import CategoryListItem from "discourse/components/category-list-item";
|
import CategoryListItem from "discourse/components/category-list-item";
|
||||||
|
|
||||||
export default CategoryListItem.extend({});
|
export default class ParentCategoryRow extends CategoryListItem {}
|
||||||
|
@ -4,8 +4,8 @@ import TextField from "discourse/components/text-field";
|
|||||||
Same as text-field, but with special features for a password input.
|
Same as text-field, but with special features for a password input.
|
||||||
Be sure to test on a variety of browsers and operating systems when changing this logic.
|
Be sure to test on a variety of browsers and operating systems when changing this logic.
|
||||||
**/
|
**/
|
||||||
export default TextField.extend({
|
export default class PasswordField extends TextField {
|
||||||
canToggle: false,
|
canToggle = false;
|
||||||
|
|
||||||
keyPress(e) {
|
keyPress(e) {
|
||||||
if (
|
if (
|
||||||
@ -21,19 +21,19 @@ export default TextField.extend({
|
|||||||
this.set("canToggle", true);
|
this.set("canToggle", true);
|
||||||
this.set("capsLockOn", false);
|
this.set("capsLockOn", false);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
keyUp(e) {
|
keyUp(e) {
|
||||||
if (e.which === 20 && this.canToggle) {
|
if (e.which === 20 && this.canToggle) {
|
||||||
this.toggleProperty("capsLockOn");
|
this.toggleProperty("capsLockOn");
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
focusOut() {
|
focusOut() {
|
||||||
this.set("capsLockOn", false);
|
this.set("capsLockOn", false);
|
||||||
},
|
}
|
||||||
|
|
||||||
focusIn() {
|
focusIn() {
|
||||||
this.set("canToggle", false); // can't know the state of caps lock yet. keyPress will figure it out.
|
this.set("canToggle", false); // can't know the state of caps lock yet. keyPress will figure it out.
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
@ -4,12 +4,12 @@ import { ajax } from "discourse/lib/ajax";
|
|||||||
import { loadOneboxes } from "discourse/lib/load-oneboxes";
|
import { loadOneboxes } from "discourse/lib/load-oneboxes";
|
||||||
import { afterRender } from "discourse-common/utils/decorators";
|
import { afterRender } from "discourse-common/utils/decorators";
|
||||||
|
|
||||||
export default Component.extend({
|
export default class PendingPost extends Component {
|
||||||
didRender() {
|
didRender() {
|
||||||
this._super(...arguments);
|
super.didRender(...arguments);
|
||||||
this._loadOneboxes();
|
this._loadOneboxes();
|
||||||
this._resolveUrls();
|
this._resolveUrls();
|
||||||
},
|
}
|
||||||
|
|
||||||
@afterRender
|
@afterRender
|
||||||
_loadOneboxes() {
|
_loadOneboxes() {
|
||||||
@ -21,10 +21,10 @@ export default Component.extend({
|
|||||||
this.siteSettings.max_oneboxes_per_post,
|
this.siteSettings.max_oneboxes_per_post,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
|
|
||||||
@afterRender
|
@afterRender
|
||||||
_resolveUrls() {
|
_resolveUrls() {
|
||||||
resolveAllShortUrls(ajax, this.siteSettings, this.element, this.opts);
|
resolveAllShortUrls(ajax, this.siteSettings, this.element, this.opts);
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
@ -2,6 +2,7 @@ import Component from "@ember/component";
|
|||||||
import { action } from "@ember/object";
|
import { action } from "@ember/object";
|
||||||
import { service } from "@ember/service";
|
import { service } from "@ember/service";
|
||||||
import { isBlank } from "@ember/utils";
|
import { isBlank } from "@ember/utils";
|
||||||
|
import { classNames } from "@ember-decorators/component";
|
||||||
import {
|
import {
|
||||||
authorizedExtensions,
|
authorizedExtensions,
|
||||||
authorizesAllExtensions,
|
authorizesAllExtensions,
|
||||||
@ -17,39 +18,40 @@ import I18n from "discourse-i18n";
|
|||||||
// binding will still be added, and the file type will be validated here. This
|
// binding will still be added, and the file type will be validated here. This
|
||||||
// is sometimes useful if you need to do something outside the uppy upload with
|
// is sometimes useful if you need to do something outside the uppy upload with
|
||||||
// the file, such as directly using JSON or CSV data from a file in JS.
|
// the file, such as directly using JSON or CSV data from a file in JS.
|
||||||
export default Component.extend({
|
@classNames("pick-files-button")
|
||||||
dialog: service(),
|
export default class PickFilesButton extends Component {
|
||||||
fileInputId: null,
|
@service dialog;
|
||||||
fileInputClass: null,
|
|
||||||
fileInputDisabled: false,
|
fileInputId = null;
|
||||||
classNames: ["pick-files-button"],
|
fileInputClass = null;
|
||||||
acceptedFormatsOverride: null,
|
fileInputDisabled = false;
|
||||||
allowMultiple: false,
|
acceptedFormatsOverride = null;
|
||||||
showButton: false,
|
allowMultiple = false;
|
||||||
|
showButton = false;
|
||||||
|
|
||||||
didInsertElement() {
|
didInsertElement() {
|
||||||
this._super(...arguments);
|
super.didInsertElement(...arguments);
|
||||||
|
|
||||||
if (this.onFilesPicked) {
|
if (this.onFilesPicked) {
|
||||||
const fileInput = this.element.querySelector("input");
|
const fileInput = this.element.querySelector("input");
|
||||||
this.set("fileInput", fileInput);
|
this.set("fileInput", fileInput);
|
||||||
fileInput.addEventListener("change", this.onChange, false);
|
fileInput.addEventListener("change", this.onChange, false);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
willDestroyElement() {
|
willDestroyElement() {
|
||||||
this._super(...arguments);
|
super.willDestroyElement(...arguments);
|
||||||
|
|
||||||
if (this.onFilesPicked) {
|
if (this.onFilesPicked) {
|
||||||
this.fileInput.removeEventListener("change", this.onChange);
|
this.fileInput.removeEventListener("change", this.onChange);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
@bind
|
@bind
|
||||||
onChange() {
|
onChange() {
|
||||||
const files = this.fileInput.files;
|
const files = this.fileInput.files;
|
||||||
this._filesPicked(files);
|
this._filesPicked(files);
|
||||||
},
|
}
|
||||||
|
|
||||||
@discourseComputed()
|
@discourseComputed()
|
||||||
acceptsAllFormats() {
|
acceptsAllFormats() {
|
||||||
@ -57,7 +59,7 @@ export default Component.extend({
|
|||||||
this.capabilities.isIOS ||
|
this.capabilities.isIOS ||
|
||||||
authorizesAllExtensions(this.currentUser.staff, this.siteSettings)
|
authorizesAllExtensions(this.currentUser.staff, this.siteSettings)
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
|
|
||||||
@discourseComputed()
|
@discourseComputed()
|
||||||
acceptedFormats() {
|
acceptedFormats() {
|
||||||
@ -72,12 +74,12 @@ export default Component.extend({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return extensions.map((ext) => `.${ext}`).join();
|
return extensions.map((ext) => `.${ext}`).join();
|
||||||
},
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
openSystemFilePicker() {
|
openSystemFilePicker() {
|
||||||
this.fileInput.click();
|
this.fileInput.click();
|
||||||
},
|
}
|
||||||
|
|
||||||
_filesPicked(files) {
|
_filesPicked(files) {
|
||||||
if (!files || !files.length) {
|
if (!files || !files.length) {
|
||||||
@ -95,7 +97,7 @@ export default Component.extend({
|
|||||||
if (typeof this.onFilesPicked === "function") {
|
if (typeof this.onFilesPicked === "function") {
|
||||||
this.onFilesPicked(files);
|
this.onFilesPicked(files);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
_haveAcceptedTypes(files) {
|
_haveAcceptedTypes(files) {
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
@ -104,7 +106,7 @@ export default Component.extend({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
}
|
||||||
|
|
||||||
_hasAcceptedExtensionOrType(file) {
|
_hasAcceptedExtensionOrType(file) {
|
||||||
const extension = this._fileExtension(file.name);
|
const extension = this._fileExtension(file.name);
|
||||||
@ -112,9 +114,9 @@ export default Component.extend({
|
|||||||
this.acceptedFormats.includes(`.${extension}`) ||
|
this.acceptedFormats.includes(`.${extension}`) ||
|
||||||
this.acceptedFormats.includes(file.type)
|
this.acceptedFormats.includes(file.type)
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
|
|
||||||
_fileExtension(fileName) {
|
_fileExtension(fileName) {
|
||||||
return fileName.split(".").pop();
|
return fileName.split(".").pop();
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
@ -18,9 +18,9 @@ export function resetDecorators() {
|
|||||||
_decorators = {};
|
_decorators = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Component.extend({
|
export default class PluginConnector extends Component {
|
||||||
init() {
|
init() {
|
||||||
this._super(...arguments);
|
super.init(...arguments);
|
||||||
|
|
||||||
const args = this.args || {};
|
const args = this.args || {};
|
||||||
Object.keys(args).forEach((key) => {
|
Object.keys(args).forEach((key) => {
|
||||||
@ -68,31 +68,31 @@ export default Component.extend({
|
|||||||
connectorInfo
|
connectorInfo
|
||||||
);
|
);
|
||||||
connectorClass?.setupComponent?.call(this, merged, this);
|
connectorClass?.setupComponent?.call(this, merged, this);
|
||||||
},
|
}
|
||||||
|
|
||||||
didReceiveAttrs() {
|
didReceiveAttrs() {
|
||||||
this._super(...arguments);
|
super.didReceiveAttrs(...arguments);
|
||||||
|
|
||||||
this._decoratePluginOutlets();
|
this._decoratePluginOutlets();
|
||||||
},
|
}
|
||||||
|
|
||||||
@afterRender
|
@afterRender
|
||||||
_decoratePluginOutlets() {
|
_decoratePluginOutlets() {
|
||||||
(_decorators[this.connector.outletName] || []).forEach((dec) =>
|
(_decorators[this.connector.outletName] || []).forEach((dec) =>
|
||||||
dec(this.element, this.args)
|
dec(this.element, this.args)
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
|
|
||||||
willDestroyElement() {
|
willDestroyElement() {
|
||||||
this._super(...arguments);
|
super.willDestroyElement(...arguments);
|
||||||
|
|
||||||
const connectorClass = this.connector.connectorClass;
|
const connectorClass = this.connector.connectorClass;
|
||||||
connectorClass?.teardownComponent?.call(this, this);
|
connectorClass?.teardownComponent?.call(this, this);
|
||||||
},
|
}
|
||||||
|
|
||||||
send(name, ...args) {
|
send(name, ...args) {
|
||||||
const connectorClass = this.connector.connectorClass;
|
const connectorClass = this.connector.connectorClass;
|
||||||
const action = connectorClass?.actions?.[name];
|
const action = connectorClass?.actions?.[name];
|
||||||
return action ? action.call(this, ...args) : this._super(name, ...args);
|
return action ? action.call(this, ...args) : super.send(name, ...args);
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
@ -2,54 +2,61 @@ import Component from "@ember/component";
|
|||||||
import { not, or, reads } from "@ember/object/computed";
|
import { not, or, reads } from "@ember/object/computed";
|
||||||
import { service } from "@ember/service";
|
import { service } from "@ember/service";
|
||||||
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";
|
||||||
|
|
||||||
export default Component.extend({
|
@tagName("a")
|
||||||
composer: service(),
|
@classNameBindings(":popup-tip", "good", "bad", "lastShownAt::hide")
|
||||||
tagName: "a",
|
@attributeBindings("role", "ariaLabel", "tabindex")
|
||||||
classNameBindings: [":popup-tip", "good", "bad", "lastShownAt::hide"],
|
export default class PopupInputTip extends Component {
|
||||||
attributeBindings: ["role", "ariaLabel", "tabindex"],
|
@service composer;
|
||||||
tipReason: null,
|
|
||||||
lastShownAt: or("shownAt", "validation.lastShownAt"),
|
tipReason = null;
|
||||||
bad: reads("validation.failed"),
|
tabindex = "0";
|
||||||
good: not("bad"),
|
|
||||||
tabindex: "0",
|
@or("shownAt", "validation.lastShownAt") lastShownAt;
|
||||||
|
@reads("validation.failed") bad;
|
||||||
|
@not("bad") good;
|
||||||
|
|
||||||
@discourseComputed("bad")
|
@discourseComputed("bad")
|
||||||
role(bad) {
|
role(bad) {
|
||||||
if (bad) {
|
if (bad) {
|
||||||
return "alert";
|
return "alert";
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
@discourseComputed("validation.reason")
|
@discourseComputed("validation.reason")
|
||||||
ariaLabel(reason) {
|
ariaLabel(reason) {
|
||||||
return reason?.replace(/(<([^>]+)>)/gi, "");
|
return reason?.replace(/(<([^>]+)>)/gi, "");
|
||||||
},
|
}
|
||||||
|
|
||||||
dismiss() {
|
dismiss() {
|
||||||
this.set("shownAt", null);
|
this.set("shownAt", null);
|
||||||
this.composer.clearLastValidatedAt();
|
this.composer.clearLastValidatedAt();
|
||||||
this.element.previousElementSibling?.focus();
|
this.element.previousElementSibling?.focus();
|
||||||
},
|
}
|
||||||
|
|
||||||
click() {
|
click() {
|
||||||
this.dismiss();
|
this.dismiss();
|
||||||
},
|
}
|
||||||
|
|
||||||
keyDown(event) {
|
keyDown(event) {
|
||||||
if (event.key === "Enter") {
|
if (event.key === "Enter") {
|
||||||
this.dismiss();
|
this.dismiss();
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
didReceiveAttrs() {
|
didReceiveAttrs() {
|
||||||
this._super(...arguments);
|
super.didReceiveAttrs(...arguments);
|
||||||
let reason = this.get("validation.reason");
|
let reason = this.get("validation.reason");
|
||||||
if (reason) {
|
if (reason) {
|
||||||
this.set("tipReason", htmlSafe(`${reason}`));
|
this.set("tipReason", htmlSafe(`${reason}`));
|
||||||
} else {
|
} else {
|
||||||
this.set("tipReason", null);
|
this.set("tipReason", null);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
import Component from "@ember/component";
|
import Component from "@ember/component";
|
||||||
|
|
||||||
export default Component.extend({});
|
export default class PopupMenu extends Component {}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user