mirror of
https://github.com/discourse/discourse.git
synced 2024-11-25 10:20:58 -06:00
DEV: Convert core controllers to native class syntax (batch 3) (#28224)
Changes made using the ember-native-class-codemod, plus some manual tweaks
This commit is contained in:
parent
854b8b7093
commit
75d11bfeba
@ -16,368 +16,362 @@ import getUrl from "discourse-common/lib/get-url";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import I18n from "discourse-i18n";
|
||||
|
||||
export default Controller.extend(
|
||||
export default class InvitesShowController extends Controller.extend(
|
||||
PasswordValidation,
|
||||
UsernameValidation,
|
||||
NameValidation,
|
||||
UserFieldsValidation,
|
||||
{
|
||||
queryParams: ["t"],
|
||||
UserFieldsValidation
|
||||
) {
|
||||
queryParams = ["t"];
|
||||
|
||||
invitedBy: readOnly("model.invited_by"),
|
||||
email: alias("model.email"),
|
||||
accountEmail: alias("email"),
|
||||
existingUserId: readOnly("model.existing_user_id"),
|
||||
existingUserCanRedeem: readOnly("model.existing_user_can_redeem"),
|
||||
existingUserCanRedeemError: readOnly(
|
||||
"model.existing_user_can_redeem_error"
|
||||
),
|
||||
existingUserRedeeming: bool("existingUserId"),
|
||||
hiddenEmail: alias("model.hidden_email"),
|
||||
emailVerifiedByLink: alias("model.email_verified_by_link"),
|
||||
differentExternalEmail: alias("model.different_external_email"),
|
||||
accountUsername: alias("model.username"),
|
||||
passwordRequired: not("externalAuthsOnly"),
|
||||
successMessage: null,
|
||||
errorMessage: null,
|
||||
userFields: null,
|
||||
authOptions: null,
|
||||
inviteImageUrl: getUrl("/images/envelope.svg"),
|
||||
isInviteLink: readOnly("model.is_invite_link"),
|
||||
rejectedEmails: null,
|
||||
maskPassword: true,
|
||||
@readOnly("model.invited_by") invitedBy;
|
||||
@alias("model.email") email;
|
||||
@alias("email") accountEmail;
|
||||
@readOnly("model.existing_user_id") existingUserId;
|
||||
@readOnly("model.existing_user_can_redeem") existingUserCanRedeem;
|
||||
@readOnly("model.existing_user_can_redeem_error") existingUserCanRedeemError;
|
||||
@bool("existingUserId") existingUserRedeeming;
|
||||
@alias("model.hidden_email") hiddenEmail;
|
||||
@alias("model.email_verified_by_link") emailVerifiedByLink;
|
||||
@alias("model.different_external_email") differentExternalEmail;
|
||||
@alias("model.username") accountUsername;
|
||||
@not("externalAuthsOnly") passwordRequired;
|
||||
@readOnly("model.is_invite_link") isInviteLink;
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
successMessage = null;
|
||||
errorMessage = null;
|
||||
userFields = null;
|
||||
authOptions = null;
|
||||
inviteImageUrl = getUrl("/images/envelope.svg");
|
||||
rejectedEmails = [];
|
||||
maskPassword = true;
|
||||
|
||||
this.rejectedEmails = [];
|
||||
},
|
||||
authenticationComplete(options) {
|
||||
const props = {
|
||||
accountUsername: options.username,
|
||||
accountName: options.name,
|
||||
authOptions: EmberObject.create(options),
|
||||
};
|
||||
|
||||
authenticationComplete(options) {
|
||||
const props = {
|
||||
accountUsername: options.username,
|
||||
accountName: options.name,
|
||||
authOptions: EmberObject.create(options),
|
||||
};
|
||||
if (this.isInviteLink) {
|
||||
props.email = options.email;
|
||||
}
|
||||
|
||||
if (this.isInviteLink) {
|
||||
props.email = options.email;
|
||||
}
|
||||
this.setProperties(props);
|
||||
}
|
||||
|
||||
this.setProperties(props);
|
||||
},
|
||||
@discourseComputed
|
||||
discourseConnectEnabled() {
|
||||
return this.siteSettings.enable_discourse_connect;
|
||||
}
|
||||
|
||||
@discourseComputed
|
||||
discourseConnectEnabled() {
|
||||
return this.siteSettings.enable_discourse_connect;
|
||||
},
|
||||
@discourseComputed
|
||||
welcomeTitle() {
|
||||
return I18n.t("invites.welcome_to", {
|
||||
site_name: this.siteSettings.title,
|
||||
});
|
||||
}
|
||||
|
||||
@discourseComputed
|
||||
welcomeTitle() {
|
||||
return I18n.t("invites.welcome_to", {
|
||||
site_name: this.siteSettings.title,
|
||||
@discourseComputed("existingUserId")
|
||||
subheaderMessage(existingUserId) {
|
||||
if (existingUserId) {
|
||||
return I18n.t("invites.existing_user_can_redeem");
|
||||
} else {
|
||||
return I18n.t("create_account.subheader_title");
|
||||
}
|
||||
}
|
||||
|
||||
@discourseComputed("email")
|
||||
yourEmailMessage(email) {
|
||||
return I18n.t("invites.your_email", { email });
|
||||
}
|
||||
|
||||
@discourseComputed
|
||||
externalAuthsEnabled() {
|
||||
return findLoginMethods().length > 0;
|
||||
}
|
||||
|
||||
@discourseComputed
|
||||
externalAuthsOnly() {
|
||||
return (
|
||||
!this.siteSettings.enable_local_logins &&
|
||||
this.externalAuthsEnabled &&
|
||||
!this.siteSettings.enable_discourse_connect
|
||||
);
|
||||
}
|
||||
|
||||
@discourseComputed(
|
||||
"emailValidation.failed",
|
||||
"usernameValidation.failed",
|
||||
"passwordValidation.failed",
|
||||
"nameValidation.failed",
|
||||
"userFieldsValidation.failed",
|
||||
"existingUserRedeeming",
|
||||
"existingUserCanRedeem"
|
||||
)
|
||||
submitDisabled(
|
||||
emailValidationFailed,
|
||||
usernameValidationFailed,
|
||||
passwordValidationFailed,
|
||||
nameValidationFailed,
|
||||
userFieldsValidationFailed,
|
||||
existingUserRedeeming,
|
||||
existingUserCanRedeem
|
||||
) {
|
||||
if (existingUserRedeeming) {
|
||||
return !existingUserCanRedeem;
|
||||
}
|
||||
|
||||
return (
|
||||
emailValidationFailed ||
|
||||
usernameValidationFailed ||
|
||||
passwordValidationFailed ||
|
||||
nameValidationFailed ||
|
||||
userFieldsValidationFailed
|
||||
);
|
||||
}
|
||||
|
||||
@discourseComputed(
|
||||
"externalAuthsEnabled",
|
||||
"externalAuthsOnly",
|
||||
"discourseConnectEnabled"
|
||||
)
|
||||
showSocialLoginAvailable(
|
||||
externalAuthsEnabled,
|
||||
externalAuthsOnly,
|
||||
discourseConnectEnabled
|
||||
) {
|
||||
return (
|
||||
externalAuthsEnabled && !externalAuthsOnly && !discourseConnectEnabled
|
||||
);
|
||||
}
|
||||
|
||||
@discourseComputed(
|
||||
"externalAuthsOnly",
|
||||
"authOptions",
|
||||
"emailValidation.failed",
|
||||
"existingUserRedeeming"
|
||||
)
|
||||
shouldDisplayForm(
|
||||
externalAuthsOnly,
|
||||
authOptions,
|
||||
emailValidationFailed,
|
||||
existingUserRedeeming
|
||||
) {
|
||||
return (
|
||||
(this.siteSettings.enable_local_logins ||
|
||||
(externalAuthsOnly && authOptions && !emailValidationFailed)) &&
|
||||
!this.siteSettings.enable_discourse_connect &&
|
||||
!existingUserRedeeming
|
||||
);
|
||||
}
|
||||
|
||||
@discourseComputed
|
||||
fullnameRequired() {
|
||||
return (
|
||||
this.siteSettings.full_name_required || this.siteSettings.enable_names
|
||||
);
|
||||
}
|
||||
|
||||
@discourseComputed(
|
||||
"email",
|
||||
"rejectedEmails.[]",
|
||||
"authOptions.email",
|
||||
"authOptions.email_valid",
|
||||
"hiddenEmail",
|
||||
"emailVerifiedByLink",
|
||||
"differentExternalEmail"
|
||||
)
|
||||
emailValidation(
|
||||
email,
|
||||
rejectedEmails,
|
||||
externalAuthEmail,
|
||||
externalAuthEmailValid,
|
||||
hiddenEmail,
|
||||
emailVerifiedByLink,
|
||||
differentExternalEmail
|
||||
) {
|
||||
if (hiddenEmail && !differentExternalEmail) {
|
||||
return EmberObject.create({
|
||||
ok: true,
|
||||
reason: I18n.t("user.email.ok"),
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("existingUserId")
|
||||
subheaderMessage(existingUserId) {
|
||||
if (existingUserId) {
|
||||
return I18n.t("invites.existing_user_can_redeem");
|
||||
} else {
|
||||
return I18n.t("create_account.subheader_title");
|
||||
}
|
||||
},
|
||||
|
||||
@discourseComputed("email")
|
||||
yourEmailMessage(email) {
|
||||
return I18n.t("invites.your_email", { email });
|
||||
},
|
||||
|
||||
@discourseComputed
|
||||
externalAuthsEnabled() {
|
||||
return findLoginMethods().length > 0;
|
||||
},
|
||||
|
||||
@discourseComputed
|
||||
externalAuthsOnly() {
|
||||
return (
|
||||
!this.siteSettings.enable_local_logins &&
|
||||
this.externalAuthsEnabled &&
|
||||
!this.siteSettings.enable_discourse_connect
|
||||
);
|
||||
},
|
||||
|
||||
@discourseComputed(
|
||||
"emailValidation.failed",
|
||||
"usernameValidation.failed",
|
||||
"passwordValidation.failed",
|
||||
"nameValidation.failed",
|
||||
"userFieldsValidation.failed",
|
||||
"existingUserRedeeming",
|
||||
"existingUserCanRedeem"
|
||||
)
|
||||
submitDisabled(
|
||||
emailValidationFailed,
|
||||
usernameValidationFailed,
|
||||
passwordValidationFailed,
|
||||
nameValidationFailed,
|
||||
userFieldsValidationFailed,
|
||||
existingUserRedeeming,
|
||||
existingUserCanRedeem
|
||||
) {
|
||||
if (existingUserRedeeming) {
|
||||
return !existingUserCanRedeem;
|
||||
}
|
||||
|
||||
return (
|
||||
emailValidationFailed ||
|
||||
usernameValidationFailed ||
|
||||
passwordValidationFailed ||
|
||||
nameValidationFailed ||
|
||||
userFieldsValidationFailed
|
||||
);
|
||||
},
|
||||
|
||||
@discourseComputed(
|
||||
"externalAuthsEnabled",
|
||||
"externalAuthsOnly",
|
||||
"discourseConnectEnabled"
|
||||
)
|
||||
showSocialLoginAvailable(
|
||||
externalAuthsEnabled,
|
||||
externalAuthsOnly,
|
||||
discourseConnectEnabled
|
||||
) {
|
||||
return (
|
||||
externalAuthsEnabled && !externalAuthsOnly && !discourseConnectEnabled
|
||||
);
|
||||
},
|
||||
|
||||
@discourseComputed(
|
||||
"externalAuthsOnly",
|
||||
"authOptions",
|
||||
"emailValidation.failed",
|
||||
"existingUserRedeeming"
|
||||
)
|
||||
shouldDisplayForm(
|
||||
externalAuthsOnly,
|
||||
authOptions,
|
||||
emailValidationFailed,
|
||||
existingUserRedeeming
|
||||
) {
|
||||
return (
|
||||
(this.siteSettings.enable_local_logins ||
|
||||
(externalAuthsOnly && authOptions && !emailValidationFailed)) &&
|
||||
!this.siteSettings.enable_discourse_connect &&
|
||||
!existingUserRedeeming
|
||||
);
|
||||
},
|
||||
|
||||
@discourseComputed
|
||||
fullnameRequired() {
|
||||
return (
|
||||
this.siteSettings.full_name_required || this.siteSettings.enable_names
|
||||
);
|
||||
},
|
||||
|
||||
@discourseComputed(
|
||||
"email",
|
||||
"rejectedEmails.[]",
|
||||
"authOptions.email",
|
||||
"authOptions.email_valid",
|
||||
"hiddenEmail",
|
||||
"emailVerifiedByLink",
|
||||
"differentExternalEmail"
|
||||
)
|
||||
emailValidation(
|
||||
email,
|
||||
rejectedEmails,
|
||||
externalAuthEmail,
|
||||
externalAuthEmailValid,
|
||||
hiddenEmail,
|
||||
emailVerifiedByLink,
|
||||
differentExternalEmail
|
||||
) {
|
||||
if (hiddenEmail && !differentExternalEmail) {
|
||||
return EmberObject.create({
|
||||
ok: true,
|
||||
reason: I18n.t("user.email.ok"),
|
||||
});
|
||||
}
|
||||
|
||||
// If blank, fail without a reason
|
||||
if (isEmpty(email)) {
|
||||
return EmberObject.create({
|
||||
failed: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (rejectedEmails.includes(email)) {
|
||||
return EmberObject.create({
|
||||
failed: true,
|
||||
reason: I18n.t("user.email.invalid"),
|
||||
});
|
||||
}
|
||||
|
||||
if (externalAuthEmail && externalAuthEmailValid) {
|
||||
const provider = this.authProviderDisplayName(
|
||||
this.get("authOptions.auth_provider")
|
||||
);
|
||||
|
||||
if (externalAuthEmail === email) {
|
||||
return EmberObject.create({
|
||||
ok: true,
|
||||
reason: I18n.t("user.email.authenticated", {
|
||||
provider,
|
||||
}),
|
||||
});
|
||||
} else {
|
||||
return EmberObject.create({
|
||||
failed: true,
|
||||
reason: I18n.t("user.email.invite_auth_email_invalid", {
|
||||
provider,
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (emailVerifiedByLink) {
|
||||
return EmberObject.create({
|
||||
ok: true,
|
||||
reason: I18n.t("user.email.authenticated_by_invite"),
|
||||
});
|
||||
}
|
||||
|
||||
if (emailValid(email)) {
|
||||
return EmberObject.create({
|
||||
ok: true,
|
||||
reason: I18n.t("user.email.ok"),
|
||||
});
|
||||
}
|
||||
// If blank, fail without a reason
|
||||
if (isEmpty(email)) {
|
||||
return EmberObject.create({
|
||||
failed: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (rejectedEmails.includes(email)) {
|
||||
return EmberObject.create({
|
||||
failed: true,
|
||||
reason: I18n.t("user.email.invalid"),
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
authProviderDisplayName(providerName) {
|
||||
const matchingProvider = findLoginMethods().find((provider) => {
|
||||
return provider.name === providerName;
|
||||
});
|
||||
return matchingProvider
|
||||
? matchingProvider.get("prettyName")
|
||||
: providerName;
|
||||
},
|
||||
if (externalAuthEmail && externalAuthEmailValid) {
|
||||
const provider = this.authProviderDisplayName(
|
||||
this.get("authOptions.auth_provider")
|
||||
);
|
||||
|
||||
@discourseComputed
|
||||
wavingHandURL: () => wavingHandURL(),
|
||||
|
||||
@discourseComputed
|
||||
ssoPath: () => getUrl("/session/sso"),
|
||||
|
||||
@discourseComputed
|
||||
disclaimerHtml() {
|
||||
if (this.site.tos_url && this.site.privacy_policy_url) {
|
||||
return I18n.t("create_account.disclaimer", {
|
||||
tos_link: this.site.tos_url,
|
||||
privacy_link: this.site.privacy_policy_url,
|
||||
if (externalAuthEmail === email) {
|
||||
return EmberObject.create({
|
||||
ok: true,
|
||||
reason: I18n.t("user.email.authenticated", {
|
||||
provider,
|
||||
}),
|
||||
});
|
||||
} else {
|
||||
return EmberObject.create({
|
||||
failed: true,
|
||||
reason: I18n.t("user.email.invite_auth_email_invalid", {
|
||||
provider,
|
||||
}),
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("authOptions.associate_url", "authOptions.auth_provider")
|
||||
associateHtml(url, provider) {
|
||||
if (!url) {
|
||||
return;
|
||||
}
|
||||
return I18n.t("create_account.associate", {
|
||||
associate_link: url,
|
||||
provider: I18n.t(`login.${provider}.name`),
|
||||
if (emailVerifiedByLink) {
|
||||
return EmberObject.create({
|
||||
ok: true,
|
||||
reason: I18n.t("user.email.authenticated_by_invite"),
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
@action
|
||||
togglePasswordMask() {
|
||||
this.toggleProperty("maskPassword");
|
||||
},
|
||||
if (emailValid(email)) {
|
||||
return EmberObject.create({
|
||||
ok: true,
|
||||
reason: I18n.t("user.email.ok"),
|
||||
});
|
||||
}
|
||||
|
||||
actions: {
|
||||
submit() {
|
||||
const userFields = this.userFields;
|
||||
let userCustomFields = {};
|
||||
if (!isEmpty(userFields)) {
|
||||
userFields.forEach(function (f) {
|
||||
userCustomFields[f.get("field.id")] = f.get("value");
|
||||
});
|
||||
}
|
||||
|
||||
const data = {
|
||||
username: this.accountUsername,
|
||||
name: this.accountName,
|
||||
password: this.accountPassword,
|
||||
user_custom_fields: userCustomFields,
|
||||
timezone: moment.tz.guess(),
|
||||
};
|
||||
|
||||
if (this.isInviteLink) {
|
||||
data.email = this.email;
|
||||
} else {
|
||||
data.email_token = this.t;
|
||||
}
|
||||
|
||||
ajax({
|
||||
url: `/invites/show/${this.get("model.token")}.json`,
|
||||
type: "PUT",
|
||||
data,
|
||||
})
|
||||
.then((result) => {
|
||||
if (result.success) {
|
||||
this.set(
|
||||
"successMessage",
|
||||
result.message || I18n.t("invites.success")
|
||||
);
|
||||
if (result.redirect_to) {
|
||||
DiscourseURL.redirectTo(result.redirect_to);
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
result.errors &&
|
||||
result.errors.email &&
|
||||
result.errors.email.length > 0 &&
|
||||
result.values
|
||||
) {
|
||||
this.rejectedEmails.pushObject(result.values.email);
|
||||
}
|
||||
if (
|
||||
result.errors &&
|
||||
result.errors.password &&
|
||||
result.errors.password.length > 0
|
||||
) {
|
||||
this.rejectedPasswords.pushObject(this.accountPassword);
|
||||
this.rejectedPasswordsMessages.set(
|
||||
this.accountPassword,
|
||||
result.errors.password[0]
|
||||
);
|
||||
}
|
||||
if (result.message) {
|
||||
this.set("errorMessage", result.message);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.set("errorMessage", extractError(error));
|
||||
});
|
||||
},
|
||||
|
||||
externalLogin(provider) {
|
||||
provider.doLogin({
|
||||
signup: true,
|
||||
params: {
|
||||
origin: window.location.href,
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
return EmberObject.create({
|
||||
failed: true,
|
||||
reason: I18n.t("user.email.invalid"),
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
authProviderDisplayName(providerName) {
|
||||
const matchingProvider = findLoginMethods().find((provider) => {
|
||||
return provider.name === providerName;
|
||||
});
|
||||
return matchingProvider ? matchingProvider.get("prettyName") : providerName;
|
||||
}
|
||||
|
||||
@discourseComputed
|
||||
wavingHandURL() {
|
||||
return wavingHandURL();
|
||||
}
|
||||
|
||||
@discourseComputed
|
||||
ssoPath() {
|
||||
return getUrl("/session/sso");
|
||||
}
|
||||
|
||||
@discourseComputed
|
||||
disclaimerHtml() {
|
||||
if (this.site.tos_url && this.site.privacy_policy_url) {
|
||||
return I18n.t("create_account.disclaimer", {
|
||||
tos_link: this.site.tos_url,
|
||||
privacy_link: this.site.privacy_policy_url,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@discourseComputed("authOptions.associate_url", "authOptions.auth_provider")
|
||||
associateHtml(url, provider) {
|
||||
if (!url) {
|
||||
return;
|
||||
}
|
||||
return I18n.t("create_account.associate", {
|
||||
associate_link: url,
|
||||
provider: I18n.t(`login.${provider}.name`),
|
||||
});
|
||||
}
|
||||
|
||||
@action
|
||||
togglePasswordMask() {
|
||||
this.toggleProperty("maskPassword");
|
||||
}
|
||||
|
||||
@action
|
||||
submit() {
|
||||
const userFields = this.userFields;
|
||||
let userCustomFields = {};
|
||||
if (!isEmpty(userFields)) {
|
||||
userFields.forEach(function (f) {
|
||||
userCustomFields[f.get("field.id")] = f.get("value");
|
||||
});
|
||||
}
|
||||
|
||||
const data = {
|
||||
username: this.accountUsername,
|
||||
name: this.accountName,
|
||||
password: this.accountPassword,
|
||||
user_custom_fields: userCustomFields,
|
||||
timezone: moment.tz.guess(),
|
||||
};
|
||||
|
||||
if (this.isInviteLink) {
|
||||
data.email = this.email;
|
||||
} else {
|
||||
data.email_token = this.t;
|
||||
}
|
||||
|
||||
ajax({
|
||||
url: `/invites/show/${this.get("model.token")}.json`,
|
||||
type: "PUT",
|
||||
data,
|
||||
})
|
||||
.then((result) => {
|
||||
if (result.success) {
|
||||
this.set(
|
||||
"successMessage",
|
||||
result.message || I18n.t("invites.success")
|
||||
);
|
||||
if (result.redirect_to) {
|
||||
DiscourseURL.redirectTo(result.redirect_to);
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
result.errors &&
|
||||
result.errors.email &&
|
||||
result.errors.email.length > 0 &&
|
||||
result.values
|
||||
) {
|
||||
this.rejectedEmails.pushObject(result.values.email);
|
||||
}
|
||||
if (
|
||||
result.errors &&
|
||||
result.errors.password &&
|
||||
result.errors.password.length > 0
|
||||
) {
|
||||
this.rejectedPasswords.pushObject(this.accountPassword);
|
||||
this.rejectedPasswordsMessages.set(
|
||||
this.accountPassword,
|
||||
result.errors.password[0]
|
||||
);
|
||||
}
|
||||
if (result.message) {
|
||||
this.set("errorMessage", result.message);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.set("errorMessage", extractError(error));
|
||||
});
|
||||
}
|
||||
|
||||
@action
|
||||
externalLogin(provider) {
|
||||
provider.doLogin({
|
||||
signup: true,
|
||||
params: {
|
||||
origin: window.location.href,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -11,23 +11,26 @@ import getURL from "discourse-common/lib/get-url";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import I18n from "discourse-i18n";
|
||||
|
||||
export default Controller.extend(PasswordValidation, {
|
||||
isDeveloper: alias("model.is_developer"),
|
||||
admin: alias("model.admin"),
|
||||
secondFactorRequired: alias("model.second_factor_required"),
|
||||
securityKeyRequired: alias("model.security_key_required"),
|
||||
backupEnabled: alias("model.backup_enabled"),
|
||||
securityKeyOrSecondFactorRequired: or(
|
||||
"model.second_factor_required",
|
||||
"model.security_key_required"
|
||||
),
|
||||
otherMethodAllowed: readOnly("model.multiple_second_factor_methods"),
|
||||
passwordRequired: true,
|
||||
errorMessage: null,
|
||||
successMessage: null,
|
||||
requiresApproval: false,
|
||||
redirected: false,
|
||||
maskPassword: true,
|
||||
export default class PasswordResetController extends Controller.extend(
|
||||
PasswordValidation
|
||||
) {
|
||||
@alias("model.is_developer") isDeveloper;
|
||||
@alias("model.admin") admin;
|
||||
@alias("model.second_factor_required") secondFactorRequired;
|
||||
@alias("model.security_key_required") securityKeyRequired;
|
||||
@alias("model.backup_enabled") backupEnabled;
|
||||
@or("model.second_factor_required", "model.security_key_required")
|
||||
securityKeyOrSecondFactorRequired;
|
||||
@readOnly("model.multiple_second_factor_methods") otherMethodAllowed;
|
||||
|
||||
passwordRequired = true;
|
||||
errorMessage = null;
|
||||
successMessage = null;
|
||||
requiresApproval = false;
|
||||
redirected = false;
|
||||
maskPassword = true;
|
||||
|
||||
lockImageUrl = getURL("/images/lock.svg");
|
||||
|
||||
@discourseComputed("securityKeyRequired", "selectedSecondFactorMethod")
|
||||
displaySecurityKeyForm(securityKeyRequired, selectedSecondFactorMethod) {
|
||||
@ -35,7 +38,7 @@ export default Controller.extend(PasswordValidation, {
|
||||
securityKeyRequired &&
|
||||
selectedSecondFactorMethod === SECOND_FACTOR_METHODS.SECURITY_KEY
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
initSelectedSecondFactorMethod() {
|
||||
if (this.model.security_key_required) {
|
||||
@ -48,21 +51,19 @@ export default Controller.extend(PasswordValidation, {
|
||||
} else if (this.model.backup_enabled) {
|
||||
this.set("selectedSecondFactorMethod", SECOND_FACTOR_METHODS.BACKUP_CODE);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed()
|
||||
continueButtonText() {
|
||||
return I18n.t("password_reset.continue", {
|
||||
site_name: this.siteSettings.title,
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("redirectTo")
|
||||
redirectHref(redirectTo) {
|
||||
return getURL(redirectTo || "/");
|
||||
},
|
||||
|
||||
lockImageUrl: getURL("/images/lock.svg"),
|
||||
}
|
||||
|
||||
@action
|
||||
done(event) {
|
||||
@ -73,12 +74,12 @@ export default Controller.extend(PasswordValidation, {
|
||||
event.preventDefault();
|
||||
this.set("redirected", true);
|
||||
DiscourseURL.redirectTo(this.redirectTo || "/");
|
||||
},
|
||||
}
|
||||
|
||||
@action
|
||||
togglePasswordMask() {
|
||||
this.toggleProperty("maskPassword");
|
||||
},
|
||||
}
|
||||
|
||||
@action
|
||||
async submit() {
|
||||
@ -138,7 +139,7 @@ export default Controller.extend(PasswordValidation, {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@action
|
||||
authenticateSecurityKey() {
|
||||
@ -159,5 +160,5 @@ export default Controller.extend(PasswordValidation, {
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
import Controller from "@ember/controller";
|
||||
|
||||
export default Controller.extend({});
|
||||
export default class PreferencesController extends Controller {}
|
||||
|
@ -1,12 +1,13 @@
|
||||
import Controller from "@ember/controller";
|
||||
import { action } from "@ember/object";
|
||||
import { next } from "@ember/runloop";
|
||||
import { underscore } from "@ember/string";
|
||||
import { isPresent } from "@ember/utils";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import I18n from "discourse-i18n";
|
||||
|
||||
export default Controller.extend({
|
||||
queryParams: [
|
||||
export default class ReviewIndexController extends Controller {
|
||||
queryParams = [
|
||||
"priority",
|
||||
"type",
|
||||
"status",
|
||||
@ -18,26 +19,21 @@ export default Controller.extend({
|
||||
"to_date",
|
||||
"sort_order",
|
||||
"additional_filters",
|
||||
],
|
||||
type: null,
|
||||
status: "pending",
|
||||
priority: "low",
|
||||
category_id: null,
|
||||
reviewables: null,
|
||||
topic_id: null,
|
||||
filtersExpanded: false,
|
||||
username: "",
|
||||
reviewed_by: "",
|
||||
from_date: null,
|
||||
to_date: null,
|
||||
sort_order: null,
|
||||
additional_filters: null,
|
||||
];
|
||||
|
||||
init(...args) {
|
||||
this._super(...args);
|
||||
this.set("priority", this.siteSettings.reviewable_default_visibility);
|
||||
this.set("filtersExpanded", this.site.desktopView);
|
||||
},
|
||||
type = null;
|
||||
status = "pending";
|
||||
priority = this.siteSettings.reviewable_default_visibility;
|
||||
category_id = null;
|
||||
reviewables = null;
|
||||
topic_id = null;
|
||||
filtersExpanded = this.site.desktopView;
|
||||
username = "";
|
||||
reviewed_by = "";
|
||||
from_date = null;
|
||||
to_date = null;
|
||||
sort_order = null;
|
||||
additional_filters = null;
|
||||
|
||||
@discourseComputed("reviewableTypes")
|
||||
allTypes() {
|
||||
@ -49,7 +45,7 @@ export default Controller.extend({
|
||||
name: I18n.t(`review.types.${translationKey}.title`),
|
||||
};
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed
|
||||
priorities() {
|
||||
@ -59,7 +55,7 @@ export default Controller.extend({
|
||||
name: I18n.t(`review.filters.priority.${priority}`),
|
||||
};
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed
|
||||
sortOrders() {
|
||||
@ -71,7 +67,7 @@ export default Controller.extend({
|
||||
};
|
||||
}
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed
|
||||
statuses() {
|
||||
@ -86,110 +82,115 @@ export default Controller.extend({
|
||||
].map((id) => {
|
||||
return { id, name: I18n.t(`review.statuses.${id}.title`) };
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("filtersExpanded")
|
||||
toggleFiltersIcon(filtersExpanded) {
|
||||
return filtersExpanded ? "chevron-up" : "chevron-down";
|
||||
},
|
||||
}
|
||||
|
||||
setRange(range) {
|
||||
this.setProperties(range);
|
||||
},
|
||||
}
|
||||
|
||||
refreshModel() {
|
||||
next(() => this.send("refreshRoute"));
|
||||
},
|
||||
}
|
||||
|
||||
actions: {
|
||||
remove(ids) {
|
||||
if (!ids) {
|
||||
return;
|
||||
}
|
||||
@action
|
||||
remove(ids) {
|
||||
if (!ids) {
|
||||
return;
|
||||
}
|
||||
|
||||
let newList = this.reviewables.reject((reviewable) => {
|
||||
return ids.includes(reviewable.id);
|
||||
});
|
||||
let newList = this.reviewables.reject((reviewable) => {
|
||||
return ids.includes(reviewable.id);
|
||||
});
|
||||
|
||||
if (newList.length === 0) {
|
||||
this.refreshModel();
|
||||
} else {
|
||||
this.reviewables.setObjects(newList);
|
||||
}
|
||||
},
|
||||
|
||||
resetTopic() {
|
||||
this.set("topic_id", null);
|
||||
if (newList.length === 0) {
|
||||
this.refreshModel();
|
||||
},
|
||||
} else {
|
||||
this.reviewables.setObjects(newList);
|
||||
}
|
||||
}
|
||||
|
||||
refresh() {
|
||||
const currentStatus = this.status;
|
||||
const nextStatus = this.filterStatus;
|
||||
const currentOrder = this.sort_order;
|
||||
let nextOrder = this.filterSortOrder;
|
||||
@action
|
||||
resetTopic() {
|
||||
this.set("topic_id", null);
|
||||
this.refreshModel();
|
||||
}
|
||||
|
||||
const createdAtStatuses = ["reviewed", "all"];
|
||||
const priorityStatuses = [
|
||||
"approved",
|
||||
"rejected",
|
||||
"deleted",
|
||||
"ignored",
|
||||
"pending",
|
||||
];
|
||||
@action
|
||||
refresh() {
|
||||
const currentStatus = this.status;
|
||||
const nextStatus = this.filterStatus;
|
||||
const currentOrder = this.sort_order;
|
||||
let nextOrder = this.filterSortOrder;
|
||||
|
||||
if (
|
||||
createdAtStatuses.includes(currentStatus) &&
|
||||
currentOrder === "created_at" &&
|
||||
priorityStatuses.includes(nextStatus) &&
|
||||
nextOrder === "created_at"
|
||||
) {
|
||||
nextOrder = "score";
|
||||
}
|
||||
const createdAtStatuses = ["reviewed", "all"];
|
||||
const priorityStatuses = [
|
||||
"approved",
|
||||
"rejected",
|
||||
"deleted",
|
||||
"ignored",
|
||||
"pending",
|
||||
];
|
||||
|
||||
if (
|
||||
priorityStatuses.includes(currentStatus) &&
|
||||
currentOrder === "score" &&
|
||||
createdAtStatuses.includes(nextStatus) &&
|
||||
nextOrder === "score"
|
||||
) {
|
||||
nextOrder = "created_at";
|
||||
}
|
||||
if (
|
||||
createdAtStatuses.includes(currentStatus) &&
|
||||
currentOrder === "created_at" &&
|
||||
priorityStatuses.includes(nextStatus) &&
|
||||
nextOrder === "created_at"
|
||||
) {
|
||||
nextOrder = "score";
|
||||
}
|
||||
|
||||
this.setProperties({
|
||||
type: this.filterType,
|
||||
priority: this.filterPriority,
|
||||
status: this.filterStatus,
|
||||
category_id: this.filterCategoryId,
|
||||
username: this.filterUsername,
|
||||
reviewed_by: this.filterReviewedBy,
|
||||
from_date: isPresent(this.filterFromDate)
|
||||
? this.filterFromDate.toISOString(true).split("T")[0]
|
||||
: null,
|
||||
to_date: isPresent(this.filterToDate)
|
||||
? this.filterToDate.toISOString(true).split("T")[0]
|
||||
: null,
|
||||
sort_order: nextOrder,
|
||||
additional_filters: JSON.stringify(this.additionalFilters),
|
||||
});
|
||||
if (
|
||||
priorityStatuses.includes(currentStatus) &&
|
||||
currentOrder === "score" &&
|
||||
createdAtStatuses.includes(nextStatus) &&
|
||||
nextOrder === "score"
|
||||
) {
|
||||
nextOrder = "created_at";
|
||||
}
|
||||
|
||||
this.refreshModel();
|
||||
},
|
||||
this.setProperties({
|
||||
type: this.filterType,
|
||||
priority: this.filterPriority,
|
||||
status: this.filterStatus,
|
||||
category_id: this.filterCategoryId,
|
||||
username: this.filterUsername,
|
||||
reviewed_by: this.filterReviewedBy,
|
||||
from_date: isPresent(this.filterFromDate)
|
||||
? this.filterFromDate.toISOString(true).split("T")[0]
|
||||
: null,
|
||||
to_date: isPresent(this.filterToDate)
|
||||
? this.filterToDate.toISOString(true).split("T")[0]
|
||||
: null,
|
||||
sort_order: nextOrder,
|
||||
additional_filters: JSON.stringify(this.additionalFilters),
|
||||
});
|
||||
|
||||
loadMore() {
|
||||
return this.reviewables.loadMore();
|
||||
},
|
||||
this.refreshModel();
|
||||
}
|
||||
|
||||
toggleFilters() {
|
||||
this.toggleProperty("filtersExpanded");
|
||||
},
|
||||
@action
|
||||
loadMore() {
|
||||
return this.reviewables.loadMore();
|
||||
}
|
||||
|
||||
updateFilterReviewedBy(selected) {
|
||||
this.set("filterReviewedBy", selected.firstObject);
|
||||
},
|
||||
@action
|
||||
toggleFilters() {
|
||||
this.toggleProperty("filtersExpanded");
|
||||
}
|
||||
|
||||
updateFilterUsername(selected) {
|
||||
this.set("filterUsername", selected.firstObject);
|
||||
},
|
||||
},
|
||||
});
|
||||
@action
|
||||
updateFilterReviewedBy(selected) {
|
||||
this.set("filterReviewedBy", selected.firstObject);
|
||||
}
|
||||
|
||||
@action
|
||||
updateFilterUsername(selected) {
|
||||
this.set("filterUsername", selected.firstObject);
|
||||
}
|
||||
}
|
||||
|
@ -1,32 +1,32 @@
|
||||
import Controller from "@ember/controller";
|
||||
import { action } from "@ember/object";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import I18n from "discourse-i18n";
|
||||
|
||||
export default Controller.extend({
|
||||
saving: false,
|
||||
saved: false,
|
||||
export default class ReviewSettingsController extends Controller {
|
||||
saving = false;
|
||||
saved = false;
|
||||
|
||||
actions: {
|
||||
save() {
|
||||
let priorities = {};
|
||||
this.scoreTypes.forEach((st) => {
|
||||
priorities[st.id] = parseFloat(st.reviewable_priority);
|
||||
});
|
||||
@action
|
||||
save() {
|
||||
let priorities = {};
|
||||
this.scoreTypes.forEach((st) => {
|
||||
priorities[st.id] = parseFloat(st.reviewable_priority);
|
||||
});
|
||||
|
||||
this.set("saving", true);
|
||||
ajax("/review/settings", {
|
||||
type: "PUT",
|
||||
data: { reviewable_priorities: priorities },
|
||||
this.set("saving", true);
|
||||
ajax("/review/settings", {
|
||||
type: "PUT",
|
||||
data: { reviewable_priorities: priorities },
|
||||
})
|
||||
.then(() => {
|
||||
this.set("saved", true);
|
||||
})
|
||||
.then(() => {
|
||||
this.set("saved", true);
|
||||
})
|
||||
.catch(popupAjaxError)
|
||||
.finally(() => this.set("saving", false));
|
||||
},
|
||||
},
|
||||
.catch(popupAjaxError)
|
||||
.finally(() => this.set("saving", false));
|
||||
}
|
||||
|
||||
@discourseComputed("settings.reviewable_score_types")
|
||||
scoreTypes(types) {
|
||||
@ -36,5 +36,5 @@ export default Controller.extend({
|
||||
...type,
|
||||
title: type.title.replace("%{username}", username),
|
||||
}));
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -10,45 +10,42 @@ import discourseComputed from "discourse-common/utils/decorators";
|
||||
import I18n from "discourse-i18n";
|
||||
|
||||
const { TOTP, BACKUP_CODE, SECURITY_KEY } = SECOND_FACTOR_METHODS;
|
||||
export default Controller.extend({
|
||||
TOTP,
|
||||
BACKUP_CODE,
|
||||
SECURITY_KEY,
|
||||
export default class SecondFactorAuthController extends Controller {
|
||||
TOTP = TOTP;
|
||||
BACKUP_CODE = BACKUP_CODE;
|
||||
SECURITY_KEY = SECURITY_KEY;
|
||||
queryParams = ["nonce"];
|
||||
message = null;
|
||||
loadError = false;
|
||||
messageIsError = false;
|
||||
secondFactorToken = null;
|
||||
userSelectedMethod = null;
|
||||
|
||||
queryParams: ["nonce"],
|
||||
|
||||
message: null,
|
||||
loadError: false,
|
||||
messageIsError: false,
|
||||
secondFactorToken: null,
|
||||
userSelectedMethod: null,
|
||||
|
||||
totpEnabled: readOnly("model.totp_enabled"),
|
||||
backupCodesEnabled: readOnly("model.backup_enabled"),
|
||||
securityKeysEnabled: readOnly("model.security_keys_enabled"),
|
||||
allowedMethods: readOnly("model.allowed_methods"),
|
||||
customDescription: readOnly("model.description"),
|
||||
|
||||
showTotpForm: equal("shownSecondFactorMethod", TOTP),
|
||||
showSecurityKeyForm: equal("shownSecondFactorMethod", SECURITY_KEY),
|
||||
showBackupCodesForm: equal("shownSecondFactorMethod", BACKUP_CODE),
|
||||
@readOnly("model.totp_enabled") totpEnabled;
|
||||
@readOnly("model.backup_enabled") backupCodesEnabled;
|
||||
@readOnly("model.security_keys_enabled") securityKeysEnabled;
|
||||
@readOnly("model.allowed_methods") allowedMethods;
|
||||
@readOnly("model.description") customDescription;
|
||||
@equal("shownSecondFactorMethod", TOTP) showTotpForm;
|
||||
@equal("shownSecondFactorMethod", SECURITY_KEY) showSecurityKeyForm;
|
||||
@equal("shownSecondFactorMethod", BACKUP_CODE) showBackupCodesForm;
|
||||
|
||||
@discourseComputed("allowedMethods.[]", "totpEnabled")
|
||||
totpAvailable() {
|
||||
return this.totpEnabled && this.allowedMethods.includes(TOTP);
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("allowedMethods.[]", "backupCodesEnabled")
|
||||
backupCodesAvailable() {
|
||||
return this.backupCodesEnabled && this.allowedMethods.includes(BACKUP_CODE);
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("allowedMethods.[]", "securityKeysEnabled")
|
||||
securityKeysAvailable() {
|
||||
return (
|
||||
this.securityKeysEnabled && this.allowedMethods.includes(SECURITY_KEY)
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed(
|
||||
"userSelectedMethod",
|
||||
@ -75,7 +72,7 @@ export default Controller.extend({
|
||||
throw new Error("unexpected state of user 2fa settings!");
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed(
|
||||
"shownSecondFactorMethod",
|
||||
@ -115,7 +112,7 @@ export default Controller.extend({
|
||||
}
|
||||
|
||||
return alts;
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("shownSecondFactorMethod")
|
||||
secondFactorTitle(shownSecondFactorMethod) {
|
||||
@ -127,7 +124,7 @@ export default Controller.extend({
|
||||
case BACKUP_CODE:
|
||||
return I18n.t("login.second_factor_backup_title");
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("shownSecondFactorMethod")
|
||||
secondFactorDescription(shownSecondFactorMethod) {
|
||||
@ -139,7 +136,7 @@ export default Controller.extend({
|
||||
case BACKUP_CODE:
|
||||
return I18n.t("login.second_factor_backup_description");
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("messageIsError")
|
||||
alertClass(messageIsError) {
|
||||
@ -148,7 +145,7 @@ export default Controller.extend({
|
||||
} else {
|
||||
return "alert-success";
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("showTotpForm", "showBackupCodesForm")
|
||||
inputFormClass(showTotpForm, showBackupCodesForm) {
|
||||
@ -157,7 +154,7 @@ export default Controller.extend({
|
||||
} else if (showBackupCodesForm) {
|
||||
return "backup-code-token";
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
resetState() {
|
||||
this.set("message", null);
|
||||
@ -165,17 +162,17 @@ export default Controller.extend({
|
||||
this.set("secondFactorToken", null);
|
||||
this.set("userSelectedMethod", null);
|
||||
this.set("loadError", false);
|
||||
},
|
||||
}
|
||||
|
||||
displayError(message) {
|
||||
this.set("message", message);
|
||||
this.set("messageIsError", true);
|
||||
},
|
||||
}
|
||||
|
||||
displaySuccess(message) {
|
||||
this.set("message", message);
|
||||
this.set("messageIsError", false);
|
||||
},
|
||||
}
|
||||
|
||||
verifySecondFactor(data) {
|
||||
return ajax("/session/2fa", {
|
||||
@ -207,13 +204,13 @@ export default Controller.extend({
|
||||
.catch((error) => {
|
||||
this.displayError(extractError(error));
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
@action
|
||||
useAnotherMethod(newMethod, event) {
|
||||
event?.preventDefault();
|
||||
this.set("userSelectedMethod", newMethod);
|
||||
},
|
||||
}
|
||||
|
||||
@action
|
||||
authenticateSecurityKey() {
|
||||
@ -227,10 +224,10 @@ export default Controller.extend({
|
||||
this.displayError(errorMessage);
|
||||
}
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
@action
|
||||
authenticateToken() {
|
||||
this.verifySecondFactor({ second_factor_token: this.secondFactorToken });
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
import Controller, { inject as controller } from "@ember/controller";
|
||||
import { action } from "@ember/object";
|
||||
import { service } from "@ember/service";
|
||||
|
||||
export default Controller.extend({
|
||||
router: service(),
|
||||
tagGroups: controller(),
|
||||
export default class TagGroupsEditController extends Controller {
|
||||
@service router;
|
||||
@controller tagGroups;
|
||||
|
||||
actions: {
|
||||
onDestroy() {
|
||||
const tagGroups = this.tagGroups.model;
|
||||
tagGroups.removeObject(this.model);
|
||||
@action
|
||||
onDestroy() {
|
||||
const tagGroups = this.tagGroups.model;
|
||||
tagGroups.removeObject(this.model);
|
||||
|
||||
this.router.transitionTo("tagGroups.index");
|
||||
},
|
||||
},
|
||||
});
|
||||
this.router.transitionTo("tagGroups.index");
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
import Controller, { inject as controller } from "@ember/controller";
|
||||
import { action } from "@ember/object";
|
||||
import { service } from "@ember/service";
|
||||
|
||||
export default Controller.extend({
|
||||
router: service(),
|
||||
tagGroups: controller(),
|
||||
export default class TagGroupsNewController extends Controller {
|
||||
@service router;
|
||||
@controller tagGroups;
|
||||
|
||||
actions: {
|
||||
onSave() {
|
||||
const tagGroups = this.tagGroups.model;
|
||||
tagGroups.pushObject(this.model);
|
||||
@action
|
||||
onSave() {
|
||||
const tagGroups = this.tagGroups.model;
|
||||
tagGroups.pushObject(this.model);
|
||||
|
||||
this.router.transitionTo("tagGroups.index");
|
||||
},
|
||||
},
|
||||
});
|
||||
this.router.transitionTo("tagGroups.index");
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
import Controller from "@ember/controller";
|
||||
import { action } from "@ember/object";
|
||||
import { service } from "@ember/service";
|
||||
|
||||
export default Controller.extend({
|
||||
router: service(),
|
||||
export default class TagGroupsController extends Controller {
|
||||
@service router;
|
||||
|
||||
actions: {
|
||||
newTagGroup() {
|
||||
this.router.transitionTo("tagGroups.new");
|
||||
},
|
||||
},
|
||||
});
|
||||
@action
|
||||
newTagGroup() {
|
||||
this.router.transitionTo("tagGroups.new");
|
||||
}
|
||||
}
|
||||
|
@ -8,18 +8,20 @@ import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import I18n from "discourse-i18n";
|
||||
|
||||
export default Controller.extend({
|
||||
dialog: service(),
|
||||
modal: service(),
|
||||
sortedByCount: true,
|
||||
sortedByName: false,
|
||||
sortAlphabetically: alias("siteSettings.tags_sort_alphabetically"),
|
||||
canAdminTags: alias("currentUser.staff"),
|
||||
groupedByCategory: notEmpty("model.extras.categories"),
|
||||
groupedByTagGroup: notEmpty("model.extras.tag_groups"),
|
||||
export default class TagsIndexController extends Controller {
|
||||
@service dialog;
|
||||
@service modal;
|
||||
|
||||
sortedByCount = true;
|
||||
sortedByName = false;
|
||||
|
||||
@alias("siteSettings.tags_sort_alphabetically") sortAlphabetically;
|
||||
@alias("currentUser.staff") canAdminTags;
|
||||
@notEmpty("model.extras.categories") groupedByCategory;
|
||||
@notEmpty("model.extras.tag_groups") groupedByTagGroup;
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
super.init(...arguments);
|
||||
|
||||
const isAlphaSort = this.sortAlphabetically;
|
||||
|
||||
@ -28,7 +30,7 @@ export default Controller.extend({
|
||||
sortedByName: isAlphaSort ? true : false,
|
||||
sortProperties: isAlphaSort ? ["id"] : ["totalCount:desc", "id"],
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed("groupedByCategory", "groupedByTagGroup")
|
||||
otherTagsTitleKey(groupedByCategory, groupedByTagGroup) {
|
||||
@ -37,7 +39,7 @@ export default Controller.extend({
|
||||
} else {
|
||||
return "tagging.other_tags";
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@discourseComputed
|
||||
actionsMapping() {
|
||||
@ -46,7 +48,7 @@ export default Controller.extend({
|
||||
uploadTags: () => this.send("showUploader"),
|
||||
deleteUnusedTags: () => this.send("deleteUnused"),
|
||||
};
|
||||
},
|
||||
}
|
||||
|
||||
@action
|
||||
sortByCount(event) {
|
||||
@ -56,7 +58,7 @@ export default Controller.extend({
|
||||
sortedByCount: true,
|
||||
sortedByName: false,
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
@action
|
||||
sortById(event) {
|
||||
@ -66,53 +68,53 @@ export default Controller.extend({
|
||||
sortedByCount: false,
|
||||
sortedByName: true,
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
actions: {
|
||||
showUploader() {
|
||||
this.modal.show(TagUpload);
|
||||
},
|
||||
@action
|
||||
showUploader() {
|
||||
this.modal.show(TagUpload);
|
||||
}
|
||||
|
||||
deleteUnused() {
|
||||
ajax("/tags/unused", { type: "GET" })
|
||||
.then((result) => {
|
||||
const displayN = 20;
|
||||
const tags = result["tags"];
|
||||
@action
|
||||
deleteUnused() {
|
||||
ajax("/tags/unused", { type: "GET" })
|
||||
.then((result) => {
|
||||
const displayN = 20;
|
||||
const tags = result["tags"];
|
||||
|
||||
if (tags.length === 0) {
|
||||
this.dialog.alert(I18n.t("tagging.delete_no_unused_tags"));
|
||||
return;
|
||||
}
|
||||
if (tags.length === 0) {
|
||||
this.dialog.alert(I18n.t("tagging.delete_no_unused_tags"));
|
||||
return;
|
||||
}
|
||||
|
||||
const joinedTags = tags
|
||||
.slice(0, displayN)
|
||||
.join(I18n.t("tagging.tag_list_joiner"));
|
||||
const more = Math.max(0, tags.length - displayN);
|
||||
const joinedTags = tags
|
||||
.slice(0, displayN)
|
||||
.join(I18n.t("tagging.tag_list_joiner"));
|
||||
const more = Math.max(0, tags.length - displayN);
|
||||
|
||||
const tagsString =
|
||||
more === 0
|
||||
? joinedTags
|
||||
: I18n.t("tagging.delete_unused_confirmation_more_tags", {
|
||||
count: more,
|
||||
tags: joinedTags,
|
||||
});
|
||||
const tagsString =
|
||||
more === 0
|
||||
? joinedTags
|
||||
: I18n.t("tagging.delete_unused_confirmation_more_tags", {
|
||||
count: more,
|
||||
tags: joinedTags,
|
||||
});
|
||||
|
||||
const message = I18n.t("tagging.delete_unused_confirmation", {
|
||||
count: tags.length,
|
||||
tags: tagsString,
|
||||
});
|
||||
const message = I18n.t("tagging.delete_unused_confirmation", {
|
||||
count: tags.length,
|
||||
tags: tagsString,
|
||||
});
|
||||
|
||||
this.dialog.deleteConfirm({
|
||||
message,
|
||||
confirmButtonLabel: "tagging.delete_unused",
|
||||
didConfirm: () => {
|
||||
return ajax("/tags/unused", { type: "DELETE" })
|
||||
.then(() => this.send("triggerRefresh"))
|
||||
.catch(popupAjaxError);
|
||||
},
|
||||
});
|
||||
})
|
||||
.catch(popupAjaxError);
|
||||
},
|
||||
},
|
||||
});
|
||||
this.dialog.deleteConfirm({
|
||||
message,
|
||||
confirmButtonLabel: "tagging.delete_unused",
|
||||
didConfirm: () => {
|
||||
return ajax("/tags/unused", { type: "DELETE" })
|
||||
.then(() => this.send("triggerRefresh"))
|
||||
.catch(popupAjaxError);
|
||||
},
|
||||
});
|
||||
})
|
||||
.catch(popupAjaxError);
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user