diff --git a/app/assets/javascripts/discourse/app/components/edit-category-general.js b/app/assets/javascripts/discourse/app/components/edit-category-general.js index bab781b1f19..c041b7ecc82 100644 --- a/app/assets/javascripts/discourse/app/components/edit-category-general.js +++ b/app/assets/javascripts/discourse/app/components/edit-category-general.js @@ -9,32 +9,29 @@ import getURL from "discourse-common/lib/get-url"; import discourseLater from "discourse-common/lib/later"; import discourseComputed from "discourse-common/utils/decorators"; -export default buildCategoryPanel("general", { - init() { - this._super(...arguments); +export default class EditCategoryGeneral extends buildCategoryPanel("general") { + @not("category.isUncategorizedCategory") canSelectParentCategory; - this.foregroundColors = ["FFFFFF", "000000"]; - }, + uncategorizedSiteSettingLink = getURL( + "/admin/site_settings/category/all_results?filter=allow_uncategorized_topics" + ); + customizeTextContentLink = getURL( + "/admin/customize/site_texts?q=uncategorized" + ); + + foregroundColors = ["FFFFFF", "000000"]; didInsertElement() { - this._super(...arguments); + super.didInsertElement(...arguments); this._focusCategoryName(); - }, + } willDestroyElement() { - this._super(...arguments); + super.willDestroyElement(...arguments); this._laterFocus && cancel(this._laterFocus); - }, - - canSelectParentCategory: not("category.isUncategorizedCategory"), - uncategorizedSiteSettingLink: getURL( - "/admin/site_settings/category/all_results?filter=allow_uncategorized_topics" - ), - customizeTextContentLink: getURL( - "/admin/customize/site_texts?q=uncategorized" - ), + } // background colors are available as a pipe-separated string @discourseComputed @@ -51,7 +48,7 @@ export default buildCategoryPanel("general", { }) ) .uniq(); - }, + } @discourseComputed("category.id", "category.color") usedBackgroundColors(categoryId, categoryColor) { @@ -66,14 +63,14 @@ export default buildCategoryPanel("general", { : c.color.toUpperCase(); }, this) .compact(); - }, + } @discourseComputed parentCategories() { return this.site .get("categoriesList") .filter((c) => c.level + 1 < this.siteSettings.max_category_nesting); - }, + } @discourseComputed( "category.parent_category_id", @@ -92,7 +89,7 @@ export default buildCategoryPanel("general", { read_restricted: category.get("read_restricted"), }); return categoryBadgeHTML(c, { link: false, previewColor: true }); - }, + } // We can change the parent if there are no children @discourseComputed("category.id") @@ -101,7 +98,7 @@ export default buildCategoryPanel("general", { return null; } return Category.list().filterBy("parent_category_id", categoryId); - }, + } @discourseComputed( "category.isUncategorizedCategory", @@ -110,18 +107,18 @@ export default buildCategoryPanel("general", { ) showDescription(isUncategorizedCategory, categoryId, topicUrl) { return !isUncategorizedCategory && categoryId && topicUrl; - }, + } @action showCategoryTopic() { window.open(this.get("category.topic_url"), "_blank").focus(); return false; - }, + } _focusCategoryName() { this._laterFocus = discourseLater(() => { const categoryName = this.element.querySelector(".category-name"); categoryName && categoryName.focus(); }, 25); - }, -}); + } +} diff --git a/app/assets/javascripts/discourse/app/components/edit-category-images.js b/app/assets/javascripts/discourse/app/components/edit-category-images.js index ea4adbee45d..27310f39b67 100644 --- a/app/assets/javascripts/discourse/app/components/edit-category-images.js +++ b/app/assets/javascripts/discourse/app/components/edit-category-images.js @@ -1,61 +1,67 @@ -import EmberObject from "@ember/object"; +import EmberObject, { action } from "@ember/object"; import { buildCategoryPanel } from "discourse/components/edit-category-panel"; import discourseComputed from "discourse-common/utils/decorators"; -export default buildCategoryPanel("images").extend({ +export default class EditCategoryImages extends buildCategoryPanel("images") { @discourseComputed("category.uploaded_background.url") backgroundImageUrl(uploadedBackgroundUrl) { return uploadedBackgroundUrl || ""; - }, + } @discourseComputed("category.uploaded_background_dark.url") backgroundDarkImageUrl(uploadedBackgroundDarkUrl) { return uploadedBackgroundDarkUrl || ""; - }, + } @discourseComputed("category.uploaded_logo.url") logoImageUrl(uploadedLogoUrl) { return uploadedLogoUrl || ""; - }, + } @discourseComputed("category.uploaded_logo_dark.url") logoImageDarkUrl(uploadedLogoDarkUrl) { return uploadedLogoDarkUrl || ""; - }, + } - actions: { - logoUploadDone(upload) { - this._setFromUpload("category.uploaded_logo", upload); - }, + @action + logoUploadDone(upload) { + this._setFromUpload("category.uploaded_logo", upload); + } - logoUploadDeleted() { - this._deleteUpload("category.uploaded_logo"); - }, + @action + logoUploadDeleted() { + this._deleteUpload("category.uploaded_logo"); + } - logoDarkUploadDone(upload) { - this._setFromUpload("category.uploaded_logo_dark", upload); - }, + @action + logoDarkUploadDone(upload) { + this._setFromUpload("category.uploaded_logo_dark", upload); + } - logoDarkUploadDeleted() { - this._deleteUpload("category.uploaded_logo_dark"); - }, + @action + logoDarkUploadDeleted() { + this._deleteUpload("category.uploaded_logo_dark"); + } - backgroundUploadDone(upload) { - this._setFromUpload("category.uploaded_background", upload); - }, + @action + backgroundUploadDone(upload) { + this._setFromUpload("category.uploaded_background", upload); + } - backgroundUploadDeleted() { - this._deleteUpload("category.uploaded_background"); - }, + @action + backgroundUploadDeleted() { + this._deleteUpload("category.uploaded_background"); + } - backgroundDarkUploadDone(upload) { - this._setFromUpload("category.uploaded_background_dark", upload); - }, + @action + backgroundDarkUploadDone(upload) { + this._setFromUpload("category.uploaded_background_dark", upload); + } - backgroundDarkUploadDeleted() { - this._deleteUpload("category.uploaded_background_dark"); - }, - }, + @action + backgroundDarkUploadDeleted() { + this._deleteUpload("category.uploaded_background_dark"); + } _deleteUpload(path) { this.set( @@ -65,7 +71,7 @@ export default buildCategoryPanel("images").extend({ url: null, }) ); - }, + } _setFromUpload(path, upload) { this.set( @@ -75,5 +81,5 @@ export default buildCategoryPanel("images").extend({ id: upload.id, }) ); - }, -}); + } +} diff --git a/app/assets/javascripts/discourse/app/components/edit-category-panel.js b/app/assets/javascripts/discourse/app/components/edit-category-panel.js index e20bc7baab5..cc30d287dc3 100644 --- a/app/assets/javascripts/discourse/app/components/edit-category-panel.js +++ b/app/assets/javascripts/discourse/app/components/edit-category-panel.js @@ -1,19 +1,17 @@ import Component from "@ember/component"; import { equal } from "@ember/object/computed"; -const EditCategoryPanel = Component.extend({}); +import { classNameBindings } from "@ember-decorators/component"; -export default EditCategoryPanel; +export default class EditCategoryPanel extends Component {} -export function buildCategoryPanel(tab, extras) { - return EditCategoryPanel.extend( - { - activeTab: equal("selectedTab", tab), - classNameBindings: [ - ":edit-category-tab", - "activeTab::hide", - `:edit-category-tab-${tab}`, - ], - }, - extras || {} - ); +export function buildCategoryPanel(tab) { + @classNameBindings( + ":edit-category-tab", + "activeTab::hide", + `:edit-category-tab-${tab}` + ) + class BuiltCategoryPanel extends EditCategoryPanel { + @equal("selectedTab", tab) activeTab; + } + return BuiltCategoryPanel; } diff --git a/app/assets/javascripts/discourse/app/components/edit-category-security.js b/app/assets/javascripts/discourse/app/components/edit-category-security.js index 07617234792..49edb4b9a04 100644 --- a/app/assets/javascripts/discourse/app/components/edit-category-security.js +++ b/app/assets/javascripts/discourse/app/components/edit-category-security.js @@ -1,16 +1,20 @@ +import { action } from "@ember/object"; import { not } from "@ember/object/computed"; import { buildCategoryPanel } from "discourse/components/edit-category-panel"; import PermissionType from "discourse/models/permission-type"; import discourseComputed from "discourse-common/utils/decorators"; -export default buildCategoryPanel("security", { - selectedGroup: null, - noGroupSelected: not("selectedGroup"), +export default class EditCategorySecurity extends buildCategoryPanel( + "security" +) { + selectedGroup = null; + + @not("selectedGroup") noGroupSelected; @discourseComputed("category.permissions.@each.permission_type") everyonePermission(permissions) { return permissions.findBy("group_name", "everyone"); - }, + } @discourseComputed("category.permissions.@each.permission_type") everyoneGrantedFull() { @@ -18,36 +22,36 @@ export default buildCategoryPanel("security", { this.everyonePermission && this.everyonePermission.permission_type === PermissionType.FULL ); - }, + } @discourseComputed("everyonePermission") minimumPermission(everyonePermission) { return everyonePermission ? everyonePermission.permission_type : PermissionType.READONLY; - }, + } - actions: { - onSelectGroup(group_name) { - this.category.addPermission({ - group_name, - permission_type: this.minimumPermission, - }); - }, + @action + onSelectGroup(group_name) { + this.category.addPermission({ + group_name, + permission_type: this.minimumPermission, + }); + } - onChangeEveryonePermission(everyonePermissionType) { - this.category.permissions.forEach((permission, idx) => { - if (permission.group_name === "everyone") { - return; - } + @action + onChangeEveryonePermission(everyonePermissionType) { + this.category.permissions.forEach((permission, idx) => { + if (permission.group_name === "everyone") { + return; + } - if (everyonePermissionType < permission.permission_type) { - this.category.set( - `permissions.${idx}.permission_type`, - everyonePermissionType - ); - } - }); - }, - }, -}); + if (everyonePermissionType < permission.permission_type) { + this.category.set( + `permissions.${idx}.permission_type`, + everyonePermissionType + ); + } + }); + } +} diff --git a/app/assets/javascripts/discourse/app/components/edit-category-settings.js b/app/assets/javascripts/discourse/app/components/edit-category-settings.js index 223147ffdb7..2192171cfaf 100644 --- a/app/assets/javascripts/discourse/app/components/edit-category-settings.js +++ b/app/assets/javascripts/discourse/app/components/edit-category-settings.js @@ -12,18 +12,20 @@ export function addCategorySortCriteria(criteria) { categorySortCriteria.push(criteria); } -export default buildCategoryPanel("settings", { - emailInEnabled: setting("email_in"), - showPositionInput: setting("fixed_category_positions"), +export default class EditCategorySettings extends buildCategoryPanel( + "settings" +) { + @setting("email_in") emailInEnabled; + @setting("fixed_category_positions") showPositionInput; + + @and("category.show_subcategory_list", "isParentCategory") + showSubcategoryListStyle; + @empty("category.sort_order") isDefaultSortOrder; + @discourseComputed("category.isParent", "category.parent_category_id") isParentCategory(isParent, parentCategoryId) { return isParent || !parentCategoryId; - }, - showSubcategoryListStyle: and( - "category.show_subcategory_list", - "isParentCategory" - ), - isDefaultSortOrder: empty("category.sort_order"), + } @discourseComputed availableSubcategoryListStyles() { @@ -46,11 +48,11 @@ export default buildCategoryPanel("settings", { value: "boxes_with_featured_topics", }, ]; - }, + } groupFinder(term) { return Group.findAll({ term, ignore_automatic: true }); - }, + } @discourseComputed availableViews() { @@ -58,7 +60,7 @@ export default buildCategoryPanel("settings", { { name: I18n.t("filters.latest.title"), value: "latest" }, { name: I18n.t("filters.top.title"), value: "top" }, ]; - }, + } @discourseComputed availableTopPeriods() { @@ -67,14 +69,14 @@ export default buildCategoryPanel("settings", { return { name: I18n.t(`filters.top.${p}.title`), value: p }; } ); - }, + } @discourseComputed availableListFilters() { return ["all", "none"].map((p) => { return { name: I18n.t(`category.list_filters.${p}`), value: p }; }); - }, + } @discourseComputed searchPrioritiesOptions() { @@ -90,7 +92,7 @@ export default buildCategoryPanel("settings", { }); return options; - }, + } @discourseComputed availableSorts() { @@ -107,7 +109,7 @@ export default buildCategoryPanel("settings", { .concat(categorySortCriteria) .map((s) => ({ name: I18n.t("category.sort_options." + s), value: s })) .sort((a, b) => a.name.localeCompare(b.name)); - }, + } @discourseComputed("category.sort_ascending") sortAscendingOption(sortAscending) { @@ -118,7 +120,7 @@ export default buildCategoryPanel("settings", { return true; } return sortAscending; - }, + } @discourseComputed sortAscendingOptions() { @@ -126,22 +128,22 @@ export default buildCategoryPanel("settings", { { name: I18n.t("category.sort_ascending"), value: true }, { name: I18n.t("category.sort_descending"), value: false }, ]; - }, + } @discourseComputed hiddenRelativeIntervals() { return ["mins"]; - }, + } @action onAutoCloseDurationChange(minutes) { let hours = minutes ? minutes / 60 : null; this.set("category.auto_close_hours", hours); - }, + } @action onDefaultSlowModeDurationChange(minutes) { let seconds = minutes ? minutes * 60 : null; this.set("category.default_slow_mode_seconds", seconds); - }, -}); + } +} diff --git a/app/assets/javascripts/discourse/app/components/edit-category-tab.js b/app/assets/javascripts/discourse/app/components/edit-category-tab.js index e9a6342cddc..ba53c831b59 100644 --- a/app/assets/javascripts/discourse/app/components/edit-category-tab.js +++ b/app/assets/javascripts/discourse/app/components/edit-category-tab.js @@ -1,54 +1,53 @@ import Component from "@ember/component"; import { action } from "@ember/object"; -import { empty } from "@ember/object/computed"; +import { empty, equal } from "@ember/object/computed"; import { scheduleOnce } from "@ember/runloop"; import { underscore } from "@ember/string"; -import { propertyEqual } from "discourse/lib/computed"; +import { classNameBindings, tagName } from "@ember-decorators/component"; import DiscourseURL from "discourse/lib/url"; import getURL from "discourse-common/lib/get-url"; import discourseComputed from "discourse-common/utils/decorators"; import I18n from "discourse-i18n"; -export default Component.extend({ - tagName: "li", - classNameBindings: ["active", "tabClassName"], - newCategory: empty("params.slug"), +@tagName("li") +@classNameBindings("active", "tabClassName") +export default class EditCategoryTab extends Component { + @empty("params.slug") newCategory; + @equal("selectedTab", "tab") active; @discourseComputed("tab") tabClassName(tab) { return "edit-category-" + tab; - }, - - active: propertyEqual("selectedTab", "tab"), + } @discourseComputed("tab") title(tab) { return I18n.t(`category.${underscore(tab)}`); - }, + } didInsertElement() { - this._super(...arguments); + super.didInsertElement(...arguments); scheduleOnce("afterRender", this, this._addToCollection); - }, + } willDestroyElement() { - this._super(...arguments); + super.willDestroyElement(...arguments); this.setProperties({ selectedTab: "general", params: {}, }); - }, + } _addToCollection() { this.panels.addObject(this.tabClassName); - }, + } @discourseComputed("params.slug", "params.parentSlug") fullSlug(slug, parentSlug) { const slugPart = parentSlug && slug ? `${parentSlug}/${slug}` : slug; return getURL(`/c/${slugPart}/edit/${this.tab}`); - }, + } @action select(event) { @@ -57,5 +56,5 @@ export default Component.extend({ if (!this.newCategory) { DiscourseURL.routeTo(this.fullSlug); } - }, -}); + } +} diff --git a/app/assets/javascripts/discourse/app/components/edit-category-tags.js b/app/assets/javascripts/discourse/app/components/edit-category-tags.js index 7e497ac079d..e826255f0aa 100644 --- a/app/assets/javascripts/discourse/app/components/edit-category-tags.js +++ b/app/assets/javascripts/discourse/app/components/edit-category-tags.js @@ -2,10 +2,10 @@ import { action, set } from "@ember/object"; import { and, empty } from "@ember/object/computed"; import { buildCategoryPanel } from "discourse/components/edit-category-panel"; -export default buildCategoryPanel("tags", { - allowedTagsEmpty: empty("category.allowed_tags"), - allowedTagGroupsEmpty: empty("category.allowed_tag_groups"), - disableAllowGlobalTags: and("allowedTagsEmpty", "allowedTagGroupsEmpty"), +export default class EditCategoryTags extends buildCategoryPanel("tags") { + @empty("category.allowed_tags") allowedTagsEmpty; + @empty("category.allowed_tag_groups") allowedTagGroupsEmpty; + @and("allowedTagsEmpty", "allowedTagGroupsEmpty") disableAllowGlobalTags; @action onTagGroupChange(rtg, valueArray) { @@ -13,17 +13,17 @@ export default buildCategoryPanel("tags", { // to select a single tag group. This action takes the array // and extracts the first value in it. set(rtg, "name", valueArray[0]); - }, + } @action addRequiredTagGroup() { this.category.required_tag_groups.pushObject({ min_count: 1, }); - }, + } @action deleteRequiredTagGroup(rtg) { this.category.required_tag_groups.removeObject(rtg); - }, -}); + } +} diff --git a/app/assets/javascripts/discourse/app/components/edit-category-topic-template.js b/app/assets/javascripts/discourse/app/components/edit-category-topic-template.js index 2da203fa9ad..1875a562aed 100644 --- a/app/assets/javascripts/discourse/app/components/edit-category-topic-template.js +++ b/app/assets/javascripts/discourse/app/components/edit-category-topic-template.js @@ -1,17 +1,25 @@ -import { action, computed } from "@ember/object"; +import { tracked } from "@glimmer/tracking"; +import { action } from "@ember/object"; import { schedule } from "@ember/runloop"; +import { observes } from "@ember-decorators/object"; import { buildCategoryPanel } from "discourse/components/edit-category-panel"; -import discourseComputed, { observes } from "discourse-common/utils/decorators"; +import discourseComputed from "discourse-common/utils/decorators"; -export default buildCategoryPanel("topic-template", { - showFormTemplate: computed("category.form_template_ids", { - get() { - return Boolean(this.category.form_template_ids.length); - }, - set(key, value) { - return value; - }, - }), +export default class EditCategoryTopicTemplate extends buildCategoryPanel( + "topic-template" +) { + @tracked _showFormTemplateOverride; + + get showFormTemplate() { + return ( + this._showFormTemplateOverride ?? + Boolean(this.category.get("form_template_ids.length")) + ); + } + + set showFormTemplate(value) { + this._showFormTemplateOverride = value; + } @discourseComputed("showFormTemplate") templateTypeToggleLabel(showFormTemplate) { @@ -20,7 +28,7 @@ export default buildCategoryPanel("topic-template", { } return "admin.form_templates.edit_category.toggle_freeform"; - }, + } @action toggleTemplateType() { @@ -30,7 +38,7 @@ export default buildCategoryPanel("topic-template", { // Clear associated form templates if switching to freeform this.set("category.form_template_ids", []); } - }, + } @observes("activeTab", "showFormTemplate") _activeTabChanged() { @@ -39,5 +47,5 @@ export default buildCategoryPanel("topic-template", { this.element.querySelector(".d-editor-input").focus() ); } - }, -}); + } +} diff --git a/app/assets/javascripts/discourse/app/components/emoji-group-buttons.js b/app/assets/javascripts/discourse/app/components/emoji-group-buttons.js index 87d5ddb040f..de1579c0b8d 100644 --- a/app/assets/javascripts/discourse/app/components/emoji-group-buttons.js +++ b/app/assets/javascripts/discourse/app/components/emoji-group-buttons.js @@ -1,3 +1,3 @@ import Component from "@ember/component"; -export default Component.extend({}); +export default class EmojiGroupButtons extends Component {} diff --git a/app/assets/javascripts/discourse/app/components/emoji-group-sections.js b/app/assets/javascripts/discourse/app/components/emoji-group-sections.js index 87d5ddb040f..0951a47984f 100644 --- a/app/assets/javascripts/discourse/app/components/emoji-group-sections.js +++ b/app/assets/javascripts/discourse/app/components/emoji-group-sections.js @@ -1,3 +1,3 @@ import Component from "@ember/component"; -export default Component.extend({}); +export default class EmojiGroupSections extends Component {} diff --git a/app/assets/javascripts/discourse/app/components/emoji-uploader.js b/app/assets/javascripts/discourse/app/components/emoji-uploader.js index fa3dabccd2f..501332a7885 100644 --- a/app/assets/javascripts/discourse/app/components/emoji-uploader.js +++ b/app/assets/javascripts/discourse/app/components/emoji-uploader.js @@ -8,21 +8,23 @@ import I18n from "discourse-i18n"; const DEFAULT_GROUP = "default"; -export default Component.extend(UppyUploadMixin, { - type: "emoji", - uploadUrl: "/admin/customize/emojis", - hasName: notEmpty("name"), - hasGroup: notEmpty("group"), - group: "default", - emojiGroups: null, - newEmojiGroups: null, - tagName: null, - preventDirectS3Uploads: true, +export default class EmojiUploader extends Component.extend(UppyUploadMixin) { + type = "emoji"; + uploadUrl = "/admin/customize/emojis"; + + @notEmpty("name") hasName; + @notEmpty("group") hasGroup; + + group = "default"; + emojiGroups = null; + newEmojiGroups = null; + tagName = null; + preventDirectS3Uploads = true; didReceiveAttrs() { - this._super(...arguments); + super.didReceiveAttrs(...arguments); this.set("newEmojiGroups", this.emojiGroups); - }, + } @action createEmojiGroup(group) { @@ -34,7 +36,7 @@ export default Component.extend(UppyUploadMixin, { newEmojiGroups, group, }); - }, + } _perFileData() { const payload = {}; @@ -51,21 +53,21 @@ export default Component.extend(UppyUploadMixin, { } return payload; - }, + } validateUploadedFilesOptions() { return { imagesOnly: true }; - }, + } uploadDone(upload) { this.done(upload, this.group); this.set("name", null); - }, + } @action chooseFiles() { this.fileInputEl.click(); - }, + } @discourseComputed("uploading", "uploadProgress") buttonLabel(uploading, uploadProgress) { @@ -74,7 +76,7 @@ export default Component.extend(UppyUploadMixin, { } else { return I18n.t("admin.emoji.add"); } - }, + } @discourseComputed("uploading") buttonIcon(uploading) { @@ -83,5 +85,5 @@ export default Component.extend(UppyUploadMixin, { } else { return "plus"; } - }, -}); + } +}