UX: show an enveloppe icon when a badge is used in messages
- the badge count now includes messages - only show the message badges to admins
This commit is contained in:
parent
1e132b4599
commit
e9abdaebbe
|
@ -1,22 +1,23 @@
|
||||||
|
import computed from "ember-addons/ember-computed-decorators";
|
||||||
|
|
||||||
export default Ember.Component.extend({
|
export default Ember.Component.extend({
|
||||||
classNameBindings: [':tag-list', 'categoryClass'],
|
classNameBindings: [':tag-list', 'categoryClass'],
|
||||||
|
|
||||||
isPrivateMessage: false,
|
isPrivateMessage: false,
|
||||||
sortedTags: Ember.computed.sort('tags', 'sortProperties'),
|
sortedTags: Ember.computed.sort('tags', 'sortProperties'),
|
||||||
|
|
||||||
title: function() {
|
@computed("titleKey")
|
||||||
if (this.get('titleKey')) { return I18n.t(this.get('titleKey')); }
|
title(titleKey) {
|
||||||
}.property('titleKey'),
|
return titleKey && I18n.t(titleKey);
|
||||||
|
},
|
||||||
|
|
||||||
category: function() {
|
@computed("categoryId")
|
||||||
if (this.get('categoryId')) {
|
category(categoryId) {
|
||||||
return Discourse.Category.findById(this.get('categoryId'));
|
return categoryId && Discourse.Category.findById(categoryId);
|
||||||
}
|
},
|
||||||
}.property('categoryId'),
|
|
||||||
|
|
||||||
categoryClass: function() {
|
@computed("category.fullSlug")
|
||||||
if (this.get('category')) {
|
categoryClass(slug) {
|
||||||
return "tag-list-" + this.get('category.fullSlug');
|
return slug && `tag-list-${slug}`;
|
||||||
}
|
}
|
||||||
}.property('category')
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import computed from 'ember-addons/ember-computed-decorators';
|
import computed from 'ember-addons/ember-computed-decorators';
|
||||||
|
|
||||||
export default Ember.Controller.extend({
|
export default Ember.Controller.extend({
|
||||||
sortProperties: ['count:desc', 'id'],
|
sortProperties: ['totalCount:desc', 'id'],
|
||||||
sortedByCount: true,
|
sortedByCount: true,
|
||||||
sortedByName: false,
|
sortedByName: false,
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ export default Ember.Controller.extend({
|
||||||
actions: {
|
actions: {
|
||||||
sortByCount() {
|
sortByCount() {
|
||||||
this.setProperties({
|
this.setProperties({
|
||||||
sortProperties: ['count:desc', 'id'],
|
sortProperties: ['totalCount:desc', 'id'],
|
||||||
sortedByCount: true,
|
sortedByCount: true,
|
||||||
sortedByName: false
|
sortedByName: false
|
||||||
});
|
});
|
||||||
|
|
|
@ -37,7 +37,6 @@ CategoryList.reopenClass({
|
||||||
c.topics = c.topics.map(t => Discourse.Topic.create(t));
|
c.topics = c.topics.map(t => Discourse.Topic.create(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
switch(statPeriod) {
|
switch(statPeriod) {
|
||||||
case "week":
|
case "week":
|
||||||
case "month":
|
case "month":
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import RestModel from "discourse/models/rest";
|
||||||
|
import computed from "ember-addons/ember-computed-decorators";
|
||||||
|
|
||||||
|
export default RestModel.extend({
|
||||||
|
@computed("count", "pm_count")
|
||||||
|
totalCount(count, pmCount) {
|
||||||
|
return count + pmCount;
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,6 +1,22 @@
|
||||||
|
import Tag from "discourse/models/tag";
|
||||||
|
|
||||||
export default Discourse.Route.extend({
|
export default Discourse.Route.extend({
|
||||||
model() {
|
model() {
|
||||||
return this.store.findAll('tag');
|
return this.store.findAll("tag").then(result => {
|
||||||
|
if (result.extras) {
|
||||||
|
if (result.extras.categories) {
|
||||||
|
result.extras.categories.forEach(category => {
|
||||||
|
category.tags = category.tags.map(t => Tag.create(t));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (result.extras.tag_groups) {
|
||||||
|
result.extras.tag_groups.forEach(tagGroup => {
|
||||||
|
tagGroup.tags = tagGroup.tags.map(t => Tag.create(t));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
titleToken() {
|
titleToken() {
|
||||||
|
@ -10,7 +26,7 @@ export default Discourse.Route.extend({
|
||||||
setupController(controller, model) {
|
setupController(controller, model) {
|
||||||
this.controllerFor('tags.index').setProperties({
|
this.controllerFor('tags.index').setProperties({
|
||||||
model,
|
model,
|
||||||
sortProperties: this.siteSettings.tags_sort_alphabetically ? ['id'] : ['count:desc', 'id']
|
sortProperties: this.siteSettings.tags_sort_alphabetically ? ['id'] : ['totalCount:desc', 'id']
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,7 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#each sortedTags as |tag|}}
|
{{#each sortedTags as |tag|}}
|
||||||
<div class='tag-box'>
|
<div class='tag-box'>
|
||||||
{{#if tag.count}}
|
{{discourse-tag tag.id isPrivateMessage=isPrivateMessage tagsForUser=tagsForUser}} {{#if tag.pm_count}}{{d-icon "envelope"}}{{/if}}{{#if tag.totalCount}} <span class='tag-count'>x {{tag.totalCount}}</span>{{/if}}
|
||||||
{{discourse-tag tag.id isPrivateMessage=isPrivateMessage tagsForUser=tagsForUser}} <span class='tag-count'>x {{tag.count}}</span>
|
|
||||||
{{else}}
|
|
||||||
{{discourse-tag tag.id}}
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
<div class="clearfix" />
|
<div class="clearfix" />
|
||||||
|
|
|
@ -33,7 +33,11 @@ class TagsController < ::ApplicationController
|
||||||
|
|
||||||
format.json do
|
format.json do
|
||||||
ungrouped_tags = Tag.where("tags.id NOT IN (select tag_id from tag_group_memberships)")
|
ungrouped_tags = Tag.where("tags.id NOT IN (select tag_id from tag_group_memberships)")
|
||||||
ungrouped_tags = ungrouped_tags.where("tags.topic_count > 0") unless guardian.can_admin_tags?
|
|
||||||
|
# show all the tags to admins
|
||||||
|
unless guardian.can_admin_tags? && guardian.is_admin?
|
||||||
|
ungrouped_tags = ungrouped_tags.where("tags.topic_count > 0")
|
||||||
|
end
|
||||||
|
|
||||||
if SiteSetting.tags_listed_by_group
|
if SiteSetting.tags_listed_by_group
|
||||||
grouped_tag_counts = TagGroup.allowed(guardian).order('name ASC').includes(:tags).map do |tag_group|
|
grouped_tag_counts = TagGroup.allowed(guardian).order('name ASC').includes(:tags).map do |tag_group|
|
||||||
|
@ -210,7 +214,7 @@ class TagsController < ::ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.tag_counts_json(tags)
|
def self.tag_counts_json(tags)
|
||||||
tags.map { |t| { id: t.name, text: t.name, count: t.topic_count } }
|
tags.map { |t| { id: t.name, text: t.name, count: t.topic_count, pm_count: t.pm_topic_count } }
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_category_from_params
|
def set_category_from_params
|
||||||
|
|
|
@ -20,22 +20,40 @@ class Tag < ActiveRecord::Base
|
||||||
after_commit :trigger_tag_destroyed_event, on: :destroy
|
after_commit :trigger_tag_destroyed_event, on: :destroy
|
||||||
|
|
||||||
def self.ensure_consistency!
|
def self.ensure_consistency!
|
||||||
update_topic_counts # topic_count counter cache can miscount
|
update_topic_counts
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.update_topic_counts
|
def self.update_topic_counts
|
||||||
Category.exec_sql <<~SQL
|
Tag.exec_sql <<~SQL
|
||||||
UPDATE tags t
|
UPDATE tags t
|
||||||
SET topic_count = x.topic_count
|
SET topic_count = x.topic_count
|
||||||
FROM (
|
FROM (
|
||||||
SELECT COUNT(topics.id) AS topic_count, tags.id AS tag_id
|
SELECT COUNT(topics.id) AS topic_count, tags.id AS tag_id
|
||||||
FROM tags
|
FROM tags
|
||||||
LEFT JOIN topic_tags ON tags.id = topic_tags.tag_id
|
LEFT JOIN topic_tags ON tags.id = topic_tags.tag_id
|
||||||
LEFT JOIN topics ON topics.id = topic_tags.topic_id AND topics.deleted_at IS NULL AND topics.archetype != 'private_message'
|
LEFT JOIN topics ON topics.id = topic_tags.topic_id
|
||||||
GROUP BY tags.id
|
AND topics.deleted_at IS NULL
|
||||||
) x
|
AND topics.archetype != 'private_message'
|
||||||
WHERE x.tag_id = t.id
|
GROUP BY tags.id
|
||||||
AND x.topic_count <> t.topic_count
|
) x
|
||||||
|
WHERE x.tag_id = t.id
|
||||||
|
AND x.topic_count <> t.topic_count
|
||||||
|
SQL
|
||||||
|
|
||||||
|
Tag.exec_sql <<~SQL
|
||||||
|
UPDATE tags t
|
||||||
|
SET pm_topic_count = x.pm_topic_count
|
||||||
|
FROM (
|
||||||
|
SELECT COUNT(topics.id) AS pm_topic_count, tags.id AS tag_id
|
||||||
|
FROM tags
|
||||||
|
LEFT JOIN topic_tags ON tags.id = topic_tags.tag_id
|
||||||
|
LEFT JOIN topics ON topics.id = topic_tags.topic_id
|
||||||
|
AND topics.deleted_at IS NULL
|
||||||
|
AND topics.archetype = 'private_message'
|
||||||
|
GROUP BY tags.id
|
||||||
|
) x
|
||||||
|
WHERE x.tag_id = t.id
|
||||||
|
AND x.pm_topic_count <> t.pm_topic_count
|
||||||
SQL
|
SQL
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -54,7 +72,7 @@ class Tag < ActiveRecord::Base
|
||||||
tag_names_with_counts = Tag.exec_sql <<~SQL
|
tag_names_with_counts = Tag.exec_sql <<~SQL
|
||||||
SELECT tags.name as tag_name, SUM(stats.topic_count) AS sum_topic_count
|
SELECT tags.name as tag_name, SUM(stats.topic_count) AS sum_topic_count
|
||||||
FROM category_tag_stats stats
|
FROM category_tag_stats stats
|
||||||
INNER JOIN tags ON stats.tag_id = tags.id AND stats.topic_count > 0
|
JOIN tags ON stats.tag_id = tags.id AND stats.topic_count > 0
|
||||||
WHERE stats.category_id in (#{scope_category_ids.join(',')})
|
WHERE stats.category_id in (#{scope_category_ids.join(',')})
|
||||||
#{filter_sql}
|
#{filter_sql}
|
||||||
GROUP BY tags.name
|
GROUP BY tags.name
|
||||||
|
@ -71,23 +89,24 @@ class Tag < ActiveRecord::Base
|
||||||
user_id = allowed_user.id
|
user_id = allowed_user.id
|
||||||
|
|
||||||
tag_names_with_counts = Tag.exec_sql <<~SQL
|
tag_names_with_counts = Tag.exec_sql <<~SQL
|
||||||
SELECT tags.name,
|
SELECT tags.name, COUNT(topics.id) AS topic_count
|
||||||
COUNT(topics.id) AS topic_count
|
FROM tags
|
||||||
FROM tags
|
JOIN topic_tags ON tags.id = topic_tags.tag_id
|
||||||
INNER JOIN topic_tags ON tags.id = topic_tags.tag_id
|
JOIN topics ON topics.id = topic_tags.topic_id
|
||||||
INNER JOIN topics ON topics.id = topic_tags.topic_id
|
AND topics.deleted_at IS NULL
|
||||||
AND topics.deleted_at IS NULL
|
AND topics.archetype = 'private_message'
|
||||||
AND topics.archetype = 'private_message'
|
WHERE topic_tags.topic_id IN (
|
||||||
WHERE topic_tags.topic_id IN
|
SELECT topic_id
|
||||||
(SELECT topic_id
|
FROM topic_allowed_users
|
||||||
FROM topic_allowed_users
|
WHERE user_id = #{user_id}
|
||||||
WHERE user_id = #{user_id}
|
UNION
|
||||||
UNION ALL SELECT tg.topic_id
|
SELECT tg.topic_id
|
||||||
FROM topic_allowed_groups tg
|
FROM topic_allowed_groups tg
|
||||||
JOIN group_users gu ON gu.user_id = #{user_id}
|
JOIN group_users gu ON gu.user_id = #{user_id}
|
||||||
AND gu.group_id = tg.group_id)
|
AND gu.group_id = tg.group_id
|
||||||
GROUP BY tags.name
|
)
|
||||||
LIMIT #{limit}
|
GROUP BY tags.name
|
||||||
|
LIMIT #{limit}
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
tag_names_with_counts.map { |t| { id: t['name'], text: t['name'], count: t['topic_count'] } }
|
tag_names_with_counts.map { |t| { id: t['name'], text: t['name'], count: t['topic_count'] } }
|
||||||
|
@ -120,11 +139,12 @@ end
|
||||||
#
|
#
|
||||||
# Table name: tags
|
# Table name: tags
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
# name :string not null
|
# name :string not null
|
||||||
# topic_count :integer default(0), not null
|
# topic_count :integer default(0), not null
|
||||||
# created_at :datetime not null
|
# created_at :datetime not null
|
||||||
# updated_at :datetime not null
|
# updated_at :datetime not null
|
||||||
|
# pm_topic_count :integer default(0), not null
|
||||||
#
|
#
|
||||||
# Indexes
|
# Indexes
|
||||||
#
|
#
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
class AddPmTopicCountToTags < ActiveRecord::Migration[5.1]
|
||||||
|
def change
|
||||||
|
add_column :tags, :pm_topic_count, :integer, null: false, default: 0
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue