* FIX: Use pluralized string
* REFACTOR: Fix misuse of pluralized string
* REFACTOR: Fix misuse of pluralized string
* DEV: Remove linting of `one` key in MessageFormat string, it doesn't work
* REFACTOR: Fix misuse of pluralized string
This also ensures that the URL works on subfolder and shows the site setting link only for admins instead of staff. The string is quite complicated, so the best option was to switch to MessageFormat.
* REFACTOR: Fix misuse of pluralized string
* FIX: Use pluralized string
This also ensures that the URL works on subfolder and shows the site setting link only for admins instead of staff.
* REFACTOR: Correctly pluralize reaction tooltips in chat
This also ensures that maximum 5 usernames are shown and fixes the number of "others" which was off by 1 if the current user reacted on a message.
* REFACTOR: Use translatable string as comma separator
* DEV: Add comment to translation to clarify the meaning of `%{identifier}`
* REFACTOR: Use translatable comma separator and use explicit interpolation keys
* REFACTOR: Don't interpolate lowercase channel status
* REFACTOR: Fix misuse of pluralized string
* REFACTOR: Don't interpolate channel status
* REFACTOR: Use %{count} interpolation key
* REFACTOR: Fix misuse of pluralized string
* REFACTOR: Correctly pluralize DM chat channel titles
267 lines
7.0 KiB
JavaScript
267 lines
7.0 KiB
JavaScript
import { escapeExpression } from "discourse/lib/utilities";
|
|
import { ajax } from "discourse/lib/ajax";
|
|
import { cancel } from "@ember/runloop";
|
|
import discourseDebounce from "discourse-common/lib/debounce";
|
|
import Controller from "@ember/controller";
|
|
import I18n from "I18n";
|
|
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
|
import { action, computed } from "@ember/object";
|
|
import { gt, notEmpty } from "@ember/object/computed";
|
|
import { inject as service } from "@ember/service";
|
|
import { isBlank, isPresent } from "@ember/utils";
|
|
import { htmlSafe } from "@ember/template";
|
|
|
|
const DEFAULT_HINT = htmlSafe(
|
|
I18n.t("chat.create_channel.choose_category.default_hint", {
|
|
link: "/categories",
|
|
category: "category",
|
|
})
|
|
);
|
|
|
|
export default class CreateChannelController extends Controller.extend(
|
|
ModalFunctionality
|
|
) {
|
|
@service chat;
|
|
@service dialog;
|
|
@service chatChannelsManager;
|
|
@service chatApi;
|
|
@service router;
|
|
|
|
category = null;
|
|
categoryId = null;
|
|
name = "";
|
|
slug = "";
|
|
autoGeneratedSlug = "";
|
|
description = "";
|
|
categoryPermissionsHint = null;
|
|
autoJoinUsers = null;
|
|
autoJoinWarning = "";
|
|
|
|
@notEmpty("category") categorySelected;
|
|
@gt("siteSettings.max_chat_auto_joined_users", 0) autoJoinAvailable;
|
|
|
|
@computed("categorySelected", "name")
|
|
get createDisabled() {
|
|
return !this.categorySelected || isBlank(this.name);
|
|
}
|
|
|
|
@computed("categorySelected", "name")
|
|
get categoryName() {
|
|
return this.categorySelected && isPresent(this.name)
|
|
? escapeExpression(this.name)
|
|
: null;
|
|
}
|
|
|
|
onShow() {
|
|
this.set("categoryPermissionsHint", DEFAULT_HINT);
|
|
}
|
|
|
|
onClose() {
|
|
cancel(this.generateSlugHandler);
|
|
this.setProperties({
|
|
categoryId: null,
|
|
category: null,
|
|
name: "",
|
|
description: "",
|
|
slug: "",
|
|
autoGeneratedSlug: "",
|
|
categoryPermissionsHint: DEFAULT_HINT,
|
|
autoJoinWarning: "",
|
|
});
|
|
}
|
|
|
|
_createChannel() {
|
|
const data = {
|
|
chatable_id: this.categoryId,
|
|
name: this.name,
|
|
slug: this.slug || this.autoGeneratedSlug,
|
|
description: this.description,
|
|
auto_join_users: this.autoJoinUsers,
|
|
};
|
|
|
|
return this.chatApi
|
|
.createChannel(data)
|
|
.then((channel) => {
|
|
this.send("closeModal");
|
|
this.chatChannelsManager.follow(channel);
|
|
this.router.transitionTo("chat.channel", ...channel.routeModels);
|
|
})
|
|
.catch((e) => {
|
|
this.flash(e.jqXHR.responseJSON.errors[0], "error");
|
|
});
|
|
}
|
|
|
|
_buildCategorySlug(category) {
|
|
const parent = category.parentCategory;
|
|
|
|
if (parent) {
|
|
return `${this._buildCategorySlug(parent)}/${category.slug}`;
|
|
} else {
|
|
return category.slug;
|
|
}
|
|
}
|
|
|
|
_updateAutoJoinConfirmWarning(category, catPermissions) {
|
|
const allowedGroups = catPermissions.allowed_groups;
|
|
let warning;
|
|
|
|
if (catPermissions.private) {
|
|
switch (allowedGroups.length) {
|
|
case 1:
|
|
warning = I18n.t(
|
|
"chat.create_channel.auto_join_users.warning_1_group",
|
|
{
|
|
count: catPermissions.members_count,
|
|
group: escapeExpression(allowedGroups[0]),
|
|
}
|
|
);
|
|
break;
|
|
case 2:
|
|
warning = I18n.t(
|
|
"chat.create_channel.auto_join_users.warning_2_groups",
|
|
{
|
|
count: catPermissions.members_count,
|
|
group1: escapeExpression(allowedGroups[0]),
|
|
group2: escapeExpression(allowedGroups[1]),
|
|
}
|
|
);
|
|
break;
|
|
default:
|
|
warning = I18n.messageFormat(
|
|
"chat.create_channel.auto_join_users.warning_multiple_groups_MF",
|
|
{
|
|
groupCount: allowedGroups.length - 1,
|
|
userCount: catPermissions.members_count,
|
|
groupName: escapeExpression(allowedGroups[0]),
|
|
}
|
|
);
|
|
break;
|
|
}
|
|
} else {
|
|
this.set(
|
|
"autoJoinWarning",
|
|
I18n.t(`chat.create_channel.auto_join_users.public_category_warning`, {
|
|
category: escapeExpression(category.name),
|
|
})
|
|
);
|
|
}
|
|
|
|
this.set("autoJoinWarning", warning);
|
|
}
|
|
|
|
_updatePermissionsHint(category) {
|
|
if (category) {
|
|
const fullSlug = this._buildCategorySlug(category);
|
|
|
|
return this.chatApi
|
|
.categoryPermissions(category.id)
|
|
.then((catPermissions) => {
|
|
this._updateAutoJoinConfirmWarning(category, catPermissions);
|
|
const allowedGroups = catPermissions.allowed_groups;
|
|
const settingLink = `/c/${escapeExpression(fullSlug)}/edit/security`;
|
|
let hint;
|
|
|
|
switch (allowedGroups.length) {
|
|
case 1:
|
|
hint = I18n.t(
|
|
"chat.create_channel.choose_category.hint_1_group",
|
|
{
|
|
settingLink,
|
|
group: escapeExpression(allowedGroups[0]),
|
|
}
|
|
);
|
|
break;
|
|
case 2:
|
|
hint = I18n.t(
|
|
"chat.create_channel.choose_category.hint_2_groups",
|
|
{
|
|
settingLink,
|
|
group1: escapeExpression(allowedGroups[0]),
|
|
group2: escapeExpression(allowedGroups[1]),
|
|
}
|
|
);
|
|
break;
|
|
default:
|
|
hint = I18n.t(
|
|
"chat.create_channel.choose_category.hint_multiple_groups",
|
|
{
|
|
settingLink,
|
|
group: escapeExpression(allowedGroups[0]),
|
|
count: allowedGroups.length - 1,
|
|
}
|
|
);
|
|
break;
|
|
}
|
|
|
|
this.set("categoryPermissionsHint", htmlSafe(hint));
|
|
});
|
|
} else {
|
|
this.set("categoryPermissionsHint", DEFAULT_HINT);
|
|
this.set("autoJoinWarning", "");
|
|
}
|
|
}
|
|
|
|
// intentionally not showing AJAX error for this, we will autogenerate
|
|
// the slug server-side if they leave it blank
|
|
_generateSlug(name) {
|
|
ajax("/slugs.json", { type: "POST", data: { name } }).then((response) => {
|
|
this.set("autoGeneratedSlug", response.slug);
|
|
});
|
|
}
|
|
|
|
_debouncedGenerateSlug(name) {
|
|
cancel(this.generateSlugHandler);
|
|
this._clearAutoGeneratedSlug();
|
|
if (!name) {
|
|
return;
|
|
}
|
|
this.generateSlugHandler = discourseDebounce(
|
|
this,
|
|
this._generateSlug,
|
|
name,
|
|
300
|
|
);
|
|
}
|
|
|
|
_clearAutoGeneratedSlug() {
|
|
this.set("autoGeneratedSlug", "");
|
|
}
|
|
|
|
@action
|
|
onCategoryChange(categoryId) {
|
|
let category = categoryId
|
|
? this.site.categories.findBy("id", categoryId)
|
|
: null;
|
|
this._updatePermissionsHint(category);
|
|
|
|
const name = this.name || category?.name || "";
|
|
this.setProperties({
|
|
categoryId,
|
|
category,
|
|
name,
|
|
});
|
|
this._debouncedGenerateSlug(name);
|
|
}
|
|
|
|
@action
|
|
onNameChange(name) {
|
|
this._debouncedGenerateSlug(name);
|
|
}
|
|
|
|
@action
|
|
create() {
|
|
if (this.createDisabled) {
|
|
return;
|
|
}
|
|
|
|
if (this.autoJoinUsers) {
|
|
this.dialog.yesNoConfirm({
|
|
message: this.autoJoinWarning,
|
|
didConfirm: () => this._createChannel(),
|
|
});
|
|
} else {
|
|
this._createChannel();
|
|
}
|
|
}
|
|
}
|