FEATURE: Allow changing slug on create channel (#19928)

This commit allows us to set the channel slug when creating new chat
channels. As well as this, it introduces a new `SlugsController` which can
generate a slug using `Slug.for` and a name string for input. We call this
after the user finishes typing the channel name (debounced) and fill in
the autogenerated slug in the background, and update the slug input
placeholder.

This autogenerated slug is used by default, but if the user writes anything
else in the input it will be used instead.
This commit is contained in:
Martin Brennan
2023-01-23 14:48:33 +10:00
committed by GitHub
parent ae20ce8654
commit 641e94fc3c
14 changed files with 322 additions and 48 deletions

View File

@ -1,4 +1,7 @@
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";
@ -26,6 +29,8 @@ export default class CreateChannelController extends Controller.extend(
category = null;
categoryId = null;
name = "";
slug = "";
autoGeneratedSlug = "";
description = "";
categoryPermissionsHint = null;
autoJoinUsers = null;
@ -51,11 +56,14 @@ export default class CreateChannelController extends Controller.extend(
}
onClose() {
cancel(this.generateSlugHandler);
this.setProperties({
categoryId: null,
category: null,
name: "",
description: "",
slug: "",
autoGeneratedSlug: "",
categoryPermissionsHint: DEFAULT_HINT,
autoJoinWarning: "",
});
@ -65,6 +73,7 @@ export default class CreateChannelController extends Controller.extend(
const data = {
chatable_id: this.categoryId,
name: this.name,
slug: this.slug || this.autoGeneratedSlug,
description: this.description,
auto_join_users: this.autoJoinUsers,
};
@ -147,17 +156,53 @@ export default class CreateChannelController extends Controller.extend(
}
}
// intentionally not showing AJAX error for this, we will autogenerate
// the slug server-side if they leave it blank
_generateSlug(name) {
ajax("/slugs/generate.json", { type: "GET", 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.name || category?.name || "",
name,
});
this._debouncedGenerateSlug(name);
}
@action
onNameChange(name) {
this._debouncedGenerateSlug(name);
}
@action

View File

@ -8,6 +8,20 @@
class="create-channel-name-input"
@type="text"
@value={{this.name}}
{{on "input" (action "onNameChange" value="target.value")}}
/>
</div>
<div class="create-channel-control">
<label for="channel-slug" class="create-channel-label">
{{i18n "chat.create_channel.slug"}}
</label>
<Input
name="channel-slug"
class="create-channel-slug-input"
@type="text"
@value={{this.slug}}
placeholder={{this.autoGeneratedSlug}}
/>
</div>