DEV: Convert select-kit components to native class syntax (#28489)

Changes made using the ember-native-class-codemod, plus some manual tweaks
This commit is contained in:
David Taylor
2024-08-23 12:17:07 +01:00
committed by GitHub
parent 2829b670f9
commit d1cc60c435
83 changed files with 1528 additions and 1359 deletions

View File

@ -1,9 +1,11 @@
import { action } from "@ember/object";
import { service } from "@ember/service";
import { classNames } from "@ember-decorators/component";
import { popupAjaxError } from "discourse/lib/ajax-error";
import Bookmark from "discourse/models/bookmark";
import i18n from "discourse-common/helpers/i18n";
import DropdownSelectBoxComponent from "select-kit/components/dropdown-select-box";
import { selectKitOptions } from "./select-kit";
const _customButtons = [];
const _customActions = {};
@ -12,19 +14,18 @@ export function addBulkDropdownAction(name, customAction) {
_customActions[name] = customAction;
}
export default DropdownSelectBoxComponent.extend({
classNames: ["bulk-select-bookmarks-dropdown"],
headerIcon: null,
@classNames("bulk-select-bookmarks-dropdown")
@selectKitOptions({
showCaret: true,
showFullTitle: true,
selectKitOptions: {
showCaret: true,
showFullTitle: true,
none: "select_kit.components.bulk_select_bookmarks_dropdown.title",
},
none: "select_kit.components.bulk_select_bookmarks_dropdown.title",
})
export default class BulkSelectBookmarksDropdown extends DropdownSelectBoxComponent {
@service router;
@service toasts;
@service dialog;
router: service(),
toasts: service(),
dialog: service(),
headerIcon = null;
get content() {
let options = [];
@ -42,11 +43,11 @@ export default DropdownSelectBoxComponent.extend({
]);
return [...options, ..._customButtons];
},
}
getSelectedBookmarks() {
return this.bulkSelectHelper.selected;
},
}
@action
onSelect(id) {
@ -99,5 +100,5 @@ export default DropdownSelectBoxComponent.extend({
},
});
}
},
});
}
}

View File

@ -1,21 +1,22 @@
import { computed } from "@ember/object";
import { classNames } from "@ember-decorators/component";
import I18n from "discourse-i18n";
import DropdownSelectBoxComponent from "select-kit/components/dropdown-select-box";
import { pluginApiIdentifiers, selectKitOptions } from "./select-kit";
export default DropdownSelectBoxComponent.extend({
pluginApiIdentifiers: ["categories-admin-dropdown"],
classNames: ["categories-admin-dropdown"],
selectKitOptions: {
icons: ["wrench", "caret-down"],
showFullTitle: false,
autoFilterable: false,
filterable: false,
none: "select_kit.components.categories_admin_dropdown.title",
focusAfterOnChange: false,
},
content: computed(function () {
@classNames("categories-admin-dropdown")
@selectKitOptions({
icons: ["wrench", "caret-down"],
showFullTitle: false,
autoFilterable: false,
filterable: false,
none: "select_kit.components.categories_admin_dropdown.title",
focusAfterOnChange: false,
})
@pluginApiIdentifiers(["categories-admin-dropdown"])
export default class CategoriesAdminDropdown extends DropdownSelectBoxComponent {
@computed
get content() {
const items = [
{
id: "create",
@ -33,7 +34,7 @@ export default DropdownSelectBoxComponent.extend({
});
return items;
}),
}
_onChange(value, item) {
if (item.onChange) {
@ -41,5 +42,5 @@ export default DropdownSelectBoxComponent.extend({
} else if (this.onChange) {
this.onChange(value, item);
}
},
});
}
}

View File

@ -1,6 +1,7 @@
import { computed, set } from "@ember/object";
import { htmlSafe } from "@ember/template";
import { isNone } from "@ember/utils";
import { classNames } from "@ember-decorators/component";
import { categoryBadgeHTML } from "discourse/helpers/category-link";
import { setting } from "discourse/lib/computed";
import Category from "discourse/models/category";
@ -8,26 +9,26 @@ import PermissionType from "discourse/models/permission-type";
import I18n from "discourse-i18n";
import CategoryRow from "select-kit/components/category-row";
import ComboBoxComponent from "select-kit/components/combo-box";
import { pluginApiIdentifiers, selectKitOptions } from "./select-kit";
export default ComboBoxComponent.extend({
pluginApiIdentifiers: ["category-chooser"],
classNames: ["category-chooser"],
allowUncategorized: setting("allow_uncategorized_topics"),
fixedCategoryPositionsOnCreate: setting("fixed_category_positions_on_create"),
selectKitOptions: {
filterable: true,
allowUncategorized: "allowUncategorized",
autoInsertNoneItem: false,
allowSubCategories: true,
permissionType: PermissionType.FULL,
excludeCategoryId: null,
scopedCategoryId: null,
prioritizedCategoryId: null,
},
@classNames("category-chooser")
@selectKitOptions({
filterable: true,
allowUncategorized: "allowUncategorized",
autoInsertNoneItem: false,
allowSubCategories: true,
permissionType: PermissionType.FULL,
excludeCategoryId: null,
scopedCategoryId: null,
prioritizedCategoryId: null,
})
@pluginApiIdentifiers(["category-chooser"])
export default class CategoryChooser extends ComboBoxComponent {
@setting("allow_uncategorized_topics") allowUncategorized;
@setting("fixed_category_positions_on_create") fixedCategoryPositionsOnCreate;
init() {
this._super(...arguments);
super.init(...arguments);
if (
this.site.lazy_load_categories &&
@ -40,11 +41,11 @@ export default ComboBoxComponent.extend({
this.notifyPropertyChange("value");
});
}
},
}
modifyComponentForRow() {
return CategoryRow;
},
}
modifyNoSelection() {
if (!isNone(this.selectKit.options.none)) {
@ -67,7 +68,7 @@ export default ComboBoxComponent.extend({
return this.defaultItem(null, htmlSafe(I18n.t("category.choose")));
}
}
},
}
modifySelection(content) {
if (this.selectKit.hasSelection) {
@ -88,7 +89,7 @@ export default ComboBoxComponent.extend({
}
return content;
},
}
search(filter) {
if (this.site.lazy_load_categories) {
@ -119,29 +120,28 @@ export default ComboBoxComponent.extend({
} else {
return this.content;
}
},
}
content: computed(
@computed(
"selectKit.filter",
"selectKit.options.scopedCategoryId",
"selectKit.options.prioritizedCategoryId",
function () {
if (!this.selectKit.filter) {
let { scopedCategoryId, prioritizedCategoryId } =
this.selectKit.options;
"selectKit.options.prioritizedCategoryId"
)
get content() {
if (!this.selectKit.filter) {
let { scopedCategoryId, prioritizedCategoryId } = this.selectKit.options;
if (scopedCategoryId) {
return this.categoriesByScope({ scopedCategoryId });
}
if (prioritizedCategoryId) {
return this.categoriesByScope({ prioritizedCategoryId });
}
if (scopedCategoryId) {
return this.categoriesByScope({ scopedCategoryId });
}
return this.categoriesByScope();
if (prioritizedCategoryId) {
return this.categoriesByScope({ prioritizedCategoryId });
}
}
),
return this.categoriesByScope();
}
categoriesByScope({
scopedCategoryId = null,
@ -218,14 +218,14 @@ export default ComboBoxComponent.extend({
} else {
return scopedCategories;
}
},
}
_matchCategory(filter, categoryName) {
return this._normalize(categoryName).includes(filter);
},
}
_onChange(value) {
this._boundaryActionHandler("onChangeCategory", Category.findById(value));
return true;
},
});
}
}

View File

@ -1,6 +1,7 @@
import { computed } from "@ember/object";
import { action, computed } from "@ember/object";
import { readOnly } from "@ember/object/computed";
import { htmlSafe } from "@ember/template";
import { classNameBindings, classNames } from "@ember-decorators/component";
import { categoryBadgeHTML } from "discourse/helpers/category-link";
import { setting } from "discourse/lib/computed";
import DiscourseURL, {
@ -12,113 +13,118 @@ import I18n from "discourse-i18n";
import CategoryDropMoreCollection from "select-kit/components/category-drop-more-collection";
import CategoryRow from "select-kit/components/category-row";
import ComboBoxComponent from "select-kit/components/combo-box";
import { MAIN_COLLECTION } from "select-kit/components/select-kit";
import {
MAIN_COLLECTION,
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
export const NO_CATEGORIES_ID = "no-categories";
export const ALL_CATEGORIES_ID = "all-categories";
const MORE_COLLECTION = "MORE_COLLECTION";
export default ComboBoxComponent.extend({
pluginApiIdentifiers: ["category-drop"],
classNames: ["category-drop"],
classNameBindings: ["noSubcategories:has-selection"],
value: readOnly("category.id"),
content: readOnly("categoriesWithShortcuts.[]"),
noCategoriesLabel: I18n.t("categories.no_subcategories"),
navigateToEdit: false,
editingCategory: false,
editingCategoryTab: null,
allowUncategorized: setting("allow_uncategorized_topics"),
@classNames("category-drop")
@classNameBindings("noSubcategories:has-selection")
@selectKitOptions({
filterable: true,
none: "category.all",
caretDownIcon: "caret-right",
caretUpIcon: "caret-down",
fullWidthOnMobile: true,
noSubcategories: false,
subCategory: false,
clearable: false,
hideParentCategory: "hideParentCategory",
countSubcategories: false,
autoInsertNoneItem: false,
displayCategoryDescription: "displayCategoryDescription",
headerComponent: "category-drop/category-drop-header",
parentCategory: false,
allowUncategorized: "allowUncategorized",
})
@pluginApiIdentifiers(["category-drop"])
export default class CategoryDrop extends ComboBoxComponent {
@readOnly("category.id") value;
@readOnly("categoriesWithShortcuts.[]") content;
@readOnly("selectKit.options.parentCategory.displayName") parentCategoryName;
@setting("allow_uncategorized_topics") allowUncategorized;
selectKitOptions: {
filterable: true,
none: "category.all",
caretDownIcon: "caret-right",
caretUpIcon: "caret-down",
fullWidthOnMobile: true,
noSubcategories: false,
subCategory: false,
clearable: false,
hideParentCategory: "hideParentCategory",
countSubcategories: false,
autoInsertNoneItem: false,
displayCategoryDescription: "displayCategoryDescription",
headerComponent: "category-drop/category-drop-header",
parentCategory: false,
allowUncategorized: "allowUncategorized",
},
noCategoriesLabel = I18n.t("categories.no_subcategories");
navigateToEdit = false;
editingCategory = false;
editingCategoryTab = null;
init() {
this._super(...arguments);
super.init(...arguments);
this.insertAfterCollection(MAIN_COLLECTION, MORE_COLLECTION);
},
}
modifyComponentForCollection(collection) {
if (collection === MORE_COLLECTION) {
return CategoryDropMoreCollection;
}
},
}
modifyComponentForRow() {
return CategoryRow;
},
}
noSubcategories: computed("selectKit.options.noSubcategories", function () {
@computed("selectKit.options.noSubcategories")
get noSubcategories() {
return this.selectKit.options.noSubcategories;
}),
}
displayCategoryDescription: computed(function () {
@computed
get displayCategoryDescription() {
return !(
this.get("currentUser.staff") || this.get("currentUser.trust_level") > 0
);
}),
}
hideParentCategory: computed(function () {
@computed
get hideParentCategory() {
return this.options.subCategory || false;
}),
}
shortcuts: computed(
"value",
"selectKit.options.{subCategory,noSubcategories}",
function () {
const shortcuts = [];
@computed("value", "selectKit.options.{subCategory,noSubcategories}")
get shortcuts() {
const shortcuts = [];
if (
(this.value && !this.editingCategory) ||
(this.selectKit.options.noSubcategories &&
this.selectKit.options.subCategory)
) {
shortcuts.push({
id: ALL_CATEGORIES_ID,
name: this.allCategoriesLabel,
});
}
if (
this.selectKit.options.subCategory &&
(this.value || !this.selectKit.options.noSubcategories)
) {
shortcuts.push({
id: NO_CATEGORIES_ID,
name: this.noCategoriesLabel,
});
}
// If there is a single shortcut, we can have a single "remove filter" option
if (shortcuts.length === 1 && shortcuts[0].id === ALL_CATEGORIES_ID) {
shortcuts[0].name = I18n.t("categories.remove_filter");
}
return shortcuts;
if (
(this.value && !this.editingCategory) ||
(this.selectKit.options.noSubcategories &&
this.selectKit.options.subCategory)
) {
shortcuts.push({
id: ALL_CATEGORIES_ID,
name: this.allCategoriesLabel,
});
}
),
categoriesWithShortcuts: computed("categories.[]", "shortcuts", function () {
if (
this.selectKit.options.subCategory &&
(this.value || !this.selectKit.options.noSubcategories)
) {
shortcuts.push({
id: NO_CATEGORIES_ID,
name: this.noCategoriesLabel,
});
}
// If there is a single shortcut, we can have a single "remove filter" option
if (shortcuts.length === 1 && shortcuts[0].id === ALL_CATEGORIES_ID) {
shortcuts[0].name = I18n.t("categories.remove_filter");
}
return shortcuts;
}
@computed("categories.[]", "shortcuts")
get categoriesWithShortcuts() {
const results = this._filterUncategorized(this.categories || []);
return this.shortcuts.concat(results);
}),
}
modifyNoSelection() {
if (this.selectKit.options.noSubcategories) {
@ -134,7 +140,7 @@ export default ComboBoxComponent.extend({
: I18n.t("categories.categories_label")
);
}
},
}
modifySelection(content) {
if (this.value) {
@ -150,27 +156,22 @@ export default ComboBoxComponent.extend({
}
return content;
},
}
parentCategoryName: readOnly("selectKit.options.parentCategory.displayName"),
allCategoriesLabel: computed(
"parentCategoryName",
"selectKit.options.subCategory",
function () {
if (this.editingCategory) {
return this.noCategoriesLabel;
}
if (this.selectKit.options.subCategory) {
return I18n.t("categories.remove_filter", {
categoryName: this.parentCategoryName,
});
}
return I18n.t("categories.all");
@computed("parentCategoryName", "selectKit.options.subCategory")
get allCategoriesLabel() {
if (this.editingCategory) {
return this.noCategoriesLabel;
}
),
if (this.selectKit.options.subCategory) {
return I18n.t("categories.remove_filter", {
categoryName: this.parentCategoryName,
});
}
return I18n.t("categories.all");
}
async search(filter) {
if (this.site.lazy_load_categories) {
@ -221,34 +222,33 @@ export default ComboBoxComponent.extend({
} else {
return this._filterUncategorized(this.content);
}
},
}
actions: {
onChange(categoryId) {
const category =
categoryId === ALL_CATEGORIES_ID || categoryId === NO_CATEGORIES_ID
? this.selectKit.options.parentCategory
: Category.findById(parseInt(categoryId, 10));
@action
onChange(categoryId) {
const category =
categoryId === ALL_CATEGORIES_ID || categoryId === NO_CATEGORIES_ID
? this.selectKit.options.parentCategory
: Category.findById(parseInt(categoryId, 10));
let route;
if (this.editingCategoryTab) {
// rendered on category page
route = getEditCategoryUrl(
category,
categoryId !== NO_CATEGORIES_ID,
this.editingCategoryTab
);
} else {
route = getCategoryAndTagUrl(
category,
categoryId !== NO_CATEGORIES_ID,
this.tagId
);
}
let route;
if (this.editingCategoryTab) {
// rendered on category page
route = getEditCategoryUrl(
category,
categoryId !== NO_CATEGORIES_ID,
this.editingCategoryTab
);
} else {
route = getCategoryAndTagUrl(
category,
categoryId !== NO_CATEGORIES_ID,
this.tagId
);
}
DiscourseURL.routeToUrl(route);
},
},
DiscourseURL.routeToUrl(route);
}
_filterUncategorized(content) {
if (!this.siteSettings.allow_uncategorized_topics) {
@ -258,5 +258,5 @@ export default ComboBoxComponent.extend({
}
return content;
},
});
}
}

View File

@ -1,16 +1,16 @@
import { classNames } from "@ember-decorators/component";
import discourseComputed from "discourse-common/utils/decorators";
import ComboBoxSelectBoxHeaderComponent from "select-kit/components/combo-box/combo-box-header";
export default ComboBoxSelectBoxHeaderComponent.extend({
classNames: ["category-drop-header"],
@classNames("category-drop-header")
export default class CategoryDropHeader extends ComboBoxSelectBoxHeaderComponent {
@discourseComputed("selectedContent.color")
categoryBackgroundColor(categoryColor) {
return categoryColor || "#e9e9e9";
},
}
@discourseComputed("selectedContent.text_color")
categoryTextColor(categoryTextColor) {
return categoryTextColor || "#333";
},
});
}
}

View File

@ -1,15 +1,16 @@
import { or } from "@ember/object/computed";
import { classNames } from "@ember-decorators/component";
import I18n from "discourse-i18n";
import NotificationOptionsComponent from "select-kit/components/notifications-button";
import { pluginApiIdentifiers, selectKitOptions } from "./select-kit";
export default NotificationOptionsComponent.extend({
pluginApiIdentifiers: ["category-notifications-button"],
classNames: ["category-notifications-button"],
isHidden: or("category.deleted"),
selectKitOptions: {
i18nPrefix: "category.notifications",
showFullTitle: false,
headerAriaLabel: I18n.t("category.notifications.title"),
},
});
@selectKitOptions({
i18nPrefix: "category.notifications",
showFullTitle: false,
headerAriaLabel: I18n.t("category.notifications.title"),
})
@pluginApiIdentifiers(["category-notifications-button"])
@classNames("category-notifications-button")
export default class CategoryNotificationsButton extends NotificationOptionsComponent {
@or("category.deleted") isHidden;
}

View File

@ -1,33 +1,36 @@
import EmberObject, { computed } from "@ember/object";
import EmberObject, { action, computed } from "@ember/object";
import { mapBy } from "@ember/object/computed";
import { classNames } from "@ember-decorators/component";
import Category from "discourse/models/category";
import { makeArray } from "discourse-common/lib/helpers";
import CategoryRow from "select-kit/components/category-row";
import MultiSelectComponent from "select-kit/components/multi-select";
import { pluginApiIdentifiers, selectKitOptions } from "./select-kit";
export default MultiSelectComponent.extend({
pluginApiIdentifiers: ["category-selector"],
classNames: ["category-selector"],
categories: null,
blockedCategories: null,
selectKitOptions: {
filterable: true,
allowAny: false,
allowUncategorized: true,
displayCategoryDescription: false,
selectedChoiceComponent: "selected-choice-category",
},
@classNames("category-selector")
@selectKitOptions({
filterable: true,
allowAny: false,
allowUncategorized: true,
displayCategoryDescription: false,
selectedChoiceComponent: "selected-choice-category",
})
@pluginApiIdentifiers(["category-selector"])
export default class CategorySelector extends MultiSelectComponent {
categories = null;
blockedCategories = null;
@mapBy("categories", "id") value;
init() {
this._super(...arguments);
super.init(...arguments);
if (!this.blockedCategories) {
this.set("blockedCategories", []);
}
},
}
content: computed("categories.[]", "blockedCategories.[]", function () {
@computed("categories.[]", "blockedCategories.[]")
get content() {
return Category.list().filter((category) => {
if (category.isUncategorizedCategory) {
if (this.options?.allowUncategorized !== undefined) {
@ -42,13 +45,11 @@ export default MultiSelectComponent.extend({
!this.blockedCategories.includes(category)
);
});
}),
value: mapBy("categories", "id"),
}
modifyComponentForRow() {
return CategoryRow;
},
}
async search(filter) {
let categories;
@ -66,7 +67,7 @@ export default MultiSelectComponent.extend({
rejectCategoryIds: Array.from(rejectCategoryIds),
});
} else {
categories = this._super(filter);
categories = super.search(filter);
}
// If there is a single match or an exact match and it has subcategories,
@ -91,7 +92,7 @@ export default MultiSelectComponent.extend({
}
return categories;
},
}
async select(value, item) {
// item is usually a category, but if the "category" property is set, then
@ -113,14 +114,13 @@ export default MultiSelectComponent.extend({
makeArray(this.selectedContent).concat(item.category.descendants)
);
} else {
this._super(value, item);
super.select(value, item);
}
},
}
actions: {
onChange(values) {
this.onChange(values.map((v) => Category.findById(v)).filter(Boolean));
return false;
},
},
});
@action
_onChange(values) {
this.onChange(values.map((v) => Category.findById(v)).filter(Boolean));
return false;
}
}

View File

@ -1,15 +1,15 @@
import { classNames } from "@ember-decorators/component";
import I18n from "discourse-i18n";
import ComboBoxComponent from "select-kit/components/combo-box";
import { pluginApiIdentifiers, selectKitOptions } from "./select-kit";
export default ComboBoxComponent.extend({
pluginApiIdentifiers: ["color-palettes"],
classNames: ["color-palettes"],
@classNames("color-palettes")
@selectKitOptions({
translatedNone: I18n.t("admin.customize.theme.default_light_scheme"),
})
@pluginApiIdentifiers(["color-palettes"])
export default class ColorPalettes extends ComboBoxComponent {
modifyComponentForRow() {
return "color-palettes/color-palettes-row";
},
selectKitOptions: {
translatedNone: I18n.t("admin.customize.theme.default_light_scheme"),
},
});
}
}

View File

@ -1,11 +1,12 @@
import { computed } from "@ember/object";
import { htmlSafe } from "@ember/template";
import { classNames } from "@ember-decorators/component";
import SelectKitRowComponent from "select-kit/components/select-kit/select-kit-row";
export default SelectKitRowComponent.extend({
classNames: ["color-palettes-row"],
palettes: computed("item.colors.[]", function () {
@classNames("color-palettes-row")
export default class ColorPalettesRow extends SelectKitRowComponent {
@computed("item.colors.[]")
get palettes() {
return htmlSafe(
(this.item.colors || [])
.filter((color) => color.name !== "secondary")
@ -16,9 +17,10 @@ export default SelectKitRowComponent.extend({
)
.join("")
);
}),
}
backgroundColor: computed("item.colors.[]", function () {
@computed("item.colors.[]")
get backgroundColor() {
const secondary = (this.item.colors || []).findBy("name", "secondary");
if (secondary && secondary.hex) {
@ -26,5 +28,5 @@ export default SelectKitRowComponent.extend({
} else {
return "";
}
}),
});
}
}

View File

@ -1,17 +1,17 @@
import { gte } from "@ember/object/computed";
import { classNames } from "@ember-decorators/component";
import SingleSelectComponent from "select-kit/components/single-select";
import { pluginApiIdentifiers, selectKitOptions } from "./select-kit";
export default SingleSelectComponent.extend({
pluginApiIdentifiers: ["combo-box"],
classNames: ["combobox", "combo-box"],
selectKitOptions: {
caretUpIcon: "caret-up",
caretDownIcon: "caret-down",
autoFilterable: "autoFilterable",
clearable: false,
headerComponent: "combo-box/combo-box-header",
},
autoFilterable: gte("content.length", 10),
});
@classNames("combobox", "combo-box")
@pluginApiIdentifiers(["combo-box"])
@selectKitOptions({
caretUpIcon: "caret-up",
caretDownIcon: "caret-down",
autoFilterable: "autoFilterable",
clearable: false,
headerComponent: "combo-box/combo-box-header",
})
export default class ComboBox extends SingleSelectComponent {
@gte("content.length", 10) autoFilterable;
}

View File

@ -1,20 +1,17 @@
import { computed } from "@ember/object";
import { and, reads } from "@ember/object/computed";
import { classNames } from "@ember-decorators/component";
import SingleSelectHeaderComponent from "select-kit/components/select-kit/single-select-header";
export default SingleSelectHeaderComponent.extend({
classNames: ["combo-box-header"],
clearable: reads("selectKit.options.clearable"),
caretUpIcon: reads("selectKit.options.caretUpIcon"),
caretDownIcon: reads("selectKit.options.caretDownIcon"),
shouldDisplayClearableButton: and("clearable", "value"),
@classNames("combo-box-header")
export default class ComboBoxHeader extends SingleSelectHeaderComponent {
@reads("selectKit.options.clearable") clearable;
@reads("selectKit.options.caretUpIcon") caretUpIcon;
@reads("selectKit.options.caretDownIcon") caretDownIcon;
@and("clearable", "value") shouldDisplayClearableButton;
caretIcon: computed(
"selectKit.isExpanded",
"caretUpIcon",
"caretDownIcon",
function () {
return this.selectKit.isExpanded ? this.caretUpIcon : this.caretDownIcon;
}
),
});
@computed("selectKit.isExpanded", "caretUpIcon", "caretDownIcon")
get caretIcon() {
return this.selectKit.isExpanded ? this.caretUpIcon : this.caretDownIcon;
}
}

View File

@ -1,7 +1,9 @@
import { action } from "@ember/object";
import { equal, gt } from "@ember/object/computed";
import { service } from "@ember/service";
import { camelize } from "@ember/string";
import { isEmpty } from "@ember/utils";
import { classNames } from "@ember-decorators/component";
import { escapeExpression } from "discourse/lib/utilities";
import {
CREATE_SHARED_DRAFT,
@ -14,6 +16,7 @@ import Draft from "discourse/models/draft";
import discourseComputed from "discourse-common/utils/decorators";
import I18n from "discourse-i18n";
import DropdownSelectBoxComponent from "select-kit/components/dropdown-select-box";
import { pluginApiIdentifiers, selectKitOptions } from "./select-kit";
// Component can get destroyed and lose state
let _topicSnapshot = null;
@ -26,30 +29,37 @@ export function _clearSnapshots() {
_actionSnapshot = null;
}
export default DropdownSelectBoxComponent.extend({
dialog: service(),
composer: service(),
seq: 0,
pluginApiIdentifiers: ["composer-actions"],
classNames: ["composer-actions"],
isEditing: equal("action", EDIT),
isInSlowMode: gt("topic.slow_mode_seconds", 0),
@classNames("composer-actions")
@pluginApiIdentifiers(["composer-actions"])
@selectKitOptions({
icon: "iconForComposerAction",
filterable: false,
showFullTitle: false,
preventHeaderFocus: true,
customStyle: true,
})
export default class ComposerActions extends DropdownSelectBoxComponent {
@service dialog;
@service composer;
selectKitOptions: {
icon: "iconForComposerAction",
filterable: false,
showFullTitle: false,
preventHeaderFocus: true,
customStyle: true,
},
seq = 0;
@equal("action", EDIT) isEditing;
@gt("topic.slow_mode_seconds", 0) isInSlowMode;
@discourseComputed("isEditing", "action", "whisper", "noBump", "isInSlowMode")
iconForComposerAction(isEditing, action, whisper, noBump, isInSlowMode) {
if (action === CREATE_TOPIC) {
iconForComposerAction(
isEditing,
composerAction,
whisper,
noBump,
isInSlowMode
) {
if (composerAction === CREATE_TOPIC) {
return "plus";
} else if (action === PRIVATE_MESSAGE) {
} else if (composerAction === PRIVATE_MESSAGE) {
return "envelope";
} else if (action === CREATE_SHARED_DRAFT) {
} else if (composerAction === CREATE_SHARED_DRAFT) {
return "far-clipboard";
} else if (whisper) {
return "far-eye-slash";
@ -62,14 +72,14 @@ export default DropdownSelectBoxComponent.extend({
} else {
return "share";
}
},
}
contentChanged() {
this.set("seq", this.seq + 1);
},
}
didReceiveAttrs() {
this._super(...arguments);
super.didReceiveAttrs(...arguments);
let changeContent = false;
// if we change topic we want to change both snapshots
@ -98,11 +108,11 @@ export default DropdownSelectBoxComponent.extend({
}
this.set("selectKit.isHidden", isEmpty(this.content));
},
}
modifySelection() {
return {};
},
}
@discourseComputed("seq")
content() {
@ -233,7 +243,7 @@ export default DropdownSelectBoxComponent.extend({
}
return items;
},
}
_continuedFromText(post, topic) {
let url = post?.url || topic?.url;
@ -248,7 +258,7 @@ export default DropdownSelectBoxComponent.extend({
return I18n.t("post.continue_discussion", {
postLink: link,
});
},
}
_replyFromExisting(options, post, topic) {
this.composer.closeComposer();
@ -256,20 +266,20 @@ export default DropdownSelectBoxComponent.extend({
...options,
prependText: this._continuedFromText(post, topic),
});
},
}
_openComposer(options) {
this.composer.closeComposer();
this.composer.open(options);
},
}
toggleWhisperSelected(options, model) {
model.toggleProperty("whisper");
},
}
toggleTopicBumpSelected(options, model) {
model.toggleProperty("noBump");
},
}
replyAsNewGroupMessageSelected(options) {
const recipients = [];
@ -284,21 +294,21 @@ export default DropdownSelectBoxComponent.extend({
options.skipDraftCheck = true;
this._replyFromExisting(options, _postSnapshot, _topicSnapshot);
},
}
replyToTopicSelected(options) {
options.action = REPLY;
options.topic = _topicSnapshot;
options.skipDraftCheck = true;
this._openComposer(options);
},
}
replyToPostSelected(options) {
options.action = REPLY;
options.post = _postSnapshot;
options.skipDraftCheck = true;
this._openComposer(options);
},
}
replyAsNewTopicSelected(options) {
Draft.get("new_topic").then((response) => {
@ -314,7 +324,7 @@ export default DropdownSelectBoxComponent.extend({
this._replyAsNewTopicSelect(options);
}
});
},
}
_replyAsNewTopicSelect(options) {
options.action = CREATE_TOPIC;
@ -322,7 +332,7 @@ export default DropdownSelectBoxComponent.extend({
options.disableScopedCategory = true;
options.skipDraftCheck = true;
this._replyFromExisting(options, _postSnapshot, _topicSnapshot);
},
}
replyAsPrivateMessageSelected(options) {
let usernames;
@ -349,44 +359,43 @@ export default DropdownSelectBoxComponent.extend({
options.skipDraftCheck = true;
this._replyFromExisting(options, _postSnapshot, _topicSnapshot);
},
}
_switchCreate(options, action) {
options.action = action;
_switchCreate(options, composerAction) {
options.action = composerAction;
options.categoryId = this.get("composerModel.categoryId");
options.topicTitle = this.get("composerModel.title");
options.tags = this.get("composerModel.tags");
options.skipDraftCheck = true;
this._openComposer(options);
},
}
createTopicSelected(options) {
this._switchCreate(options, CREATE_TOPIC);
},
}
sharedDraftSelected(options) {
this._switchCreate(options, CREATE_SHARED_DRAFT);
},
}
actions: {
onChange(value) {
const action = `${camelize(value)}Selected`;
if (this[action]) {
this[action](
this.composerModel.getProperties(
"draftKey",
"draftSequence",
"title",
"reply",
"disableScopedCategory"
),
this.composerModel
);
this.contentChanged();
} else {
// eslint-disable-next-line no-console
console.error(`No method '${action}' found`);
}
},
},
});
@action
onChange(value) {
const composerAction = `${camelize(value)}Selected`;
if (this[composerAction]) {
this[composerAction](
this.composerModel.getProperties(
"draftKey",
"draftSequence",
"title",
"reply",
"disableScopedCategory"
),
this.composerModel
);
this.contentChanged();
} else {
// eslint-disable-next-line no-console
console.error(`No method '${composerAction}' found`);
}
}
}

View File

@ -1,12 +1,12 @@
import { schedule } from "@ember/runloop";
import { classNames } from "@ember-decorators/component";
import { escapeExpression } from "discourse/lib/utilities";
import SelectKitRowComponent from "select-kit/components/select-kit/select-kit-row";
export default SelectKitRowComponent.extend({
classNames: ["create-color-row"],
@classNames("create-color-row")
export default class CreateColorRow extends SelectKitRowComponent {
didReceiveAttrs() {
this._super(...arguments);
super.didReceiveAttrs(...arguments);
schedule("afterRender", () => {
const color = escapeExpression(this.rowValue);
@ -14,5 +14,5 @@ export default SelectKitRowComponent.extend({
? color
: `#${color}`;
});
},
});
}
}

View File

@ -1,22 +1,22 @@
import { classNames } from "@ember-decorators/component";
import SingleSelectComponent from "select-kit/components/single-select";
import { pluginApiIdentifiers, selectKitOptions } from "./select-kit";
export default SingleSelectComponent.extend({
pluginApiIdentifiers: ["dropdown-select-box"],
classNames: ["dropdown-select-box"],
selectKitOptions: {
autoFilterable: false,
filterable: false,
showFullTitle: true,
headerComponent: "dropdown-select-box/dropdown-select-box-header",
caretUpIcon: "caret-up",
caretDownIcon: "caret-down",
showCaret: false,
customStyle: null,
btnCustomClasses: null,
},
@classNames("dropdown-select-box")
@selectKitOptions({
autoFilterable: false,
filterable: false,
showFullTitle: true,
headerComponent: "dropdown-select-box/dropdown-select-box-header",
caretUpIcon: "caret-up",
caretDownIcon: "caret-down",
showCaret: false,
customStyle: null,
btnCustomClasses: null,
})
@pluginApiIdentifiers(["dropdown-select-box"])
export default class DropdownSelectBox extends SingleSelectComponent {
modifyComponentForRow() {
return "dropdown-select-box/dropdown-select-box-row";
},
});
}
}

View File

@ -1,32 +1,29 @@
import { computed } from "@ember/object";
import { readOnly } from "@ember/object/computed";
import { classNameBindings, classNames } from "@ember-decorators/component";
import SingleSelectHeaderComponent from "select-kit/components/select-kit/single-select-header";
export default SingleSelectHeaderComponent.extend({
classNames: ["dropdown-select-box-header"],
classNameBindings: ["btnClassName", "btnStyleClass", "btnCustomClasses"],
showFullTitle: readOnly("selectKit.options.showFullTitle"),
customStyle: readOnly("selectKit.options.customStyle"),
@classNames("dropdown-select-box-header")
@classNameBindings("btnClassName", "btnStyleClass", "btnCustomClasses")
export default class DropdownSelectBoxHeader extends SingleSelectHeaderComponent {
@readOnly("selectKit.options.showFullTitle") showFullTitle;
@readOnly("selectKit.options.customStyle") customStyle;
@readOnly("selectKit.options.btnCustomClasses") btnCustomClasses;
@readOnly("selectKit.options.caretUpIcon") caretUpIcon;
@readOnly("selectKit.options.caretDownIcon") caretDownIcon;
btnCustomClasses: readOnly("selectKit.options.btnCustomClasses"),
btnClassName: computed("showFullTitle", function () {
@computed("showFullTitle")
get btnClassName() {
return `btn ${this.showFullTitle ? "btn-icon-text" : "no-text btn-icon"}`;
}),
}
btnStyleClass: computed("customStyle", function () {
@computed("customStyle")
get btnStyleClass() {
return `${this.customStyle ? "" : "btn-default"}`;
}),
}
caretUpIcon: readOnly("selectKit.options.caretUpIcon"),
caretDownIcon: readOnly("selectKit.options.caretDownIcon"),
caretIcon: computed(
"selectKit.isExpanded",
"caretUpIcon",
"caretDownIcon",
function () {
return this.selectKit.isExpanded ? this.caretUpIcon : this.caretDownIcon;
}
),
});
@computed("selectKit.isExpanded", "caretUpIcon", "caretDownIcon")
get caretIcon() {
return this.selectKit.isExpanded ? this.caretUpIcon : this.caretDownIcon;
}
}

View File

@ -1,7 +1,8 @@
import { readOnly } from "@ember/object/computed";
import { classNames } from "@ember-decorators/component";
import SelectKitRowComponent from "select-kit/components/select-kit/select-kit-row";
export default SelectKitRowComponent.extend({
classNames: ["dropdown-select-box-row"],
description: readOnly("item.description"),
});
@classNames("dropdown-select-box-row")
export default class DropdownSelectBoxRow extends SelectKitRowComponent {
@readOnly("item.description") description;
}

View File

@ -1,9 +1,9 @@
import { action } from "@ember/object";
import { classNames } from "@ember-decorators/component";
import MultiSelectFilterComponent from "select-kit/components/multi-select/multi-select-filter";
export default MultiSelectFilterComponent.extend({
classNames: ["email-group-user-chooser-filter"],
@classNames("email-group-user-chooser-filter")
export default class EmailGroupUserChooserFilter extends MultiSelectFilterComponent {
@action
onPaste(event) {
if (this.selectKit.options.maximum === 1) {
@ -35,5 +35,5 @@ export default MultiSelectFilterComponent.extend({
return false;
}
},
});
}
}

View File

@ -1,5 +1,5 @@
import { classNames } from "@ember-decorators/component";
import SelectKitRowComponent from "select-kit/components/select-kit/select-kit-row";
export default SelectKitRowComponent.extend({
classNames: ["email-group-user-chooser-row"],
});
@classNames("email-group-user-chooser-row")
export default class EmailGroupUserChooserRow extends SelectKitRowComponent {}

View File

@ -1,24 +1,28 @@
import { classNameBindings, classNames } from "@ember-decorators/component";
import {
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
import UserChooserComponent from "select-kit/components/user-chooser";
export default UserChooserComponent.extend({
pluginApiIdentifiers: ["email-group-user-chooser"],
classNames: ["email-group-user-chooser"],
classNameBindings: ["selectKit.options.fullWidthWrap:full-width-wrap"],
valueProperty: "id",
nameProperty: "name",
@classNames("email-group-user-chooser")
@classNameBindings("selectKit.options.fullWidthWrap:full-width-wrap")
@selectKitOptions({
filterComponent: "email-group-user-chooser-filter",
fullWidthWrap: false,
autoWrap: false,
})
@pluginApiIdentifiers(["email-group-user-chooser"])
export default class EmailGroupUserChooser extends UserChooserComponent {
valueProperty = "id";
nameProperty = "name";
modifyComponentForRow() {
return "email-group-user-chooser-row";
},
selectKitOptions: {
filterComponent: "email-group-user-chooser-filter",
fullWidthWrap: false,
autoWrap: false,
},
}
search() {
const superPromise = this._super(...arguments);
const superPromise = super.search(...arguments);
if (!superPromise) {
return;
}
@ -45,5 +49,5 @@ export default UserChooserComponent.extend({
return { ...item, ...reconstructed };
});
});
},
});
}
}

View File

@ -1,33 +1,32 @@
import { computed } from "@ember/object";
import { classNames } from "@ember-decorators/component";
import ComboBoxComponent from "select-kit/components/combo-box";
import {
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
export default ComboBoxComponent.extend({
pluginApiIdentifiers: ["flair-chooser"],
classNames: ["flair-chooser"],
selectKitOptions: {
selectedNameComponent: "selected-flair",
},
@classNames("flair-chooser")
@selectKitOptions({
selectedNameComponent: "selected-flair",
})
@pluginApiIdentifiers(["flair-chooser"])
export default class FlairChooser extends ComboBoxComponent {
modifyComponentForRow() {
return "flair-row";
},
}
selectedContent: computed(
"value",
"content.[]",
"selectKit.noneItem",
function () {
const content = (this.content || []).findBy(
this.selectKit.valueProperty,
this.value
);
@computed("value", "content.[]", "selectKit.noneItem")
get selectedContent() {
const content = (this.content || []).findBy(
this.selectKit.valueProperty,
this.value
);
if (content) {
return this.selectKit.modifySelection(content);
} else {
return this.selectKit.noneItem;
}
if (content) {
return this.selectKit.modifySelection(content);
} else {
return this.selectKit.noneItem;
}
),
});
}
}

View File

@ -1,5 +1,5 @@
import { classNames } from "@ember-decorators/component";
import SelectKitRowComponent from "select-kit/components/select-kit/select-kit-row";
export default SelectKitRowComponent.extend({
classNames: ["flair-row"],
});
@classNames("flair-row")
export default class FlairRow extends SelectKitRowComponent {}

View File

@ -1,37 +1,41 @@
import { computed } from "@ember/object";
import { classNames } from "@ember-decorators/component";
import FormTemplate from "discourse/models/form-template";
import MultiSelectComponent from "select-kit/components/multi-select";
import {
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
export default MultiSelectComponent.extend({
pluginApiIdentifiers: ["form-template-chooser"],
classNames: ["form-template-chooser"],
selectKitOptions: {
none: "form_template_chooser.select_template",
},
@classNames("form-template-chooser")
@selectKitOptions({
none: "form_template_chooser.select_template",
})
@pluginApiIdentifiers("form-template-chooser")
export default class FormTemplateChooser extends MultiSelectComponent {
init() {
this._super(...arguments);
super.init(...arguments);
this.triggerSearch();
},
}
didUpdateAttrs() {
this._super(...arguments);
super.didUpdateAttrs(...arguments);
this.set("templatesLoaded", false);
this.triggerSearch();
},
}
@computed("templates")
get content() {
return this.templates;
},
}
search(filter) {
if (this.get("templatesLoaded")) {
return this._super(filter);
return super.search(filter);
} else {
return this._fetchTemplates();
}
},
}
async _fetchTemplates() {
if (this.get("loadingTemplates")) {
@ -62,9 +66,9 @@ export default MultiSelectComponent.extend({
});
return this.templates;
},
}
_sortTemplatesByName(templates) {
return templates.sort((a, b) => a.name.localeCompare(b.name));
},
});
}
}

