FEATURE: add expandable muted categories ui to `/categories` page. (#10303)

Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
This commit is contained in:
Vinoth Kannan 2020-07-30 23:32:51 +05:30 committed by GitHub
parent f90e02162b
commit 6a1746a0c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 392 additions and 173 deletions

View File

@ -1,7 +1,54 @@
import Component from "@ember/component";
import discourseComputed from "discourse-common/utils/decorators";
import { equal } from "@ember/object/computed";
import { action } from "@ember/object";
export default Component.extend({
tagName: "",
noCategoryStyle: equal("siteSettings.category_style", "none")
showMuted: false,
noCategoryStyle: equal("siteSettings.category_style", "none"),
@discourseComputed("showMutedCategories", "filteredCategories.length")
mutedToggleIcon(showMutedCategories, filteredCategoriesLength) {
if (filteredCategoriesLength === 0) {
return;
}
if (showMutedCategories) return "minus";
return "plus";
},
@discourseComputed("showMuted", "filteredCategories.length")
showMutedCategories(showMuted, filteredCategoriesLength) {
return showMuted || filteredCategoriesLength === 0;
},
@discourseComputed("categories", "categories.length")
filteredCategories(categories, categoriesLength) {
if (!categories || categoriesLength === 0) {
return [];
}
return categories.filter(cat => !cat.isHidden);
},
@discourseComputed("categories", "categories.length")
mutedCategories(categories, categoriesLength) {
if (!categories || categoriesLength === 0) {
return [];
}
// hide in single category pages
if (categories.firstObject.parent_category_id) {
return [];
}
return categories.filterBy("hasMuted");
},
@action
toggleShowMuted() {
this.toggleProperty("showMuted");
}
});

View File

@ -0,0 +1,29 @@
import Component from "@ember/component";
import discourseComputed from "discourse-common/utils/decorators";
const LIST_TYPE = {
NORMAL: "normal",
MUTED: "muted"
};
export default Component.extend({
tagName: "",
category: null,
listType: LIST_TYPE.NORMAL,
@discourseComputed("category.isHidden", "category.hasMuted", "listType")
isHidden(isHiddenCategory, hasMuted, listType) {
return (
(isHiddenCategory && listType === LIST_TYPE.NORMAL) ||
(!hasMuted && listType === LIST_TYPE.MUTED)
);
},
@discourseComputed("category.isMuted", "listType")
isMuted(isMutedCategory, listType) {
return (
(isMutedCategory && listType === LIST_TYPE.NORMAL) ||
(!isMutedCategory && listType === LIST_TYPE.MUTED)
);
}
});

View File

@ -0,0 +1,3 @@
import CategoryListItem from "discourse/components/category-list-item";
export default CategoryListItem.extend({});

View File

@ -0,0 +1,3 @@
import CategoryListItem from "discourse/components/category-list-item";
export default CategoryListItem.extend({});

View File

@ -0,0 +1,3 @@
import CategoryListItem from "discourse/components/category-list-item";
export default CategoryListItem.extend({});

View File

@ -87,6 +87,36 @@ const Category = RestModel.extend({
return notificationLevel === NotificationLevels.MUTED;
},
@discourseComputed("isMuted", "subcategories")
isHidden(isMuted, subcategories) {
if (!isMuted) {
return false;
} else if (!subcategories) {
return true;
}
if (subcategories.some(cat => !cat.isHidden)) {
return false;
}
return true;
},
@discourseComputed("isMuted", "subcategories")
hasMuted(isMuted, subcategories) {
if (isMuted) {
return true;
} else if (!subcategories) {
return false;
}
if (subcategories.some(cat => cat.hasMuted)) {
return true;
}
return false;
},
@discourseComputed("notification_level")
notificationLevelString(notificationLevel) {
// Get the key from the value

View File

@ -1,91 +1,49 @@
{{#if categories}}
<table class="category-list {{if showTopics "with-topics"}}">
<thead>
<tr>
<th class="category"><span aria-role="heading" aria-level="2" id="categories-only-category">{{i18n "categories.category"}}</span></th>
<th class="topics">{{i18n "categories.topics"}}</th>
{{#if showTopics}}
<th class="latest">{{i18n "categories.latest"}}</th>
{{/if}}
</tr>
</thead>
<tbody aria-labelledby="categories-only-category">
{{#each categories as |c|}}
{{plugin-outlet name="category-list-above-each-category" connectorTagName="" tagName="" args=(hash category=c)}}
<tr data-category-id={{c.id}} data-notification-level={{c.notificationLevelString}} class="{{if c.description_excerpt "has-description" "no-description"}} {{if c.uploaded_logo.url "has-logo" "no-logo"}}">
<td class="category {{if c.isMuted "muted"}} {{if noCategoryStyle "no-category-style"}}" style={{unless noCategoryStyle (border-color c.color)}}>
{{category-title-link category=c}}
{{#unless c.isMuted}}
{{#if c.description_excerpt}}
<div class="category-description">
{{dir-span c.description_excerpt}}
</div>
{{/if}}
{{#if c.isGrandParent}}
<table class="category-list subcategories-with-subcategories">
<tbody>
{{#each c.subcategories as |subcategory|}}
<tr data-category-id={{subcategory.id}} data-notification-level={{subcategory.notificationLevelString}} class="{{if subcategory.description_excerpt "has-description" "no-description"}} {{if subcategory.uploaded_logo.url "has-logo" "no-logo"}}">
<td class="category" style={{border-color subcategory.color}}>
{{category-title-link tagName="h4" category=subcategory}}
{{#if subcategory.description_excerpt}}
<div class="category-description subcategory-description">
{{dir-span subcategory.description_excerpt}}
</div>
{{/if}}
{{#if subcategory.subcategories}}
<div class="subcategories">
{{#each subcategory.subcategories as |subsubcategory|}}
{{#unless subsubcategory.isMuted}}
<span class="subcategory">
{{category-title-before category=subsubcategory}}
{{category-link subsubcategory hideParent="true"}}
</span>
{{/unless}}
{{/each}}
</div>
{{else}}
{{#if subcategory.description_excerpt}}
<div class="category-description subcategory-description">
{{dir-span subcategory.description_excerpt}}
</div>
{{/if}}
{{/if}}
</td>
</tr>
{{/each}}
</tbody>
</table>
{{else if c.subcategories}}
<div class="subcategories">
{{#each c.subcategories as |subcategory|}}
{{#unless subcategory.isMuted}}
<span class="subcategory">
{{category-title-before category=subcategory}}
{{category-link subcategory hideParent="true"}}
{{category-unread category=subcategory}}
</span>
{{/unless}}
{{/each}}
</div>
{{/if}}
{{/unless}}
</td>
<td class="topics">
<div title={{c.statTitle}}>{{html-safe c.stat}}</div>
{{category-unread category=c tagName="div" class="unread-new"}}
</td>
{{#unless c.isMuted}}
{{#if showTopics}}
<td class="latest">
{{#each c.featuredTopics as |t|}}
{{featured-topic topic=t latestTopicOnly=latestTopicOnly}}
{{/each}}
</td>
{{/if}}
{{/unless}}
{{#if filteredCategories}}
<table class="category-list {{if showTopics "with-topics"}}">
<thead>
<tr>
<th class="category"><span aria-role="heading" aria-level="2" id="categories-only-category">{{i18n "categories.category"}}</span></th>
<th class="topics">{{i18n "categories.topics"}}</th>
{{#if showTopics}}
<th class="latest">{{i18n "categories.latest"}}</th>
{{/if}}
</tr>
{{/each}}
</tbody>
</table>
</thead>
<tbody aria-labelledby="categories-only-category">
{{#each categories as |category|}}
{{parent-category-row category=category showTopics=showTopics}}
{{/each}}
</tbody>
</table>
{{/if}}
{{#if mutedCategories}}
<div class="muted-categories">
<a href class="muted-categories-link" {{action "toggleShowMuted"}}>
<h3 class="muted-categories-heading">{{i18n "categories.muted"}}</h3>
{{#if mutedToggleIcon}}
{{d-icon mutedToggleIcon}}
{{/if}}
</a>
{{#if showMutedCategories}}
<table class="category-list {{if showTopics "with-topics"}}">
<thead>
<tr>
<th class="category"><span aria-role="heading" aria-level="2" id="categories-only-category">{{i18n "categories.category"}}</span></th>
<th class="topics">{{i18n "categories.topics"}}</th>
{{#if showTopics}}
<th class="latest">{{i18n "categories.latest"}}</th>
{{/if}}
</tr>
</thead>
<tbody aria-labelledby="categories-only-category">
{{#each categories as |category|}}
{{parent-category-row category=category showTopics=showTopics listType="muted"}}
{{/each}}
</tbody>
</table>
{{/if}}
</div>
{{/if}}
{{/if}}

View File

@ -0,0 +1,41 @@
{{#unless isHidden}}
{{plugin-outlet name="category-list-above-each-category" connectorTagName="" tagName="" args=(hash category=category)}}
<tr data-category-id={{category.id}} data-notification-level={{category.notificationLevelString}} class="{{if category.description_excerpt "has-description" "no-description"}} {{if category.uploaded_logo.url "has-logo" "no-logo"}}">
<td class="category {{if isMuted "muted"}} {{if noCategoryStyle "no-category-style"}}" style={{unless noCategoryStyle (border-color category.color)}}>
{{category-title-link category=category}}
{{#if category.description_excerpt}}
<div class="category-description">
{{dir-span category.description_excerpt}}
</div>
{{/if}}
{{#if category.isGrandParent}}
<table class="category-list subcategories-with-subcategories">
<tbody>
{{#each category.subcategories as |subcategory|}}
{{sub-category-row category=subcategory listType=listType}}
{{/each}}
</tbody>
</table>
{{else if category.subcategories}}
<div class="subcategories">
{{#each category.subcategories as |subcategory|}}
{{sub-category-item category=subcategory listType=listType}}
{{/each}}
</div>
{{/if}}
</td>
<td class="topics">
<div title={{category.statTitle}}>{{html-safe category.stat}}</div>
{{category-unread category=category tagName="div" class="unread-new"}}
</td>
{{#unless isMuted}}
{{#if showTopics}}
<td class="latest">
{{#each category.featuredTopics as |t|}}
{{featured-topic topic=t latestTopicOnly=latestTopicOnly}}
{{/each}}
</td>
{{/if}}
{{/unless}}
</tr>
{{/unless}}

View File

@ -0,0 +1,9 @@
{{#unless isMuted}}
<span class="subcategory">
{{category-title-before category=category}}
{{category-link category hideParent="true"}}
{{#unless hideUnread}}
{{category-unread category=category}}
{{/unless}}
</span>
{{/unless}}

View File

@ -0,0 +1,25 @@
{{#unless isHidden}}
<tr data-category-id={{category.id}} data-notification-level={{category.notificationLevelString}} class="{{if category.description_excerpt "has-description" "no-description"}} {{if category.uploaded_logo.url "has-logo" "no-logo"}}">
<td class="category {{if isMuted "muted"}}" style={{border-color category.color}}>
{{category-title-link tagName="h4" category=category}}
{{#if category.description_excerpt}}
<div class="category-description subcategory-description">
{{dir-span category.description_excerpt}}
</div>
{{/if}}
{{#if category.subcategories}}
<div class="subcategories">
{{#each category.subcategories as |subsubcategory|}}
{{sub-category-item category=subsubcategory hideUnread="true" listType=listType}}
{{/each}}
</div>
{{else}}
{{#if category.description_excerpt}}
<div class="category-description subcategory-description">
{{dir-span category.description_excerpt}}
</div>
{{/if}}
{{/if}}
</td>
</tr>
{{/unless}}

View File

@ -1,82 +1,27 @@
{{#if categories}}
<div class="category-list {{if showTopics "with-topics"}}">
{{#each categories as |c|}}
{{plugin-outlet name="category-list-above-each-category" connectorTagName="" tagName="" args=(hash category=c)}}
<div data-category-id={{c.id}} data-notification-level={{c.notificationLevelString}} style={{border-color c.color}} class="category-list-item category {{if c.isMuted "muted"}}">
<table class="topic-list">
<tbody>
<tr>
<th class="main-link">
{{category-title-link category=c}}
</th>
</tr>
{{#unless c.isMuted}}
{{#if c.description_excerpt}}
<tr class="category-description">
<td colspan="3">
{{html-safe c.description_excerpt}}
</td>
</tr>
{{/if}}
{{#if showTopics}}
{{#each c.topics as |t|}}
{{mobile-category-topic topic=t}}
{{/each}}
{{/if}}
{{#if c.isGrandParent}}
{{#each c.subcategories as |subcategory|}}
<tr data-category-id={{c.id}} style={{border-color subcategory.color}} class="subcategory-list-item category">
<td>
{{category-title-link tagName="h4" category=subcategory}}
<div class="subcategories-list">
{{#if subcategory.subcategories}}
<div class="subcategories">
{{#each subcategory.subcategories as |subsubcategory|}}
{{#unless subsubcategory.isMuted}}
{{category-link subsubcategory}}
{{/unless}}
{{/each}}
</div>
{{/if}}
</div>
</td>
</tr>
{{/each}}
{{else if c.subcategories}}
<tr class="subcategories-list">
<td>
<div class="subcategories">
{{#each c.subcategories as |subcategory|}}
{{#unless subcategory.isMuted}}
{{category-link subcategory}}
{{/unless}}
{{/each}}
</div>
</td>
</tr>
{{/if}}
{{/unless}}
</tbody>
</table>
<footer class="clearfix">
<figure title={{i18n "all_time_desc"}}>
{{number c.topics_all_time}}
<figcaption>{{i18n "all_time"}}</figcaption>
</figure>
{{#if c.pickMonth}}
<figure title={{i18n "month_desc"}}>
{{number c.topics_month}}
<figcaption>/ {{i18n "month"}}</figcaption>
</figure>
{{/if}}
{{#if c.pickWeek}}
<figure title={{i18n "week_desc"}}>
{{number c.topics_week}}
<figcaption>/ {{i18n "week"}}</figcaption>
</figure>
{{/if}}
</footer>
</div>
{{/each}}
</div>
{{#if filteredCategories}}
<div class="category-list {{if showTopics "with-topics"}}">
{{#each filteredCategories as |c|}}
{{parent-category-row category=c showTopics=showTopics}}
{{/each}}
</div>
{{/if}}
{{#if mutedCategories}}
<div class="muted-categories">
<a href class="muted-categories-link" {{action "toggleShowMuted"}}>
<h3 class="muted-categories-heading">{{i18n "categories.muted"}}</h3>
{{#if mutedToggleIcon}}
{{d-icon mutedToggleIcon}}
{{/if}}
</a>
{{#if showMutedCategories}}
<div class="category-list {{if showTopics "with-topics"}}">
{{#each mutedCategories as |c|}}
{{parent-category-row category=c showTopics=showTopics listType="muted"}}
{{/each}}
</div>
{{/if}}
</div>
{{/if}}
{{/if}}

View File

@ -0,0 +1,61 @@
{{#unless isHidden}}
{{plugin-outlet name="category-list-above-each-category" connectorTagName="" tagName="" args=(hash category=category)}}
<div data-category-id={{category.id}} data-notification-level={{category.notificationLevelString}} style={{border-color category.color}} class="category-list-item category {{if isMuted "muted"}}">
<table class="topic-list">
<tbody>
<tr>
<th class="main-link">
{{category-title-link category=category}}
</th>
</tr>
{{#if category.description_excerpt}}
<tr class="category-description">
<td colspan="3">
{{html-safe category.description_excerpt}}
</td>
</tr>
{{/if}}
{{#unless isMuted}}
{{#if showTopics}}
{{#each category.topics as |t|}}
{{mobile-category-topic topic=t}}
{{/each}}
{{/if}}
{{/unless}}
{{#if category.isGrandParent}}
{{#each category.subcategories as |subcategory|}}
{{sub-category-row category=subcategory listType=listType}}
{{/each}}
{{else if category.subcategories}}
<tr class="subcategories-list">
<td>
<div class="subcategories">
{{#each category.subcategories as |subcategory|}}
{{sub-category-item category=subcategory listType=listType}}
{{/each}}
</div>
</td>
</tr>
{{/if}}
</tbody>
</table>
<footer class="clearfix">
<figure title={{i18n "all_time_desc"}}>
{{number category.topics_all_time}}
<figcaption>{{i18n "all_time"}}</figcaption>
</figure>
{{#if category.pickMonth}}
<figure title={{i18n "month_desc"}}>
{{number category.topics_month}}
<figcaption>/ {{i18n "month"}}</figcaption>
</figure>
{{/if}}
{{#if category.pickWeek}}
<figure title={{i18n "week_desc"}}>
{{number category.topics_week}}
<figcaption>/ {{i18n "week"}}</figcaption>
</figure>
{{/if}}
</footer>
</div>
{{/unless}}

View File

@ -0,0 +1,3 @@
{{#unless isMuted}}
{{category-link category}}
{{/unless}}

View File

@ -0,0 +1,16 @@
{{#unless isHidden}}
<tr data-category-id={{category.id}} style={{border-color category.color}} class="subcategory-list-item category {{if isMuted "muted"}}">
<td>
{{category-title-link tagName="h4" category=category}}
<div class="subcategories-list">
{{#if category.subcategories}}
<div class="subcategories">
{{#each category.subcategories as |subcategory|}}
{{sub-category-item category=subcategory listType=listType}}
{{/each}}
</div>
{{/if}}
</div>
</td>
</tr>
{{/unless}}

View File

@ -317,11 +317,15 @@
}
}
.categories-list .category.muted {
font-size: $font-down-1;
h3,
.category-name {
.category-list .category.muted {
> h3 a.category-title-link,
> h4 a.category-title-link {
color: $primary-medium;
font-size: $font-down-1;
}
> .category-description,
tr.category-description {
display: none;
}
}
@ -340,3 +344,35 @@
.category-box.no-category-boxes-style {
border-left-width: 2px;
}
.muted-categories-link {
border: 1px solid $primary-low;
display: flex;
justify-content: space-between;
padding: 0.75em;
border-left-width: 6px;
border-right: none 0;
margin: 0 0 1em -3px;
.d-icon {
color: $primary-medium;
margin-top: 0.25em;
}
}
.muted-categories-heading {
color: $primary-medium;
margin: 0;
}
.anon .muted-categories-link {
display: none;
}
.navigation-categories .category-list {
margin-bottom: 3em;
.category-list {
margin-bottom: 0;
}
}

View File

@ -542,3 +542,12 @@ td .main-link {
.category-list.with-topics .category-list-item .category-description {
display: none;
}
.category-list .category.muted a.category-title-link {
color: $primary-medium;
font-size: $font-down-1;
}
.muted-categories-link {
margin-left: 0;
}

View File

@ -819,6 +819,7 @@ en:
latest_by: "latest by"
toggle_ordering: "toggle ordering control"
subcategories: "Subcategories"
muted: "Muted categories"
topic_sentence:
one: "%{count} topic"
other: "%{count} topics"