FIX: improves category/tag drops header shortcuts (#6610)

- wont appear when filtering
- can now be selected with keyboard
- fix bugs on click with safari/firefox
This commit is contained in:
Joffrey JAFFEUX 2018-11-15 15:21:40 +01:00 committed by GitHub
parent fc95f772bc
commit 9911a41f4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 145 additions and 83 deletions

View File

@ -10,7 +10,7 @@ export default ComboBoxComponent.extend({
classNameBindings: ["categoryStyle"], classNameBindings: ["categoryStyle"],
classNames: "category-drop", classNames: "category-drop",
verticalOffset: 3, verticalOffset: 3,
content: Ember.computed.alias("categories"), content: Ember.computed.alias("categoriesWithShortcuts"),
rowComponent: "category-row", rowComponent: "category-row",
headerComponent: "category-drop/category-drop-header", headerComponent: "category-drop/category-drop-header",
allowAutoSelectFirst: false, allowAutoSelectFirst: false,
@ -24,6 +24,34 @@ export default ComboBoxComponent.extend({
subCategory: false, subCategory: false,
isAsync: Ember.computed.not("subCategory"), isAsync: Ember.computed.not("subCategory"),
@computed("categories", "hasSelection", "subCategory", "noSubcategories")
categoriesWithShortcuts(
categories,
hasSelection,
subCategory,
noSubcategories
) {
const shortcuts = [];
if (hasSelection || (noSubcategories && subCategory)) {
shortcuts.push({
name: this.get("allCategoriesLabel"),
__sk_row_type: "noopRow",
id: "all-categories"
});
}
if (subCategory && (hasSelection || !noSubcategories)) {
shortcuts.push({
name: this.get("noCategoriesLabel"),
__sk_row_type: "noopRow",
id: "no-categories"
});
}
return shortcuts.concat(categories);
},
init() { init() {
this._super(); this._super();
@ -54,45 +82,6 @@ export default ComboBoxComponent.extend({
); );
}, },
@computed(
"allCategoriesUrl",
"allCategoriesLabel",
"noCategoriesUrl",
"noCategoriesLabel"
)
collectionHeader(
allCategoriesUrl,
allCategoriesLabel,
noCategoriesUrl,
noCategoriesLabel
) {
let shortcuts = "";
if (
this.get("hasSelection") ||
(this.get("noSubcategories") && this.get("subCategory"))
) {
shortcuts += `
<a href="${allCategoriesUrl}" class="category-filter">
${allCategoriesLabel}
</a>
`;
}
if (
this.get("subCategory") &&
(this.get("hasSelection") || !this.get("noSubcategories"))
) {
shortcuts += `
<a href="${noCategoriesUrl}" class="category-filter">
${noCategoriesLabel}
</a>
`;
}
return shortcuts.htmlSafe();
},
computeHeaderContent() { computeHeaderContent() {
let content = this._super(); let content = this._super();
@ -131,19 +120,28 @@ export default ComboBoxComponent.extend({
@computed("parentCategory.url", "subCategory") @computed("parentCategory.url", "subCategory")
allCategoriesUrl(parentCategoryUrl, subCategory) { allCategoriesUrl(parentCategoryUrl, subCategory) {
return subCategory ? parentCategoryUrl || "/" : "/"; return Discourse.getURL(subCategory ? parentCategoryUrl || "/" : "/");
}, },
@computed("parentCategory.url") @computed("parentCategory.url")
noCategoriesUrl(parentCategoryUrl) { noCategoriesUrl(parentCategoryUrl) {
return `${parentCategoryUrl}/none`; return Discourse.getURL(`${parentCategoryUrl}/none`);
}, },
actions: { actions: {
onSelect(categoryId) { onSelect(categoryId) {
const category = Category.findById(parseInt(categoryId, 10)); let categoryURL;
const categoryURL =
Discourse.getURL("/c/") + Discourse.Category.slugFor(category); if (categoryId === "all-categories") {
categoryURL = Discourse.getURL(this.get("allCategoriesUrl"));
} else if (categoryId === "no-categories") {
categoryURL = Discourse.getURL(this.get("noCategoriesUrl"));
} else {
const category = Category.findById(parseInt(categoryId, 10));
const slug = Discourse.Category.slugFor(category);
categoryURL = Discourse.getURL("/c/") + slug;
}
DiscourseURL.routeTo(categoryURL); DiscourseURL.routeTo(categoryURL);
}, },

View File

@ -264,6 +264,11 @@ export default SelectKitComponent.extend({
return; return;
} }
if (computedContentItem.__sk_row_type === "noopRow") {
this._boundaryActionHandler("onSelect", computedContentItem.value);
return;
}
if (computedContentItem.__sk_row_type === "createRow") { if (computedContentItem.__sk_row_type === "createRow") {
if ( if (
!this.get("computedValues").includes(computedContentItem.value) && !this.get("computedValues").includes(computedContentItem.value) &&

View File

@ -213,7 +213,9 @@ export default Ember.Component.extend(
name: name || this._nameForContent(contentItem), name: name || this._nameForContent(contentItem),
locked: false, locked: false,
created: options.created || false, created: options.created || false,
__sk_row_type: options.created ? "createRow" : null, __sk_row_type: options.created
? "createRow"
: contentItem.__sk_row_type,
originalContent originalContent
}; };

View File

@ -210,6 +210,11 @@ export default SelectKitComponent.extend({
}, },
select(computedContentItem) { select(computedContentItem) {
if (computedContentItem.__sk_row_type === "noopRow") {
this._boundaryActionHandler("onSelect", computedContentItem.value);
return;
}
if (this.get("hasSelection")) { if (this.get("hasSelection")) {
this.deselect(this.get("selection.value")); this.deselect(this.get("selection.value"));
} }

View File

@ -67,9 +67,9 @@ export default ComboBoxComponent.extend(TagsMixin, {
@computed("firstCategory", "secondCategory") @computed("firstCategory", "secondCategory")
allTagsUrl() { allTagsUrl() {
if (this.get("currentCategory")) { if (this.get("currentCategory")) {
return this.get("currentCategory.url") + "?allTags=1"; return Discourse.getURL(this.get("currentCategory.url") + "?allTags=1");
} else { } else {
return "/"; return Discourse.getURL("/");
} }
}, },
@ -79,30 +79,7 @@ export default ComboBoxComponent.extend(TagsMixin, {
if (this.get("currentCategory")) { if (this.get("currentCategory")) {
url += this.get("currentCategory.url"); url += this.get("currentCategory.url");
} }
return `${url}/none`; return Discourse.getURL(`${url}/none`);
},
@computed("allTagsUrl", "allTagsLabel", "noTagsUrl", "noTagsLabel")
collectionHeader(allTagsUrl, allTagsLabel, noTagsUrl, noTagsLabel) {
let content = "";
if (this.get("tagId") !== "none") {
content += `
<a href="${noTagsUrl}" class="tag-filter">
${noTagsLabel}
</a>
`;
}
if (this.get("tagId")) {
content += `
<a href="${allTagsUrl}" class="tag-filter">
${allTagsLabel}
</a>
`;
}
return content;
}, },
@computed("tag") @computed("tag")
@ -115,12 +92,35 @@ export default ComboBoxComponent.extend(TagsMixin, {
return I18n.t("tagging.selector_no_tags"); return I18n.t("tagging.selector_no_tags");
}, },
@computed("site.top_tags") @computed("tagId", "allTagsLabel", "noTagsLabel")
content(topTags) { shortcuts(tagId, allTagsLabel, noTagsLabel) {
const shortcuts = [];
if (tagId !== "none") {
shortcuts.push({
name: noTagsLabel,
__sk_row_type: "noopRow",
id: "no-tags"
});
}
if (tagId) {
shortcuts.push({
name: allTagsLabel,
__sk_row_type: "noopRow",
id: "all-tags"
});
}
return shortcuts;
},
@computed("site.top_tags", "shortcuts")
content(topTags, shortcuts) {
if (this.siteSettings.tags_sort_alphabetically && topTags) { if (this.siteSettings.tags_sort_alphabetically && topTags) {
return topTags.sort(); return shortcuts.concat(topTags.sort());
} else { } else {
return topTags; return shortcuts.concat(topTags);
} }
}, },
@ -141,11 +141,20 @@ export default ComboBoxComponent.extend(TagsMixin, {
actions: { actions: {
onSelect(tagId) { onSelect(tagId) {
let url = "/tags"; let url;
if (this.get("currentCategory")) {
url += this.get("currentCategory.url"); if (tagId === "all-tags") {
url = Discourse.getURL(this.get("allTagsUrl"));
} else if (tagId === "no-tags") {
url = Discourse.getURL(this.get("noTagsUrl"));
} else {
url = "/tags";
if (this.get("currentCategory")) {
url += this.get("currentCategory.url");
}
url = Discourse.getURL(`${url}/${tagId.toLowerCase()}`);
} }
url = `${url}/${tagId.toLowerCase()}`;
DiscourseURL.routeTo(url); DiscourseURL.routeTo(url);
}, },

View File

@ -24,6 +24,7 @@
@import "common/select-kit/pinned-button"; @import "common/select-kit/pinned-button";
@import "common/select-kit/select-kit"; @import "common/select-kit/select-kit";
@import "common/select-kit/tag-chooser"; @import "common/select-kit/tag-chooser";
@import "common/select-kit/tag-drop";
@import "common/select-kit/toolbar-popup-menu-options"; @import "common/select-kit/toolbar-popup-menu-options";
@import "common/select-kit/topic-notifications-button"; @import "common/select-kit/topic-notifications-button";
@import "common/components/*"; @import "common/components/*";

View File

@ -42,6 +42,12 @@
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
&[data-value="all-categories"],
&[data-value="no-categories"] {
color: $tertiary;
font-weight: 700;
}
.category-desc { .category-desc {
font-weight: normal; font-weight: normal;
color: $primary-medium; color: $primary-medium;

View File

@ -0,0 +1,13 @@
.select-kit {
&.combo-box {
&.tag-drop {
.select-kit-row {
&[data-value="all-tags"],
&[data-value="no-tags"] {
color: $tertiary;
font-weight: 700;
}
}
}
}
}

View File

@ -887,3 +887,26 @@ componentTest("onDeselect", {
); );
} }
}); });
componentTest("noopRow", {
template: "{{single-select value=value content=content}}",
beforeEach() {
this.set("value", "blue");
this.set("content", [
{ id: "red", name: "Red", __sk_row_type: "noopRow" },
"blue",
"green"
]);
},
async test(assert) {
await this.get("subject").expand();
await this.get("subject").selectRowByValue("red");
assert.equal(this.get("value"), "blue", "it doesnt change the value");
await this.get("subject").expand();
await this.get("subject").selectRowByValue("green");
assert.equal(this.get("value"), "green");
}
});

View File

@ -42,7 +42,7 @@ componentTest("default", {
assert.equal( assert.equal(
this.get("subject") this.get("subject")
.rowByIndex(0) .rowByIndex(1)
.name(), .name(),
"jeff", "jeff",
"it has the correct tag" "it has the correct tag"
@ -50,7 +50,7 @@ componentTest("default", {
assert.equal( assert.equal(
this.get("subject") this.get("subject")
.rowByIndex(1) .rowByIndex(2)
.name(), .name(),
"neil", "neil",
"it has the correct tag" "it has the correct tag"
@ -68,7 +68,7 @@ componentTest("default", {
await this.get("subject").fillInFilter(""); await this.get("subject").fillInFilter("");
assert.equal( assert.equal(
this.get("subject") this.get("subject")
.rowByIndex(0) .rowByIndex(1)
.name(), .name(),
"jeff", "jeff",
"it returns top tags for an empty search" "it returns top tags for an empty search"