View File

@ -1,40 +1,45 @@
import { action } from "@ember/object";
import { equal } from "@ember/object/computed";
import { isEmpty } from "@ember/utils";
import { classNames } from "@ember-decorators/component";
import ComboBoxComponent from "select-kit/components/combo-box";
import {
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
export const FORMAT = "YYYY-MM-DD HH:mmZ";
export default ComboBoxComponent.extend({
pluginApiIdentifiers: ["future-date-input-selector"],
classNames: ["future-date-input-selector"],
isCustom: equal("value", "custom"),
userTimezone: null,
@classNames("future-date-input-selector")
@selectKitOptions({
autoInsertNoneItem: false,
headerComponent:
"future-date-input-selector/future-date-input-selector-header",
})
@pluginApiIdentifiers("future-date-input-selector")
export default class FutureDateInputSelector extends ComboBoxComponent {
@equal("value", "custom") isCustom;
selectKitOptions: {
autoInsertNoneItem: false,
headerComponent:
"future-date-input-selector/future-date-input-selector-header",
},
userTimezone = null;
init() {
this._super(...arguments);
super.init(...arguments);
this.userTimezone = this.currentUser.user_option.timezone;
},
}
modifyComponentForRow() {
return "future-date-input-selector/future-date-input-selector-row";
},
}
actions: {
onChange(value) {
if (value !== "custom" && !isEmpty(value)) {
const { time } = this.content.find((x) => x.id === value);
if (time) {
this.onChangeInput?.(time.locale("en").format(FORMAT));
}
@action
_onChange(value) {
if (value !== "custom" && !isEmpty(value)) {
const { time } = this.content.find((x) => x.id === value);
if (time) {
this.onChangeInput?.(time.locale("en").format(FORMAT));
}
}
this.onChange?.(value);
},
},
});
this.onChange?.(value);
}
}

View File

@ -1,5 +1,5 @@
import { classNames } from "@ember-decorators/component";
import ComboBoxHeaderComponent from "select-kit/components/combo-box/combo-box-header";
export default ComboBoxHeaderComponent.extend({
classNames: "future-date-input-selector-header",
});
@classNames("future-date-input-selector-header")
export default class FutureDateInputSelectorHeader extends ComboBoxHeaderComponent {}

View File

@ -1,5 +1,5 @@
import { classNames } from "@ember-decorators/component";
import SelectKitRowComponent from "select-kit/components/select-kit/select-kit-row";
export default SelectKitRowComponent.extend({
classNames: ["future-date-input-selector-row"],
});
@classNames("future-date-input-selector-row")
export default class FutureDateInputSelectorRow extends SelectKitRowComponent {}

View File

@ -1,9 +1,13 @@
import { classNames } from "@ember-decorators/component";
import MultiSelectComponent from "select-kit/components/multi-select";
import {
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
export default MultiSelectComponent.extend({
pluginApiIdentifiers: ["group-chooser"],
classNames: ["group-chooser"],
selectKitOptions: {
allowAny: false,
},
});
@classNames("group-chooser")
@selectKitOptions({
allowAny: false,
})
@pluginApiIdentifiers("group-chooser")
export default class GroupChooser extends MultiSelectComponent {}

View File

@ -1,26 +1,32 @@
import { computed } from "@ember/object";
import { action, computed } from "@ember/object";
import { gte, reads } from "@ember/object/computed";
import { classNames } from "@ember-decorators/component";
import { setting } from "discourse/lib/computed";
import DiscourseURL from "discourse/lib/url";
import I18n from "discourse-i18n";
import ComboBoxComponent from "select-kit/components/combo-box";
import {
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
export default ComboBoxComponent.extend({
pluginApiIdentifiers: ["group-dropdown"],
classNames: ["group-dropdown"],
content: reads("groupsWithShortcut"),
valueProperty: null,
nameProperty: null,
hasManyGroups: gte("content.length", 10),
enableGroupDirectory: setting("enable_group_directory"),
@classNames("group-dropdown")
@selectKitOptions({
caretDownIcon: "caret-right",
caretUpIcon: "caret-down",
filterable: "hasManyGroups",
})
@pluginApiIdentifiers("group-dropdown")
export default class GroupDropdown extends ComboBoxComponent {
@reads("groupsWithShortcut") content;
@gte("content.length", 10) hasManyGroups;
@setting("enable_group_directory") enableGroupDirectory;
selectKitOptions: {
caretDownIcon: "caret-right",
caretUpIcon: "caret-down",
filterable: "hasManyGroups",
},
valueProperty = null;
nameProperty = null;
groupsWithShortcut: computed("groups.[]", function () {
@computed("groups.[]")
get groupsWithShortcut() {
const shortcuts = [];
if (this.enableGroupDirectory || this.get("currentUser.staff")) {
@ -28,15 +34,14 @@ export default ComboBoxComponent.extend({
}
return shortcuts.concat(this.groups);
}),
}
actions: {
onChange(groupName) {
if ((this.groups || []).includes(groupName)) {
DiscourseURL.routeToUrl(`/g/${groupName}`);
} else {
DiscourseURL.routeToUrl(`/g`);
}
},
},
});
@action
onChange(groupName) {
if ((this.groups || []).includes(groupName)) {
DiscourseURL.routeToUrl(`/g/${groupName}`);
} else {
DiscourseURL.routeToUrl(`/g`);
}
}
}

View File

@ -1,10 +1,13 @@
import { classNames } from "@ember-decorators/component";
import NotificationOptionsComponent from "select-kit/components/notifications-button";
import {
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
export default NotificationOptionsComponent.extend({
pluginApiIdentifiers: ["group-notifications-button"],
classNames: ["group-notifications-button"],
selectKitOptions: {
i18nPrefix: "groups.notifications",
},
});
@classNames("group-notifications-button")
@selectKitOptions({
i18nPrefix: "groups.notifications",
})
@pluginApiIdentifiers("group-notifications-button")
export default class GroupNotificationsButton extends NotificationOptionsComponent {}

View File

@ -1,4 +1,5 @@
import { computed } from "@ember/object";
import { action, computed } from "@ember/object";
import { classNames } from "@ember-decorators/component";
import $ from "jquery";
import { ajax } from "discourse/lib/ajax";
import { isDevelopment } from "discourse-common/config/environment";
@ -10,18 +11,20 @@ import {
} from "discourse-common/lib/icon-library";
import FilterForMore from "select-kit/components/filter-for-more";
import MultiSelectComponent from "select-kit/components/multi-select";
import { MAIN_COLLECTION } from "select-kit/components/select-kit";
import {
MAIN_COLLECTION,
pluginApiIdentifiers,
} from "select-kit/components/select-kit";
const MORE_ICONS_COLLECTION = "MORE_ICONS_COLLECTION";
const MAX_RESULTS_RETURNED = 200;
// Matches max returned results from icon_picker_search in svg_sprite_controller.rb
export default MultiSelectComponent.extend({
pluginApiIdentifiers: ["icon-picker"],
classNames: ["icon-picker"],
@classNames("icon-picker")
@pluginApiIdentifiers("icon-picker")
export default class IconPicker extends MultiSelectComponent {
init() {
this._super(...arguments);
super.init(...arguments);
this._cachedIconsList = null;
this._resultCount = 0;
@ -31,13 +34,13 @@ export default MultiSelectComponent.extend({
}
this.insertAfterCollection(MAIN_COLLECTION, MORE_ICONS_COLLECTION);
},
}
modifyComponentForCollection(collection) {
if (collection === MORE_ICONS_COLLECTION) {
return FilterForMore;
}
},
}
modifyContentForCollection(collection) {
if (collection === MORE_ICONS_COLLECTION) {
@ -45,11 +48,12 @@ export default MultiSelectComponent.extend({
shouldShowMoreTip: this._resultCount === MAX_RESULTS_RETURNED,
};
}
},
}
content: computed("value.[]", function () {
@computed("value.[]")
get content() {
return makeArray(this.value).map(this._processIcon);
}),
}
search(filter = "") {
if (filter === "" && this._cachedIconsList?.length) {
@ -70,7 +74,7 @@ export default MultiSelectComponent.extend({
return icons;
});
}
},
}
_processIcon(icon) {
const iconName = typeof icon === "object" ? icon.id : icon,
@ -98,11 +102,11 @@ export default MultiSelectComponent.extend({
name: iconName,
icon: strippedIconName,
};
},
}
willDestroyElement() {
$("#svg-sprites .ajax-icon-holder").remove();
this._super(...arguments);
super.willDestroyElement(...arguments);
this._cachedIconsList = null;
this._resultCount = 0;
@ -110,16 +114,15 @@ export default MultiSelectComponent.extend({
if (isDevelopment()) {
enableMissingIconWarning();
}
},
}
actions: {
onChange(value, item) {
if (this.selectKit.options.maximum === 1) {
value = value.length ? value[0] : null;
item = item.length ? item[0] : null;
}
@action
_onChange(value, item) {
if (this.selectKit.options.maximum === 1) {
value = value.length ? value[0] : null;
item = item.length ? item[0] : null;
}
this.onChange?.(value, item);
},
},
});
this.onChange?.(value, item);
}
}

View File

@ -1,40 +1,46 @@
import { computed } from "@ember/object";
import { readOnly } from "@ember/object/computed";
import { classNames } from "@ember-decorators/component";
import { makeArray } from "discourse-common/lib/helpers";
import MultiSelectComponent from "select-kit/components/multi-select";
import { MAIN_COLLECTION } from "select-kit/components/select-kit";
import {
MAIN_COLLECTION,
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
export default MultiSelectComponent.extend({
pluginApiIdentifiers: ["list-setting"],
classNames: ["list-setting"],
choices: null,
nameProperty: null,
valueProperty: null,
content: readOnly("choices"),
@classNames("list-setting")
@selectKitOptions({
filterable: true,
selectedChoiceComponent: "selectedChoiceComponent",
})
@pluginApiIdentifiers("list-setting")
export default class ListSetting extends MultiSelectComponent {
choices = null;
nameProperty = null;
valueProperty = null;
selectKitOptions: {
filterable: true,
selectedChoiceComponent: "selectedChoiceComponent",
},
@readOnly("choices") content;
modifyComponentForRow(collection) {
if (collection === MAIN_COLLECTION && this.settingName?.includes("color")) {
return "create-color-row";
}
},
}
selectedChoiceComponent: computed("settingName", function () {
@computed("settingName")
get selectedChoiceComponent() {
if (this.settingName?.includes("color")) {
return "selected-choice-color";
} else {
return "selected-choice";
}
}),
}
deselect(value) {
this.onChangeChoices &&
this.onChangeChoices([...new Set([value, ...makeArray(this.choices)])]);
this._super(...arguments);
},
});
super.deselect(...arguments);
}
}

View File

@ -1,33 +1,45 @@
import { computed } from "@ember/object";
import { empty, or } from "@ember/object/computed";
import {
attributeBindings,
classNameBindings,
classNames,
} from "@ember-decorators/component";
import { setting } from "discourse/lib/computed";
import { makeArray } from "discourse-common/lib/helpers";
import I18n from "discourse-i18n";
import MultiSelectComponent from "select-kit/components/multi-select";
import {
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
import TagsMixin from "select-kit/mixins/tags";
export default MultiSelectComponent.extend(TagsMixin, {
pluginApiIdentifiers: ["mini-tag-chooser"],
attributeBindings: ["selectKit.options.categoryId:category-id"],
classNames: ["mini-tag-chooser"],
classNameBindings: ["noTags"],
noTags: empty("value"),
maxTagSearchResults: setting("max_tag_search_results"),
maxTagsPerTopic: setting("max_tags_per_topic"),
@attributeBindings("selectKit.options.categoryId:category-id")
@classNames("mini-tag-chooser")
@classNameBindings("noTags")
@selectKitOptions({
fullWidthOnMobile: true,
filterable: true,
caretDownIcon: "caretIcon",
caretUpIcon: "caretIcon",
termMatchesForbidden: false,
categoryId: null,
everyTag: false,
closeOnChange: false,
maximum: "maxTagsPerTopic",
autoInsertNoneItem: false,
useHeaderFilter: false,
})
@pluginApiIdentifiers(["mini-tag-chooser"])
export default class MiniTagChooser extends MultiSelectComponent.extend(
TagsMixin
) {
@empty("value") noTags;
@or("allowCreate", "site.can_create_tag") allowAnyTag;
selectKitOptions: {
fullWidthOnMobile: true,
filterable: true,
caretDownIcon: "caretIcon",
caretUpIcon: "caretIcon",
termMatchesForbidden: false,
categoryId: null,
everyTag: false,
closeOnChange: false,
maximum: "maxTagsPerTopic",
autoInsertNoneItem: false,
useHeaderFilter: false,
},
@setting("max_tag_search_results") maxTagSearchResults;
@setting("max_tags_per_topic") maxTagsPerTopic;
modifyComponentForRow(collection, item) {
if (this.getValue(item) === this.selectKit.filter && !item.count) {
@ -35,7 +47,7 @@ export default MultiSelectComponent.extend(TagsMixin, {
}
return "tag-row";
},
}
modifyNoSelection() {
if (this.selectKit.options.minimum > 0) {
@ -48,18 +60,18 @@ export default MultiSelectComponent.extend(TagsMixin, {
} else {
return this.defaultItem(null, I18n.t("tagging.choose_for_topic"));
}
},
}
allowAnyTag: or("allowCreate", "site.can_create_tag"),
caretIcon: computed("value.[]", "content.[]", function () {
@computed("value.[]", "content.[]")
get caretIcon() {
const maximum = this.selectKit.options.maximum;
return maximum && makeArray(this.value).length >= parseInt(maximum, 10)
? null
: "plus";
}),
}
content: computed("value.[]", function () {
@computed("value.[]")
get content() {
let values = makeArray(this.value);
if (this.selectKit.options.hiddenValues) {
values = values.filter(
@ -67,7 +79,7 @@ export default MultiSelectComponent.extend(TagsMixin, {
);
}
return values.map((x) => this.defaultItem(x, x));
}),
}
search(filter) {
const maximum = this.selectKit.options.maximum;
@ -92,7 +104,7 @@ export default MultiSelectComponent.extend(TagsMixin, {
}
return this.searchTags("/tags/filter/search", data, this._transformJson);
},
}
_transformJson(context, json) {
if (context.isDestroyed || context.isDestroying) {
@ -123,5 +135,5 @@ export default MultiSelectComponent.extend(TagsMixin, {
}
return results.filter((r) => !makeArray(context.tags).includes(r.id));
},
});
}
}

View File

@ -1,12 +1,14 @@
import Component from "@ember/component";
import { computed } from "@ember/object";
import { reads } from "@ember/object/computed";
import { tagName } from "@ember-decorators/component";
export default Component.extend({
tagName: "",
selectedTags: reads("collection.content.selectedTags.[]"),
@tagName("")
export default class SelectedCollection extends Component {
@reads("collection.content.selectedTags.[]") selectedTags;
tags: computed("selectedTags.[]", "selectKit.filter", function () {
@computed("selectedTags.[]", "selectKit.filter")
get tags() {
if (!this.selectedTags) {
return [];
}
@ -24,5 +26,5 @@ export default Component.extend({
classNames: "selected-tag",
};
});
}),
});
}
}

View File

@ -1,14 +1,18 @@
import Component from "@ember/component";
import { computed } from "@ember/object";
import { tagName } from "@ember-decorators/component";
import { makeArray } from "discourse-common/lib/helpers";
import UtilsMixin from "select-kit/mixins/utils";
export default Component.extend(UtilsMixin, {
tagName: "",
content: null,
selectKit: null,
@tagName("")
export default class FormatSelectedContent extends Component.extend(
UtilsMixin
) {
content = null;
selectKit = null;
formattedContent: computed("content", function () {
@computed("content")
get formattedContent() {
if (this.content) {
return makeArray(this.content)
.map((c) => this.getName(c))
@ -16,5 +20,5 @@ export default Component.extend(UtilsMixin, {
} else {
return this.getName(this.selectKit.noneItem);
}
}),
});
}
}

View File

@ -1,11 +1,11 @@
import { action } from "@ember/object";
import { isEmpty } from "@ember/utils";
import { classNames } from "@ember-decorators/component";
import discourseComputed from "discourse-common/utils/decorators";
import SelectKitFilterComponent from "select-kit/components/select-kit/select-kit-filter";
export default SelectKitFilterComponent.extend({
classNames: ["multi-select-filter"],
@classNames("multi-select-filter")
export default class MultiSelectFilter extends SelectKitFilterComponent {
@discourseComputed("placeholder", "selectKit.hasSelection")
computedPlaceholder(placeholder, hasSelection) {
if (this.hidePlaceholderWithSelection && hasSelection) {
@ -13,7 +13,7 @@ export default SelectKitFilterComponent.extend({
}
return isEmpty(placeholder) ? "" : placeholder;
},
}
@action
onPaste(event) {
@ -33,5 +33,5 @@ export default SelectKitFilterComponent.extend({
return false;
}
},
});
}
}

View File

@ -1,21 +1,22 @@
import { computed } from "@ember/object";
import { reads } from "@ember/object/computed";
import {
attributeBindings,
classNames,
tagName,
} from "@ember-decorators/component";
import SelectKitHeaderComponent from "select-kit/components/select-kit/select-kit-header";
export default SelectKitHeaderComponent.extend({
tagName: "summary",
classNames: ["multi-select-header"],
attributeBindings: ["ariaLabel:aria-label"],
caretUpIcon: reads("selectKit.options.caretUpIcon"),
caretDownIcon: reads("selectKit.options.caretDownIcon"),
ariaLabel: reads("selectKit.options.headerAriaLabel"),
@tagName("summary")
@classNames("multi-select-header")
@attributeBindings("ariaLabel:aria-label")
export default class MultiSelectHeader extends SelectKitHeaderComponent {
@reads("selectKit.options.caretUpIcon") caretUpIcon;
@reads("selectKit.options.caretDownIcon") caretDownIcon;
@reads("selectKit.options.headerAriaLabel") ariaLabel;
caretIcon: computed(
"selectKit.isExpanded",
"caretUpIcon",
"caretDownIcon",
function () {
return this.selectKit.isExpanded ? this.caretUpIcon : this.caretDownIcon;
}
),
});
@computed("selectKit.isExpanded", "caretUpIcon", "caretDownIcon")
get caretIcon() {
return this.selectKit.isExpanded ? this.caretUpIcon : this.caretDownIcon;
}
}

View File

@ -1,17 +1,18 @@
import { computed } from "@ember/object";
import { htmlSafe } from "@ember/template";
import { classNames } from "@ember-decorators/component";
import { categoryBadgeHTML } from "discourse/helpers/category-link";
import SelectedNameComponent from "select-kit/components/selected-name";
export default SelectedNameComponent.extend({
classNames: ["selected-category"],
badge: computed("item", function () {
@classNames("selected-category")
export default class SelectedCategory extends SelectedNameComponent {
@computed("item")
get badge() {
return htmlSafe(
categoryBadgeHTML(this.item, {
allowUncategorized: true,
link: false,
})
);
}),
});
}
}

View File

@ -1,14 +1,14 @@
import { htmlSafe } from "@ember/template";
import { classNames } from "@ember-decorators/component";
import discourseComputed from "discourse-common/utils/decorators";
import SelectedNameComponent from "select-kit/components/selected-name";
export default SelectedNameComponent.extend({
classNames: ["select-kit-selected-color"],
@classNames("select-kit-selected-color")
export default class SelectedColor extends SelectedNameComponent {
@discourseComputed("name")
footerContent(name) {
return htmlSafe(
`<span class="color-preview" style="background:#${name}"></span>`
);
},
});
}
}

View File

@ -1,11 +1,11 @@
import { htmlSafe } from "@ember/template";
import { classNames } from "@ember-decorators/component";
import { categoryBadgeHTML } from "discourse/helpers/category-link";
import discourseComputed from "discourse-common/utils/decorators";
import CategoryRowComponent from "select-kit/components/category-row";
export default CategoryRowComponent.extend({
classNames: "none category-row",
@classNames("none category-row")
export default class NoneCategoryRow extends CategoryRowComponent {
@discourseComputed("category")
badgeForCategory(category) {
return htmlSafe(
@ -15,5 +15,5 @@ export default CategoryRowComponent.extend({
hideParent: true,
})
);
},
});
}
}

View File

@ -1,25 +1,29 @@
import { computed, setProperties } from "@ember/object";
import { classNames } from "@ember-decorators/component";
import { allLevels, buttonDetails } from "discourse/lib/notification-levels";
import I18n from "discourse-i18n";
import DropdownSelectBoxComponent from "select-kit/components/dropdown-select-box";
import {
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
export default DropdownSelectBoxComponent.extend({
pluginApiIdentifiers: ["notifications-button"],
classNames: ["notifications-button"],
content: allLevels,
nameProperty: "key",
selectKitOptions: {
autoFilterable: false,
filterable: false,
i18nPrefix: "",
i18nPostfix: "",
},
@classNames("notifications-button")
@selectKitOptions({
autoFilterable: false,
filterable: false,
i18nPrefix: "",
i18nPostfix: "",
})
@pluginApiIdentifiers("notifications-button")
export default class NotificationsButton extends DropdownSelectBoxComponent {
content = allLevels;
nameProperty = "key";
getTitle(key) {
const { i18nPrefix, i18nPostfix } = this.selectKit.options;
return I18n.t(`${i18nPrefix}.${key}${i18nPostfix}.title`);
},
}
modifyComponentForRow(_, content) {
if (content) {
@ -28,7 +32,7 @@ export default DropdownSelectBoxComponent.extend({
});
}
return "notifications-button/notifications-button-row";
},
}
modifySelection(content) {
content = content || {};
@ -39,9 +43,10 @@ export default DropdownSelectBoxComponent.extend({
icon: this.buttonForValue.icon,
});
return content;
},
}
buttonForValue: computed("value", function () {
@computed("value")
get buttonForValue() {
return buttonDetails(this.value);
}),
});
}
}

View File

@ -1,31 +1,36 @@
import { computed } from "@ember/object";
import { readOnly } from "@ember/object/computed";
import { classNames } from "@ember-decorators/component";
import { escapeExpression } from "discourse/lib/utilities";
import I18n from "discourse-i18n";
import DropdownSelectBoxRowComponent from "select-kit/components/dropdown-select-box/dropdown-select-box-row";
export default DropdownSelectBoxRowComponent.extend({
classNames: ["notifications-button-row"],
i18nPrefix: readOnly("selectKit.options.i18nPrefix"),
i18nPostfix: readOnly("selectKit.options.i18nPostfix"),
@classNames("notifications-button-row")
export default class NotificationsButtonRow extends DropdownSelectBoxRowComponent {
@readOnly("selectKit.options.i18nPrefix") i18nPrefix;
@readOnly("selectKit.options.i18nPostfix") i18nPostfix;
label: computed("_start", function () {
@computed("_start")
get label() {
return escapeExpression(I18n.t(`${this._start}.title`));
}),
}
icons: computed("item.icon", function () {
@computed("item.icon")
get icons() {
return [escapeExpression(this.item.icon)];
}),
}
description: computed("_start", function () {
@computed("_start")
get description() {
if (this.site && this.site.mobileView) {
return null;
}
return escapeExpression(I18n.t(`${this._start}.description`));
}),
}
_start: computed("i18nPrefix", "i18nPostfix", "rowName", function () {
@computed("i18nPrefix", "i18nPostfix", "rowName")
get _start() {
return `${this.i18nPrefix}.${this.rowName}${this.i18nPostfix}`;
}),
});
}
}

View File

@ -1,12 +1,18 @@
import { computed } from "@ember/object";
import { classNames } from "@ember-decorators/component";
import I18n from "discourse-i18n";
import DropdownSelectBoxComponent from "select-kit/components/dropdown-select-box";
import { selectKitOptions } from "select-kit/components/select-kit";
export default DropdownSelectBoxComponent.extend({
classNames: ["notifications-filter"],
nameProperty: "label",
@classNames("notifications-filter")
@selectKitOptions({
headerComponent: "notifications-filter/notifications-filter-header",
})
export default class NotificationsFilter extends DropdownSelectBoxComponent {
nameProperty = "label";
content: computed(function () {
@computed
get content() {
return [
{
id: "all",
@ -21,9 +27,5 @@ export default DropdownSelectBoxComponent.extend({
label: I18n.t("user.user_notifications.filters.unread"),
},
];
}),
selectKitOptions: {
headerComponent: "notifications-filter/notifications-filter-header",
},
});
}
}

View File

@ -1,13 +1,14 @@
import { classNames } from "@ember-decorators/component";
import { fmt } from "discourse/lib/computed";
import discourseComputed from "discourse-common/utils/decorators";
import DropdownSelectBoxHeaderComponent from "select-kit/components/dropdown-select-box/dropdown-select-box-header";
export default DropdownSelectBoxHeaderComponent.extend({
classNames: ["notifications-filter-header", "btn-flat"],
label: fmt("value", "user.user_notifications.filters.%@"),
@classNames("notifications-filter-header", "btn-flat")
export default class NotificationsFilterHeader extends DropdownSelectBoxHeaderComponent {
@fmt("value", "user.user_notifications.filters.%@") label;
@discourseComputed("selectKit.isExpanded")
caretIcon(isExpanded) {
return isExpanded ? "caret-up" : "caret-down";
},
});
}
}

View File

@ -1,36 +1,38 @@
import { action } from "@ember/object";
import { oneWay, readOnly } from "@ember/object/computed";
import { classNameBindings, classNames } from "@ember-decorators/component";
import I18n from "discourse-i18n";
import DropdownSelectBoxComponent from "select-kit/components/dropdown-select-box";
import { selectKitOptions } from "select-kit/components/select-kit";
export default DropdownSelectBoxComponent.extend({
classNames: ["period-chooser"],
classNameBindings: ["showPeriods::hidden"],
content: oneWay("site.periods"),
value: readOnly("period"),
valueProperty: null,
nameProperty: null,
showPeriods: true,
@classNames("period-chooser")
@classNameBindings("showPeriods::hidden")
@selectKitOptions({
filterable: false,
autoFilterable: false,
fullDay: "fullDay",
customStyle: true,
headerComponent: "period-chooser/period-chooser-header",
headerAriaLabel: I18n.t("period_chooser.aria_label"),
})
export default class PeriodChooser extends DropdownSelectBoxComponent {
@oneWay("site.periods") content;
@readOnly("period") value;
valueProperty = null;
nameProperty = null;
showPeriods = true;
modifyComponentForRow() {
return "period-chooser/period-chooser-row";
},
}
selectKitOptions: {
filterable: false,
autoFilterable: false,
fullDay: "fullDay",
customStyle: true,
headerComponent: "period-chooser/period-chooser-header",
headerAriaLabel: I18n.t("period_chooser.aria_label"),
},
actions: {
onChange(value) {
if (this.action) {
this.action(value);
} else {
this.onChange?.(value);
}
},
},
});
@action
_onChange(value) {
if (this.action) {
this.action(value);
} else {
this.onChange?.(value);
}
}
}

View File

@ -1,11 +1,11 @@
import { classNames } from "@ember-decorators/component";
import discourseComputed from "discourse-common/utils/decorators";
import DropdownSelectBoxHeaderComponent from "select-kit/components/dropdown-select-box/dropdown-select-box-header";
export default DropdownSelectBoxHeaderComponent.extend({
classNames: ["period-chooser-header", "btn-flat"],
@classNames("period-chooser-header", "btn-flat")
export default class PeriodChooserHeader extends DropdownSelectBoxHeaderComponent {
@discourseComputed("selectKit.isExpanded")
caretIcon(isExpanded) {
return isExpanded ? "caret-up" : "caret-down";
},
});
}
}

View File

@ -1,12 +1,12 @@
import { classNames } from "@ember-decorators/component";
import discourseComputed from "discourse-common/utils/decorators";
import I18n from "discourse-i18n";
import DropdownSelectBoxRowComponent from "select-kit/components/dropdown-select-box/dropdown-select-box-row";
export default DropdownSelectBoxRowComponent.extend({
classNames: ["period-chooser-row"],
@classNames("period-chooser-row")
export default class PeriodChooserRow extends DropdownSelectBoxRowComponent {
@discourseComputed("rowName")
title(rowName) {
return I18n.t(`filters.top.${rowName || "this_week"}`).title;
},
});
}
}

View File

@ -1,12 +1,14 @@
import Component from "@ember/component";
import { classNameBindings, classNames } from "@ember-decorators/component";
import discourseComputed from "discourse-common/utils/decorators";
import I18n from "discourse-i18n";
import { pluginApiIdentifiers } from "select-kit/components/select-kit";
export default Component.extend({
pluginApiIdentifiers: ["pinned-button"],
descriptionKey: "help",
classNames: "pinned-button",
classNameBindings: ["isHidden"],
@classNames("pinned-button")
@classNameBindings("isHidden")
@pluginApiIdentifiers("pinned-button")
export default class PinnedButton extends Component {
descriptionKey = "help";
@discourseComputed("topic.pinned_globally", "pinned")
reasonText(pinnedGlobally, pinned) {
@ -14,10 +16,10 @@ export default Component.extend({
const pinnedKey = pinned ? `pinned${globally}` : "unpinned";
const key = `topic_statuses.${pinnedKey}.help`;
return I18n.t(key);
},
}
@discourseComputed("pinned", "topic.deleted", "topic.unpinned")
isHidden(pinned, deleted, unpinned) {
return deleted || (!pinned && !unpinned);
},
});
}
}

View File

@ -1,19 +1,22 @@
import { action, computed } from "@ember/object";
import { htmlSafe } from "@ember/template";
import { classNames } from "@ember-decorators/component";
import I18n from "discourse-i18n";
import DropdownSelectBoxComponent from "select-kit/components/dropdown-select-box";
import {
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
const UNPINNED = "unpinned";
const PINNED = "pinned";
export default DropdownSelectBoxComponent.extend({
pluginApiIdentifiers: ["pinned-options"],
classNames: ["pinned-options"],
selectKitOptions: {
showCaret: true,
},
@classNames("pinned-options")
@selectKitOptions({
showCaret: true,
})
@pluginApiIdentifiers("pinned-options")
export default class PinnedOptions extends DropdownSelectBoxComponent {
modifySelection(content) {
const pinnedGlobally = this.get("topic.pinned_globally");
const pinned = this.value;
@ -26,9 +29,10 @@ export default DropdownSelectBoxComponent.extend({
content.name = state;
content.icon = `thumbtack${state === UNPINNED ? " unpinned" : ""}`;
return content;
},
}
content: computed(function () {
@computed
get content() {
const globally = this.topic.pinned_globally ? "_globally" : "";
return [
@ -49,7 +53,7 @@ export default DropdownSelectBoxComponent.extend({
: I18n.t("topic_statuses.unpinned.help"),
},
];
}),
}
@action
onChange(value) {
@ -60,5 +64,5 @@ export default DropdownSelectBoxComponent.extend({
} else {
return topic.rePin();
}
},
});
}
}

View File

@ -1,14 +1,17 @@
import { classNames } from "@ember-decorators/component";
import CategoryChooserComponent from "select-kit/components/category-chooser";
import {
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
export default CategoryChooserComponent.extend({
pluginApiIdentifiers: ["search-advanced-category-chooser"],
classNames: ["search-advanced-category-chooser"],
selectKitOptions: {
allowUncategorized: true,
clearable: true,
none: "category.all",
displayCategoryDescription: false,
permissionType: null,
},
});
@classNames("search-advanced-category-chooser")
@selectKitOptions({
allowUncategorized: true,
clearable: true,
none: "category.all",
displayCategoryDescription: false,
permissionType: null,
})
@pluginApiIdentifiers("search-advanced-category-chooser")
export default class SearchAdvancedCategoryChooser extends CategoryChooserComponent {}

View File

@ -1,5 +1,5 @@
import Component from "@ember/component";
import { tagName } from "@ember-decorators/component";
export default Component.extend({
tagName: "",
});
@tagName("")
export default class ErrorsCollection extends Component {}

View File

@ -1,33 +1,34 @@
import Component from "@ember/component";
import { computed } from "@ember/object";
import { next } from "@ember/runloop";
import { classNameBindings, classNames } from "@ember-decorators/component";
import { bind } from "discourse-common/utils/decorators";
export default Component.extend({
classNames: ["select-kit-body"],
classNameBindings: ["emptyBody:empty-body"],
emptyBody: computed("selectKit.{filter,hasNoContent}", function () {
@classNames("select-kit-body")
@classNameBindings("emptyBody:empty-body")
export default class SelectKitBody extends Component {
@computed("selectKit.{filter,hasNoContent}")
get emptyBody() {
return false;
}),
}
didInsertElement() {
this._super(...arguments);
super.didInsertElement(...arguments);
this.element.style.position = "relative";
document.addEventListener("click", this.handleClick, true);
this.selectKit
.mainElement()
.addEventListener("keydown", this._handleKeydown, true);
},
}
willDestroyElement() {
this._super(...arguments);
super.willDestroyElement(...arguments);
document.removeEventListener("click", this.handleClick, true);
this.selectKit
.mainElement()
?.removeEventListener("keydown", this._handleKeydown, true);
},
}
@bind
handleClick(event) {
@ -40,7 +41,7 @@ export default Component.extend({
}
this.selectKit.close(event);
},
}
@bind
_handleKeydown(event) {
@ -59,5 +60,5 @@ export default Component.extend({
this.selectKit.close(event);
});
},
});
}
}

View File

@ -1,19 +1,19 @@
import { cached } from "@glimmer/tracking";
import Component from "@ember/component";
import { action } from "@ember/object";
import { tagName } from "@ember-decorators/component";
import {
disableBodyScroll,
enableBodyScroll,
} from "discourse/lib/body-scroll-lock";
export default Component.extend({
tagName: "",
@tagName("")
export default class SelectKitCollection extends Component {
@cached
get inModal() {
const element = this.selectKit.mainElement();
return element.closest(".d-modal");
},
}
@action
lock(element) {
@ -22,10 +22,10 @@ export default Component.extend({
}
disableBodyScroll(element);
},
}
@action
unlock(element) {
enableBodyScroll(element);
},
});
}
}

View File

@ -1,5 +1,5 @@
import { classNames } from "@ember-decorators/component";
import SelectKitRowComponent from "select-kit/components/select-kit/select-kit-row";
export default SelectKitRowComponent.extend({
classNames: "create",
});
@classNames("create")
export default class SelectKitCreateRow extends SelectKitRowComponent {}

View File

@ -2,29 +2,33 @@ import Component from "@ember/component";
import { action, computed } from "@ember/object";
import { not } from "@ember/object/computed";
import { isPresent } from "@ember/utils";
import {
attributeBindings,
classNameBindings,
classNames,
} from "@ember-decorators/component";
import discourseComputed from "discourse-common/utils/decorators";
import I18n from "discourse-i18n";
import UtilsMixin from "select-kit/mixins/utils";
export default Component.extend(UtilsMixin, {
classNames: ["select-kit-filter"],
classNameBindings: ["isExpanded:is-expanded"],
attributeBindings: ["role"],
tabIndex: -1,
@classNames("select-kit-filter")
@classNameBindings("isExpanded:is-expanded")
@attributeBindings("role")
export default class SelectKitFilter extends Component.extend(UtilsMixin) {
tabIndex = -1;
isHidden: computed(
@not("isHidden") isExpanded;
@computed(
"selectKit.options.{filterable,allowAny,autoFilterable}",
"content.[]",
function () {
return (
!this.selectKit.options.filterable &&
!this.selectKit.options.allowAny &&
!this.selectKit.options.autoFilterable
);
}
),
isExpanded: not("isHidden"),
"content.[]"
)
get isHidden() {
return (
!this.selectKit.options.filterable &&
!this.selectKit.options.allowAny &&
!this.selectKit.options.autoFilterable
);
}
@discourseComputed(
"selectKit.options.filterPlaceholder",
@ -45,23 +49,23 @@ export default Component.extend(UtilsMixin, {
? "select_kit.filter_placeholder_with_any"
: "select_kit.filter_placeholder"
);
},
}
@action
onPaste() {},
onPaste() {}
@action
onInput(event) {
this.selectKit.onInput(event);
return true;
},
}
@action
onKeyup(event) {
event.preventDefault();
event.stopImmediatePropagation();
return true;
},
}
@action
onKeydown(event) {
@ -131,5 +135,5 @@ export default Component.extend(UtilsMixin, {
}
this.selectKit.set("highlighted", null);
},
});
}
}

View File

@ -1,39 +1,44 @@
import Component from "@ember/component";
import { computed } from "@ember/object";
import {
attributeBindings,
classNameBindings,
classNames,
} from "@ember-decorators/component";
import { makeArray } from "discourse-common/lib/helpers";
import UtilsMixin from "select-kit/mixins/utils";
export default Component.extend(UtilsMixin, {
classNames: ["select-kit-header"],
classNameBindings: ["isFocused"],
attributeBindings: [
"role",
"tabindex",
"selectedValue:data-value",
"selectedNames:data-name",
"buttonTitle:title",
"selectKit.options.autofocus:autofocus",
],
@classNames("select-kit-header")
@classNameBindings("isFocused")
@attributeBindings(
"role",
"tabindex",
"selectedValue:data-value",
"selectedNames:data-name",
"buttonTitle:title",
"selectKit.options.autofocus:autofocus"
)
export default class SelectKitHeader extends Component.extend(UtilsMixin) {
selectKit = null;
role = "listbox";
tabindex = 0;
selectKit: null,
role: "listbox",
tabindex: 0,
selectedValue: computed("value", function () {
@computed("value")
get selectedValue() {
return this.value === this.getValue(this.selectKit.noneItem)
? null
: makeArray(this.value).join(",");
}),
}
selectedNames: computed("selectedContent.[]", function () {
@computed("selectedContent.[]")
get selectedNames() {
return makeArray(this.selectedContent)
.map((s) => this.getName(s))
.join(",");
}),
}
buttonTitle: computed("value", "selectKit.noneItem", function () {
@computed("value", "selectKit.noneItem")
get buttonTitle() {
if (
!this.value &&
this.selectKit.noneItem &&
@ -41,24 +46,25 @@ export default Component.extend(UtilsMixin, {
) {
return this.selectKit.noneItem.title || this.selectKit.noneItem.name;
}
}),
}
icons: computed("selectKit.options.{icon,icons}", function () {
@computed("selectKit.options.{icon,icons}")
get icons() {
const icon = makeArray(this.selectKit.options.icon);
const icons = makeArray(this.selectKit.options.icons);
return icon.concat(icons).filter(Boolean);
}),
}
didInsertElement() {
this._super(...arguments);
super.didInsertElement(...arguments);
if (this.selectKit.options.autofocus) {
this.set("isFocused", true);
}
},
}
mouseDown() {
return false;
},
}
click(event) {
event.preventDefault();
@ -71,13 +77,13 @@ export default Component.extend(UtilsMixin, {
return false;
}
this.selectKit.toggle(event);
},
}
keyUp(event) {
if (event.key === " ") {
event.preventDefault();
}
},
}
keyDown(event) {
if (
@ -165,7 +171,7 @@ export default Component.extend(UtilsMixin, {
return true;
}
}
},
}
_focusFilterInput() {
const filterContainer = document.querySelector(
@ -178,5 +184,5 @@ export default Component.extend(UtilsMixin, {
const filterInput = filterContainer.querySelector(".filter-input");
filterInput && filterInput.focus();
}
},
});
}
}

View File

@ -1,5 +1,5 @@
import { classNames } from "@ember-decorators/component";
import SelectKitRowComponent from "select-kit/components/select-kit/select-kit-row";
export default SelectKitRowComponent.extend({
classNames: "none",
});
@classNames("none")
export default class SelectKitNoneRow extends SelectKitRowComponent {}

View File

@ -3,81 +3,89 @@ import { action, computed } from "@ember/object";
import { reads } from "@ember/object/computed";
import { guidFor } from "@ember/object/internals";
import { dasherize } from "@ember/string";
import {
attributeBindings,
classNameBindings,
classNames,
tagName,
} from "@ember-decorators/component";
import { makeArray } from "discourse-common/lib/helpers";
import I18n from "discourse-i18n";
import UtilsMixin from "select-kit/mixins/utils";
export default Component.extend(UtilsMixin, {
classNames: ["select-kit-row"],
tagName: "li",
tabIndex: 0,
attributeBindings: [
"tabIndex",
"title",
"rowValue:data-value",
"rowName:data-name",
"index:data-index",
"role",
"ariaChecked:aria-checked",
"guid:data-guid",
"rowLang:lang",
],
classNameBindings: [
"isHighlighted",
"isSelected",
"isNone",
"isNone:none",
"item.classNames",
],
index: 0,
role: "menuitemradio",
@classNames("select-kit-row")
@tagName("li")
@attributeBindings(
"tabIndex",
"title",
"rowValue:data-value",
"rowName:data-name",
"index:data-index",
"role",
"ariaChecked:aria-checked",
"guid:data-guid",
"rowLang:lang"
)
@classNameBindings(
"isHighlighted",
"isSelected",
"isNone",
"isNone:none",
"item.classNames"
)
export default class SelectKitRow extends Component.extend(UtilsMixin) {
tabIndex = 0;
index = 0;
role = "menuitemradio";
@reads("item.lang") lang;
didInsertElement() {
this._super(...arguments);
super.didInsertElement(...arguments);
if (this.site.desktopView) {
this.element.addEventListener("mouseenter", this.handleMouseEnter);
this.element.addEventListener("focus", this.handleMouseEnter);
}
},
}
willDestroyElement() {
this._super(...arguments);
super.willDestroyElement(...arguments);
if (this.site.desktopView) {
this.element.removeEventListener("mouseenter", this.handleMouseEnter);
this.element.removeEventListener("focus", this.handleMouseEnter);
}
},
}
isNone: computed("rowValue", function () {
@computed("rowValue")
get isNone() {
return this.rowValue === this.getValue(this.selectKit.noneItem);
}),
}
guid: computed("item", function () {
@computed("item")
get guid() {
return guidFor(this.item);
}),
}
lang: reads("item.lang"),
ariaChecked: computed("isSelected", function () {
@computed("isSelected")
get ariaChecked() {
return this.isSelected ? "true" : "false";
}),
}
title: computed("rowTitle", "item.title", "rowName", function () {
@computed("rowTitle", "item.title", "rowName")
get title() {
return (
this.rowTitle || this.getProperty(this.item, "title") || this.rowName
);
}),
}
dasherizedTitle: computed("title", function () {
@computed("title")
get dasherizedTitle() {
return dasherize((this.title || "").replace(".", "-"));
}),
}
label: computed("rowLabel", "item.label", "title", "rowName", function () {
@computed("rowLabel", "item.label", "title", "rowName")
get label() {
const label =
this.rowLabel ||
this.getProperty(this.item, "label") ||
@ -92,10 +100,10 @@ export default Component.extend(UtilsMixin, {
return I18n.t("select_kit.create", { content: label });
}
return label;
}),
}
didReceiveAttrs() {
this._super(...arguments);
super.didReceiveAttrs(...arguments);
this.setProperties({
rowName: this.getName(this.item),
@ -104,25 +112,29 @@ export default Component.extend(UtilsMixin, {
rowTitle: this.getProperty(this.item, "titleProperty"),
rowLang: this.getProperty(this.item, "langProperty"),
});
},
}
icons: computed("item.{icon,icons}", function () {
@computed("item.{icon,icons}")
get icons() {
const icon = makeArray(this.getProperty(this.item, "icon"));
const icons = makeArray(this.getProperty(this.item, "icons"));
return icon.concat(icons).filter(Boolean);
}),
}
highlightedValue: computed("selectKit.highlighted", function () {
@computed("selectKit.highlighted")
get highlightedValue() {
return this.getValue(this.selectKit.highlighted);
}),
}
isHighlighted: computed("rowValue", "highlightedValue", function () {
@computed("rowValue", "highlightedValue")
get isHighlighted() {
return this.rowValue === this.highlightedValue;
}),
}
isSelected: computed("rowValue", "value", function () {
@computed("rowValue", "value")
get isSelected() {
return this.rowValue === this.value;
}),
}
@action
handleMouseEnter() {
@ -130,24 +142,24 @@ export default Component.extend(UtilsMixin, {
this.selectKit.onHover(this.rowValue, this.item);
}
return false;
},
}
click(event) {
event.preventDefault();
event.stopPropagation();
this.selectKit.select(this.rowValue, this.item);
return false;
},
}
mouseDown(event) {
if (this.selectKit.options.preventHeaderFocus) {
event.preventDefault();
}
},
}
focusIn(event) {
event.stopImmediatePropagation();
},
}
keyDown(event) {
if (this.selectKit.isExpanded) {
@ -189,5 +201,5 @@ export default Component.extend(UtilsMixin, {
}
}
}
},
});
}
}

View File

@ -1,14 +1,18 @@
import { computed } from "@ember/object";
import { or } from "@ember/object/computed";
import {
attributeBindings,
classNames,
tagName,
} from "@ember-decorators/component";
import I18n from "discourse-i18n";
import SelectKitHeaderComponent from "select-kit/components/select-kit/select-kit-header";
import UtilsMixin from "select-kit/mixins/utils";
export default SelectKitHeaderComponent.extend(UtilsMixin, {
tagName: "summary",
classNames: ["single-select-header"],
attributeBindings: ["name", "ariaLabel:aria-label"],
ariaLabel: or("selectKit.options.headerAriaLabel", "name"),
@tagName("summary")
@classNames("single-select-header")
@attributeBindings("name", "ariaLabel:aria-label")
export default class SingleSelectHeader extends SelectKitHeaderComponent {
@or("selectKit.options.headerAriaLabel", "name") ariaLabel;
focusIn(event) {
event.stopImmediatePropagation();
@ -18,9 +22,10 @@ export default SelectKitHeaderComponent.extend(UtilsMixin, {
header.parentNode.open = false;
}
});
},
}
name: computed("selectedContent.name", function () {
@computed("selectedContent.name")
get name() {
if (this.selectedContent) {
return I18n.t("select_kit.filter_by", {
name: this.getName(this.selectedContent),
@ -28,5 +33,5 @@ export default SelectKitHeaderComponent.extend(UtilsMixin, {
} else {
return I18n.t("select_kit.select_to_filter");
}
}),
});
}
}

View File

@ -1,18 +1,20 @@
import { computed } from "@ember/object";
import { htmlSafe } from "@ember/template";
import { tagName } from "@ember-decorators/component";
import { categoryBadgeHTML } from "discourse/helpers/category-link";
import SelectedChoiceComponent from "select-kit/components/selected-choice";
export default SelectedChoiceComponent.extend({
tagName: "",
extraClass: "selected-choice-category",
@tagName("")
export default class SelectedChoiceCategory extends SelectedChoiceComponent {
extraClass = "selected-choice-category";
badge: computed("item", function () {
@computed("item")
get badge() {
return htmlSafe(
categoryBadgeHTML(this.item, {
allowUncategorized: true,
link: false,
})
);
}),
});
}
}

View File

@ -1,20 +1,21 @@
import { computed } from "@ember/object";
import { schedule } from "@ember/runloop";
import { tagName } from "@ember-decorators/component";
import { escapeExpression } from "discourse/lib/utilities";
import SelectedChoiceComponent from "select-kit/components/selected-choice";
export default SelectedChoiceComponent.extend({
tagName: "",
@tagName("")
export default class SelectedChoiceColor extends SelectedChoiceComponent {
extraClass = "selected-choice-color";
extraClass: "selected-choice-color",
escapedColor: computed("item", function () {
@computed("item")
get escapedColor() {
const color = `${escapeExpression(this.item?.name || this.item)}`;
return color.startsWith("#") ? color : `#${color}`;
}),
}
didInsertElement() {
this._super(...arguments);
super.didInsertElement(...arguments);
schedule("afterRender", () => {
const element = document.querySelector(
@ -27,5 +28,5 @@ export default SelectedChoiceComponent.extend({
element.style.borderBottomColor = this.escapedColor;
});
},
});
}
}

View File

@ -1,34 +1,39 @@
import Component from "@ember/component";
import { computed } from "@ember/object";
import { guidFor } from "@ember/object/internals";
import { tagName } from "@ember-decorators/component";
import UtilsMixin from "select-kit/mixins/utils";
export default Component.extend(UtilsMixin, {
tagName: "",
item: null,
selectKit: null,
extraClass: null,
id: null,
@tagName("")
export default class SelectedChoice extends Component.extend(UtilsMixin) {
item = null;
selectKit = null;
extraClass = null;
id = null;
init() {
this._super(...arguments);
super.init(...arguments);
this.set("id", guidFor(this));
},
}
itemValue: computed("item", function () {
@computed("item")
get itemValue() {
return this.getValue(this.item);
}),
}
itemName: computed("item", function () {
@computed("item")
get itemName() {
return this.getName(this.item);
}),
}
mandatoryValuesArray: computed("item", function () {
@computed("item")
get mandatoryValuesArray() {
return this.get("mandatoryValues")?.split("|") || [];
}),
}
readOnly: computed("item", function () {
@computed("item")
get readOnly() {
return this.mandatoryValuesArray.includes(this.item.id);
}),
});
}
}

View File

@ -1,12 +1,12 @@
import { schedule } from "@ember/runloop";
import { classNames } from "@ember-decorators/component";
import { escapeExpression } from "discourse/lib/utilities";
import SelectedNameComponent from "select-kit/components/selected-name";
export default SelectedNameComponent.extend({
classNames: ["select-kit-selected-color"],
@classNames("select-kit-selected-color")
export default class SelectedColor extends SelectedNameComponent {
didInsertElement() {
this._super(...arguments);
super.didInsertElement(...arguments);
schedule("afterRender", () => {
const element = document.querySelector(
@ -21,5 +21,5 @@ export default SelectedNameComponent.extend({
const color = escapeExpression(this.name);
element.style.borderBottomColor = `#${color}`;
});
},
});
}
}

View File

@ -1,5 +1,5 @@
import { tagName } from "@ember-decorators/component";
import SelectedNameComponent from "select-kit/components/selected-name";
export default SelectedNameComponent.extend({
tagName: "",
});
@tagName("")
export default class SelectedFlair extends SelectedNameComponent {}

View File

@ -2,26 +2,29 @@ import Component from "@ember/component";
import { computed, get } from "@ember/object";
import { reads } from "@ember/object/computed";
import { guidFor } from "@ember/object/internals";
import { tagName } from "@ember-decorators/component";
import { makeArray } from "discourse-common/lib/helpers";
import UtilsMixin from "select-kit/mixins/utils";
export default Component.extend(UtilsMixin, {
tagName: "",
name: null,
value: null,
headerTitle: null,
headerLang: null,
headerLabel: null,
id: null,
@tagName("")
export default class SelectedName extends Component.extend(UtilsMixin) {
name = null;
value = null;
headerTitle = null;
headerLang = null;
headerLabel = null;
id = null;
@reads("headerLang") lang;
init() {
this._super(...arguments);
super.init(...arguments);
this.set("id", guidFor(this));
},
}
didReceiveAttrs() {
this._super(...arguments);
super.didReceiveAttrs(...arguments);
// we can't listen on `item.nameProperty` given it's variable
this.setProperties({
@ -32,43 +35,46 @@ export default Component.extend(UtilsMixin, {
value:
this.item === this.selectKit.noneItem ? null : this.getValue(this.item),
});
},
}
lang: reads("headerLang"),
ariaLabel: computed("item", "sanitizedTitle", function () {
@computed("item", "sanitizedTitle")
get ariaLabel() {
return this._safeProperty("ariaLabel", this.item) || this.sanitizedTitle;
}),
}
// this might need a more advanced solution
// but atm it's the only case we have to handle
sanitizedTitle: computed("title", function () {
@computed("title")
get sanitizedTitle() {
return String(this.title).replace("&hellip;", "");
}),
}
title: computed("headerTitle", "item", function () {
@computed("headerTitle", "item")
get title() {
return (
this.headerTitle ||
this._safeProperty("title", this.item) ||
this.name ||
""
);
}),
}
label: computed("headerLabel", "title", "name", function () {
@computed("headerLabel", "title", "name")
get label() {
return (
this.headerLabel ||
this._safeProperty("label", this.item) ||
this.title ||
this.name
);
}),
}
icons: computed("item.{icon,icons}", function () {
@computed("item.{icon,icons}")
get icons() {
const icon = makeArray(this._safeProperty("icon", this.item));
const icons = makeArray(this._safeProperty("icons", this.item));
return icon.concat(icons).filter(Boolean);
}),
}
_safeProperty(name, content) {
if (!content) {
@ -76,5 +82,5 @@ export default Component.extend(UtilsMixin, {
}
return get(content, name);
},
});
}
}

View File

@ -1,5 +1,5 @@
import { classNames } from "@ember-decorators/component";
import SelectKitRowComponent from "select-kit/components/select-kit/select-kit-row";
export default SelectKitRowComponent.extend({
classNames: ["tag-chooser-row"],
});
@classNames("tag-chooser-row")
export default class TagChooserRow extends SelectKitRowComponent {}

View File

@ -1,19 +1,27 @@
import { computed } from "@ember/object";
import { action, computed } from "@ember/object";
import { attributeBindings, classNames } from "@ember-decorators/component";
import { makeArray } from "discourse-common/lib/helpers";
import MultiSelectComponent from "select-kit/components/multi-select";
import {
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
import TagsMixin from "select-kit/mixins/tags";
export default MultiSelectComponent.extend(TagsMixin, {
pluginApiIdentifiers: ["tag-chooser"],
classNames: ["tag-chooser"],
selectKitOptions: {
filterable: true,
filterPlaceholder: "tagging.choose_for_topic",
limit: null,
allowAny: "canCreateTag",
maximum: "maximumTagCount",
},
@classNames("tag-chooser")
@attributeBindings("categoryId")
@selectKitOptions({
filterable: true,
filterPlaceholder: "tagging.choose_for_topic",
limit: null,
allowAny: "canCreateTag",
maximum: "maximumTagCount",
})
@pluginApiIdentifiers("tag-chooser")
export default class TagChooser extends MultiSelectComponent.extend(TagsMixin) {
blockedTags = null;
excludeSynonyms = false;
excludeHasSynonyms = false;
modifyComponentForRow(collection, item) {
if (this.getValue(item) === this.selectKit.filter && !item.count) {
@ -21,63 +29,57 @@ export default MultiSelectComponent.extend(TagsMixin, {
}
return "tag-chooser-row";
},
}
blockedTags: null,
attributeBindings: ["categoryId"],
excludeSynonyms: false,
excludeHasSynonyms: false,
canCreateTag: computed("site.can_create_tag", "allowCreate", function () {
@computed("site.can_create_tag", "allowCreate")
get canCreateTag() {
return this.allowCreate && this.site.can_create_tag;
}),
}
maximumTagCount: computed(
"siteSettings.max_tags_per_topic",
"unlimitedTagCount",
function () {
if (!this.unlimitedTagCount) {
return parseInt(
this.options.limit ||
this.options.maximum ||
this.siteSettings.max_tags_per_topic,
10
);
}
return null;
@computed("siteSettings.max_tags_per_topic", "unlimitedTagCount")
get maximumTagCount() {
if (!this.unlimitedTagCount) {
return parseInt(
this.options.limit ||
this.options.maximum ||
this.siteSettings.max_tags_per_topic,
10
);
}
),
return null;
}
init() {
this._super(...arguments);
super.init(...arguments);
this.setProperties({
blockedTags: this.blockedTags || [],
termMatchesForbidden: false,
termMatchErrorMessage: null,
});
},
}
value: computed("tags.[]", function () {
@computed("tags.[]")
get value() {
return makeArray(this.tags).uniq();
}),
}
content: computed("tags.[]", function () {
@computed("tags.[]")
get content() {
return makeArray(this.tags)
.uniq()
.map((t) => this.defaultItem(t, t));
}),
}
actions: {
onChange(value, items) {
if (this.onChange) {
this.onChange(value, items);
} else {
this.set("tags", value);
}
},
},
@action
_onChange(value, items) {
if (this.onChange) {
this.onChange(value, items);
} else {
this.set("tags", value);
}
}
search(query) {
const selectedTags = makeArray(this.tags).filter(Boolean);
@ -106,7 +108,7 @@ export default MultiSelectComponent.extend(TagsMixin, {
}
return this.searchTags("/tags/filter/search", data, this._transformJson);
},
}
_transformJson(context, json) {
if (context.isDestroyed || context.isDestroying) {
@ -131,5 +133,5 @@ export default MultiSelectComponent.extend(TagsMixin, {
}
return results.uniqBy("id");
},
});
}
}

View File

@ -1,12 +1,17 @@
import { computed } from "@ember/object";
import { action, computed } from "@ember/object";
import { readOnly } from "@ember/object/computed";
import { classNameBindings, classNames } from "@ember-decorators/component";
import { setting } from "discourse/lib/computed";
import DiscourseURL, { getCategoryAndTagUrl } from "discourse/lib/url";
import { makeArray } from "discourse-common/lib/helpers";
import I18n from "discourse-i18n";
import ComboBoxComponent from "select-kit/components/combo-box";
import FilterForMore from "select-kit/components/filter-for-more";
import { MAIN_COLLECTION } from "select-kit/components/select-kit";
import {
MAIN_COLLECTION,
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
import TagsMixin from "select-kit/mixins/tags";
export const NO_TAG_ID = "no-tags";
@ -16,48 +21,45 @@ export const NONE_TAG = "none";
const MORE_TAGS_COLLECTION = "MORE_TAGS_COLLECTION";
export default ComboBoxComponent.extend(TagsMixin, {
pluginApiIdentifiers: ["tag-drop"],
classNameBindings: ["tagClass"],
classNames: ["tag-drop"],
value: readOnly("tagId"),
maxTagSearchResults: setting("max_tag_search_results"),
sortTagsAlphabetically: setting("tags_sort_alphabetically"),
maxTagsInFilterList: setting("max_tags_in_filter_list"),
shouldShowMoreTags: computed(
"maxTagsInFilterList",
"topTags.[]",
"mainCollection.[]",
function () {
if (this.selectKit.filter?.length > 0) {
return this.mainCollection.length > this.maxTagsInFilterList;
} else {
return this.topTags.length > this.maxTagsInFilterList;
}
}
),
@classNameBindings("tagClass")
@classNames("tag-drop")
@selectKitOptions({
allowAny: false,
caretDownIcon: "caret-right",
caretUpIcon: "caret-down",
fullWidthOnMobile: true,
filterable: true,
headerComponent: "tag-drop/tag-drop-header",
autoInsertNoneItem: false,
})
@pluginApiIdentifiers("tag-drop")
export default class TagDrop extends ComboBoxComponent.extend(TagsMixin) {
@setting("max_tag_search_results") maxTagSearchResults;
@setting("tags_sort_alphabetically") sortTagsAlphabetically;
@setting("max_tags_in_filter_list") maxTagsInFilterList;
selectKitOptions: {
allowAny: false,
caretDownIcon: "caret-right",
caretUpIcon: "caret-down",
fullWidthOnMobile: true,
filterable: true,
headerComponent: "tag-drop/tag-drop-header",
autoInsertNoneItem: false,
},
@readOnly("tagId") value;
@computed("maxTagsInFilterList", "topTags.[]", "mainCollection.[]")
get shouldShowMoreTags() {
if (this.selectKit.filter?.length > 0) {
return this.mainCollection.length > this.maxTagsInFilterList;
} else {
return this.topTags.length > this.maxTagsInFilterList;
}
}
init() {
this._super(...arguments);
super.init(...arguments);
this.insertAfterCollection(MAIN_COLLECTION, MORE_TAGS_COLLECTION);
},
}
modifyComponentForCollection(collection) {
if (collection === MORE_TAGS_COLLECTION) {
return FilterForMore;
}
},
}
modifyContentForCollection(collection) {
if (collection === MORE_TAGS_COLLECTION) {
@ -65,7 +67,7 @@ export default ComboBoxComponent.extend(TagsMixin, {
shouldShowMoreTip: this.shouldShowMoreTags,
};
}
},
}
modifyNoSelection() {
if (this.tagId === NONE_TAG) {
@ -73,7 +75,7 @@ export default ComboBoxComponent.extend(TagsMixin, {
} else {
return this.defaultItem(ALL_TAGS_ID, I18n.t("tagging.selector_tags"));
}
},
}
modifySelection(content) {
if (this.tagId === NONE_TAG) {
@ -83,17 +85,19 @@ export default ComboBoxComponent.extend(TagsMixin, {
}
return content;
},
}
tagClass: computed("tagId", function () {
@computed("tagId")
get tagClass() {
return this.tagId ? `tag-${this.tagId}` : "tag_all";
}),
}
modifyComponentForRow() {
return "tag-row";
},
}
shortcuts: computed("tagId", function () {
@computed("tagId")
get shortcuts() {
const shortcuts = [];
if (this.tagId) {
@ -117,29 +121,26 @@ export default ComboBoxComponent.extend(TagsMixin, {
}
return shortcuts;
}),
}
topTags: computed(
"currentCategory",
"site.category_top_tags.[]",
"site.top_tags.[]",
function () {
if (this.currentCategory && this.site.category_top_tags) {
return this.site.category_top_tags || [];
}
return this.site.top_tags || [];
@computed("currentCategory", "site.category_top_tags.[]", "site.top_tags.[]")
get topTags() {
if (this.currentCategory && this.site.category_top_tags) {
return this.site.category_top_tags || [];
}
),
content: computed("topTags.[]", "shortcuts.[]", function () {
return this.site.top_tags || [];
}
@computed("topTags.[]", "shortcuts.[]")
get content() {
const topTags = this.topTags.slice(0, this.maxTagsInFilterList);
if (this.sortTagsAlphabetically && topTags) {
return this.shortcuts.concat(topTags.sort());
} else {
return this.shortcuts.concat(makeArray(topTags));
}
}),
}
search(filter) {
if (filter) {
@ -157,7 +158,7 @@ export default ComboBoxComponent.extend(TagsMixin, {
return this.defaultItem(tag, tag);
});
}
},
}
_transformJson(context, json) {
return json.results
@ -171,21 +172,20 @@ export default ComboBoxComponent.extend(TagsMixin, {
content.pmCount = r.pm_count;
return content;
});
},
}
actions: {
onChange(tagId, tag) {
if (tagId === NO_TAG_ID) {
tagId = NONE_TAG;
} else if (tagId === ALL_TAGS_ID) {
tagId = null;
} else if (tag && tag.targetTagId) {
tagId = tag.targetTagId;
}
@action
onChange(tagId, tag) {
if (tagId === NO_TAG_ID) {
tagId = NONE_TAG;
} else if (tagId === ALL_TAGS_ID) {
tagId = null;
} else if (tag && tag.targetTagId) {
tagId = tag.targetTagId;
}
DiscourseURL.routeToUrl(
getCategoryAndTagUrl(this.currentCategory, !this.noSubcategories, tagId)
);
},
},
});
DiscourseURL.routeToUrl(
getCategoryAndTagUrl(this.currentCategory, !this.noSubcategories, tagId)
);
}
}

View File

@ -1,5 +1,5 @@
import { classNames } from "@ember-decorators/component";
import ComboBoxSelectBoxHeaderComponent from "select-kit/components/combo-box/combo-box-header";
export default ComboBoxSelectBoxHeaderComponent.extend({
classNames: "tag-drop-header",
});
@classNames("tag-drop-header")
export default class TagDropHeader extends ComboBoxSelectBoxHeaderComponent {}

View File

@ -1,32 +1,39 @@
import { computed } from "@ember/object";
import { classNames } from "@ember-decorators/component";
import { makeArray } from "discourse-common/lib/helpers";
import MultiSelectComponent from "select-kit/components/multi-select";
import {
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
import TagsMixin from "select-kit/mixins/tags";
export default MultiSelectComponent.extend(TagsMixin, {
pluginApiIdentifiers: ["tag-group-chooser"],
classNames: ["tag-group-chooser", "tag-chooser"],
selectKitOptions: {
allowAny: false,
filterable: true,
filterPlaceholder: "category.tag_groups_placeholder",
limit: null,
},
@classNames("tag-group-chooser", "tag-chooser")
@selectKitOptions({
allowAny: false,
filterable: true,
filterPlaceholder: "category.tag_groups_placeholder",
limit: null,
})
@pluginApiIdentifiers("tag-group-chooser")
export default class TagGroupChooser extends MultiSelectComponent.extend(
TagsMixin
) {
modifyComponentForRow() {
return "tag-chooser-row";
},
}
value: computed("tagGroups.[]", function () {
@computed("tagGroups.[]")
get value() {
return makeArray(this.tagGroups).uniq();
}),
}
content: computed("tagGroups.[]", function () {
@computed("tagGroups.[]")
get content() {
return makeArray(this.tagGroups)
.uniq()
.map((t) => this.defaultItem(t, t));
}),
}
search(query) {
const data = {
@ -45,7 +52,7 @@ export default MultiSelectComponent.extend(TagsMixin, {
});
}
});
},
}
_transformJson(context, json) {
return json.results
@ -53,5 +60,5 @@ export default MultiSelectComponent.extend(TagsMixin, {
.map((result) => {
return { id: result.name, name: result.name, count: result.count };
});
},
});
}
}

View File

@ -1,11 +1,14 @@
import { classNames } from "@ember-decorators/component";
import NotificationsButtonComponent from "select-kit/components/notifications-button";
import {
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
export default NotificationsButtonComponent.extend({
pluginApiIdentifiers: ["tag-notifications-button"],
classNames: ["tag-notifications-button"],
selectKitOptions: {
showFullTitle: false,
i18nPrefix: "tagging.notifications",
},
});
@classNames("tag-notifications-button")
@selectKitOptions({
showFullTitle: false,
i18nPrefix: "tagging.notifications",
})
@pluginApiIdentifiers("tag-notifications-button")
export default class TagNotificationsButton extends NotificationsButtonComponent {}

View File

@ -1,11 +1,11 @@
import { classNames } from "@ember-decorators/component";
import discourseComputed from "discourse-common/utils/decorators";
import SelectKitRowComponent from "select-kit/components/select-kit/select-kit-row";
export default SelectKitRowComponent.extend({
classNames: ["tag-row"],
@classNames("tag-row")
export default class TagRow extends SelectKitRowComponent {
@discourseComputed("item")
isTag(item) {
return item.id !== "no-tags" && item.id !== "all-tags";
},
});
}
}

View File

@ -1,24 +1,25 @@
import { action } from "@ember/object";
import { attributeBindings, classNames } from "@ember-decorators/component";
import DiscourseURL from "discourse/lib/url";
import { makeArray } from "discourse-common/lib/helpers";
import MiniTagChooser from "select-kit/components/mini-tag-chooser";
import { pluginApiIdentifiers } from "select-kit/components/select-kit";
export default MiniTagChooser.extend({
pluginApiIdentifiers: ["tags-intersection-chooser"],
attributeBindings: ["selectKit.options.categoryId:category-id"],
classNames: ["tags-intersection-chooser"],
mainTag: null,
additionalTags: null,
@attributeBindings("selectKit.options.categoryId:category-id")
@classNames("tags-intersection-chooser")
@pluginApiIdentifiers("tags-intersection-chooser")
export default class TagsIntersectionChooser extends MiniTagChooser {
mainTag = null;
additionalTags = null;
didReceiveAttrs() {
this._super(...arguments);
super.didReceiveAttrs(...arguments);
this.set(
"value",
makeArray(this.mainTag).concat(makeArray(this.additionalTags))
);
},
}
@action
onChange(tags) {
@ -39,5 +40,5 @@ export default MiniTagChooser.extend({
DiscourseURL.routeTo("/tags");
}
}
},
});
}
}

View File

@ -1,29 +1,32 @@
import { classNames } from "@ember-decorators/component";
import ComboBoxComponent from "select-kit/components/combo-box";
import {
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
export default ComboBoxComponent.extend({
pluginApiIdentifiers: ["timezone-input"],
classNames: ["timezone-input"],
selectKitOptions: {
filterable: true,
allowAny: false,
},
@classNames("timezone-input")
@selectKitOptions({
filterable: true,
allowAny: false,
})
@pluginApiIdentifiers("timezone-input")
export default class TimezoneInput extends ComboBoxComponent {
get nameProperty() {
return this.isLocalized ? "name" : null;
},
}
get valueProperty() {
return this.isLocalized ? "value" : null;
},
}
get content() {
return this.isLocalized ? moment.tz.localizedNames() : moment.tz.names();
},
}
get isLocalized() {
return (
moment.locale() !== "en" && typeof moment.tz.localizedNames === "function"
);
},
});
}
}

View File

@ -1,20 +1,23 @@
import { classNames } from "@ember-decorators/component";
import { PLATFORM_KEY_MODIFIER } from "discourse/lib/keyboard-shortcuts";
import { translateModKey } from "discourse/lib/utilities";
import I18n from "discourse-i18n";
import DropdownSelectBoxComponent from "select-kit/components/dropdown-select-box";
import {
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
export default DropdownSelectBoxComponent.extend({
pluginApiIdentifiers: ["toolbar-popup-menu-options"],
classNames: ["toolbar-popup-menu-options"],
selectKitOptions: {
showFullTitle: false,
filterable: false,
autoFilterable: false,
preventHeaderFocus: true,
customStyle: true,
},
@classNames("toolbar-popup-menu-options")
@selectKitOptions({
showFullTitle: false,
filterable: false,
autoFilterable: false,
preventHeaderFocus: true,
customStyle: true,
})
@pluginApiIdentifiers("toolbar-popup-menu-options")
export default class ToolbarPopupMenuOptions extends DropdownSelectBoxComponent {
modifyContent(contents) {
return contents
.map((content) => {
@ -54,5 +57,5 @@ export default DropdownSelectBoxComponent.extend({
}
})
.filter(Boolean);
},
});
}
}

View File

@ -1,3 +1,3 @@
import Component from "@ember/component";
export default Component.extend({});
export default class ToolbarPopupMenuOptionsHeading extends Component {}

View File

@ -1,25 +1,28 @@
import { isEmpty } from "@ember/utils";
import { classNames } from "@ember-decorators/component";
import { searchForTerm } from "discourse/lib/search";
import ComboBoxComponent from "select-kit/components/combo-box";
import {
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
export default ComboBoxComponent.extend({
pluginApiIdentifiers: ["topic-chooser"],
classNames: ["topic-chooser"],
nameProperty: "fancy_title",
labelProperty: "title",
titleProperty: "title",
selectKitOptions: {
clearable: true,
filterable: true,
filterPlaceholder: "choose_topic.title.placeholder",
additionalFilters: "",
},
@classNames("topic-chooser")
@selectKitOptions({
clearable: true,
filterable: true,
filterPlaceholder: "choose_topic.title.placeholder",
additionalFilters: "",
})
@pluginApiIdentifiers("topic-chooser")
export default class TopicChooser extends ComboBoxComponent {
nameProperty = "fancy_title";
labelProperty = "title";
titleProperty = "title";
modifyComponentForRow() {
return "topic-row";
},
}
search(filter) {
if (isEmpty(filter) && isEmpty(this.selectKit.options.additionalFilters)) {
@ -41,5 +44,5 @@ export default ComboBoxComponent.extend({
return results.posts.mapBy("topic");
}
});
},
});
}
}

View File

@ -1,18 +1,21 @@
import { action } from "@ember/object";
import { classNames } from "@ember-decorators/component";
import ComboBoxComponent from "select-kit/components/combo-box";
import {
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
export default ComboBoxComponent.extend({
pluginApiIdentifiers: ["topic-footer-mobile-dropdown"],
classNames: ["topic-footer-mobile-dropdown"],
selectKitOptions: {
none: "topic.controls",
filterable: false,
autoFilterable: false,
},
actions: {
onChange(value, item) {
item.action && item.action();
},
},
});
@classNames("topic-footer-mobile-dropdown")
@selectKitOptions({
none: "topic.controls",
filterable: false,
autoFilterable: false,
})
@pluginApiIdentifiers("topic-footer-mobile-dropdown")
export default class TopicFooterMobileDropdown extends ComboBoxComponent {
@action
onChange(value, item) {
item.action && item.action();
}
}

View File

@ -1,24 +1,26 @@
import Component from "@ember/component";
import { action, computed } from "@ember/object";
import { isEmpty } from "@ember/utils";
import { classNameBindings, classNames } from "@ember-decorators/component";
import { NotificationLevels } from "discourse/lib/notification-levels";
import getURL from "discourse-common/lib/get-url";
import discourseComputed from "discourse-common/utils/decorators";
import I18n from "discourse-i18n";
export default Component.extend({
classNames: ["topic-notifications-button"],
classNameBindings: ["isLoading"],
appendReason: true,
showFullTitle: true,
notificationLevel: null,
topic: null,
showCaret: true,
isLoading: false,
@classNames("topic-notifications-button")
@classNameBindings("isLoading")
export default class TopicNotificationsButton extends Component {
appendReason = true;
showFullTitle = true;
notificationLevel = null;
topic = null;
showCaret = true;
isLoading = false;
icon: computed("isLoading", function () {
@computed("isLoading")
get icon() {
return this.isLoading ? "spinner" : null;
}),
}
@action
changeTopicNotificationLevel(levelId) {
@ -28,7 +30,7 @@ export default Component.extend({
.updateNotifications(levelId)
.finally(() => this.set("isLoading", false));
}
},
}
@discourseComputed(
"topic",
@ -70,7 +72,7 @@ export default Component.extend({
basePath: getURL(""),
});
}
},
}
// The user may have changed their category or tag tracking settings
// since this topic was tracked/watched based on those settings in the
@ -112,5 +114,5 @@ export default Component.extend({
}
return false;
},
});
}
}

View File

@ -1,19 +1,24 @@
import { computed } from "@ember/object";
import { classNames } from "@ember-decorators/component";
import { topicLevels } from "discourse/lib/notification-levels";
import NotificationsButtonComponent from "select-kit/components/notifications-button";
import {
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
export default NotificationsButtonComponent.extend({
pluginApiIdentifiers: ["topic-notifications-options"],
classNames: ["topic-notifications-options"],
content: topicLevels,
@classNames("topic-notifications-options")
@selectKitOptions({
i18nPrefix: "topic.notifications",
i18nPostfix: "i18nPostfix",
showCaret: true,
})
@pluginApiIdentifiers("topic-notifications-options")
export default class TopicNotificationsOptions extends NotificationsButtonComponent {
content = topicLevels;
selectKitOptions: {
i18nPrefix: "topic.notifications",
i18nPostfix: "i18nPostfix",
showCaret: true,
},
i18nPostfix: computed("topic.archetype", function () {
@computed("topic.archetype")
get i18nPostfix() {
return this.topic.archetype === "private_message" ? "_pm" : "";
}),
});
}
}

View File

@ -1,5 +1,5 @@
import { classNames } from "@ember-decorators/component";
import SelectKitRowComponent from "select-kit/components/select-kit/select-kit-row";
export default SelectKitRowComponent.extend({
classNames: ["topic-row"],
});
@classNames("topic-row")
export default class TopicRow extends SelectKitRowComponent {}

View File

@ -1,58 +1,61 @@
import { computed } from "@ember/object";
import { isPresent } from "@ember/utils";
import { classNames } from "@ember-decorators/component";
import userSearch, {
eagerCompleteSearch,
skipSearch,
} from "discourse/lib/user-search";
import { makeArray } from "discourse-common/lib/helpers";
import MultiSelectComponent from "select-kit/components/multi-select";
import {
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
export const CUSTOM_USER_SEARCH_OPTIONS = [];
export default MultiSelectComponent.extend({
pluginApiIdentifiers: ["user-chooser"],
classNames: ["user-chooser"],
valueProperty: "username",
@classNames("user-chooser")
@selectKitOptions({
topicId: undefined,
categoryId: undefined,
includeGroups: false,
allowedUsers: false,
includeMentionableGroups: false,
includeMessageableGroups: false,
allowEmails: false,
groupMembersOf: undefined,
excludeCurrentUser: false,
customSearchOptions: undefined,
excludedUsernames: undefined,
})
@pluginApiIdentifiers("user-chooser")
export default class UserChooser extends MultiSelectComponent {
valueProperty = "username";
modifyComponentForRow() {
return "user-chooser/user-row";
},
}
selectKitOptions: {
topicId: undefined,
categoryId: undefined,
includeGroups: false,
allowedUsers: false,
includeMentionableGroups: false,
includeMessageableGroups: false,
allowEmails: false,
groupMembersOf: undefined,
excludeCurrentUser: false,
customSearchOptions: undefined,
excludedUsernames: undefined,
},
content: computed("value.[]", function () {
@computed("value.[]")
get content() {
return makeArray(this.value).map((x) => this.defaultItem(x, x));
}),
}
excludedUsers: computed(
@computed(
"value",
"currentUser",
"selectKit.options.{excludeCurrentUser,excludedUsernames}",
{
get() {
const options = this.selectKit.options;
let usernames = makeArray(this.value);
"selectKit.options.{excludeCurrentUser,excludedUsernames}"
)
get excludedUsers() {
const options = this.selectKit.options;
let usernames = makeArray(this.value);
if (this.currentUser && options.excludeCurrentUser) {
usernames = usernames.concat([this.currentUser.username]);
}
return usernames.concat(options.excludedUsernames || []);
},
if (this.currentUser && options.excludeCurrentUser) {
usernames = usernames.concat([this.currentUser.username]);
}
),
return usernames.concat(options.excludedUsernames || []);
}
search(filter = "") {
filter = filter || "";
@ -105,5 +108,5 @@ export default MultiSelectComponent.extend({
return result;
}
});
},
});
}
}

View File

@ -1,5 +1,5 @@
import { classNames } from "@ember-decorators/component";
import SelectKitRowComponent from "select-kit/components/select-kit/select-kit-row";
export default SelectKitRowComponent.extend({
classNames: ["user-row"],
});
@classNames("user-row")
export default class UserRow extends SelectKitRowComponent {}

View File

@ -1,28 +1,30 @@
import { computed } from "@ember/object";
import { action, computed } from "@ember/object";
import { service } from "@ember/service";
import { classNames } from "@ember-decorators/component";
import IgnoreDurationModal from "discourse/components/modal/ignore-duration-with-username";
import { popupAjaxError } from "discourse/lib/ajax-error";
import I18n from "discourse-i18n";
import DropdownSelectBox from "select-kit/components/dropdown-select-box";
import { selectKitOptions } from "select-kit/components/select-kit";
export default DropdownSelectBox.extend({
modal: service(),
@classNames("user-notifications", "user-notifications-dropdown")
@selectKitOptions({
headerIcon: "userNotificationIcon",
showCaret: true,
})
export default class UserNotificationsDropdown extends DropdownSelectBox {
@service modal;
classNames: ["user-notifications", "user-notifications-dropdown"],
selectKitOptions: {
headerIcon: "userNotificationIcon",
showCaret: true,
},
userNotificationIcon: computed("mainCollection.[]", "value", function () {
@computed("mainCollection.[]", "value")
get userNotificationIcon() {
return (
this.mainCollection &&
this.mainCollection.find((row) => row.id === this.value).icon
);
}),
}
content: computed(function () {
@computed
get content() {
const content = [];
content.push({
@ -49,14 +51,16 @@ export default DropdownSelectBox.extend({
}
return content;
}),
}
changeToNormal() {
this.updateNotificationLevel({ level: "normal" }).catch(popupAjaxError);
},
}
changeToMuted() {
this.updateNotificationLevel({ level: "mute" }).catch(popupAjaxError);
},
}
changeToIgnored() {
this.modal.show(IgnoreDurationModal, {
model: {
@ -64,15 +68,14 @@ export default DropdownSelectBox.extend({
enableSelection: false,
},
});
},
}
actions: {
onChange(level) {
this[level]();
@action
onChange(level) {
this[level]();
// hack but model.ignored/muted is not
// getting updated after updateNotificationLevel
this.set("value", level);
},
},
});
// hack but model.ignored/muted is not
// getting updated after updateNotificationLevel
this.set("value", level);
}
}

View File

@ -1,20 +1,23 @@
import { computed } from "@ember/object";
import { classNames } from "@ember-decorators/component";
import { makeArray } from "discourse-common/lib/helpers";
import MultiSelectComponent from "select-kit/components/multi-select";
import {
pluginApiIdentifiers,
selectKitOptions,
} from "select-kit/components/select-kit";
export default MultiSelectComponent.extend({
pluginApiIdentifiers: ["watched-words"],
classNames: ["watched-word-input-field"],
selectKitOptions: {
autoInsertNoneItem: false,
fullWidthOnMobile: true,
allowAny: true,
none: "admin.watched_words.form.words_or_phrases",
},
@classNames("watched-word-input-field")
@selectKitOptions({
autoInsertNoneItem: false,
fullWidthOnMobile: true,
allowAny: true,
none: "admin.watched_words.form.words_or_phrases",
})
@pluginApiIdentifiers("watched-words")
export default class WatchedWords extends MultiSelectComponent {
@computed("value.[]")
get content() {
return makeArray(this.value).map((x) => this.defaultItem(x, x));
},
});
}
}