dropdown on categorypage

This commit is contained in:
Catrin 2014-04-17 11:17:39 +02:00 committed by Neil Lalonde
parent 26fcd3793b
commit 772a304fc2
12 changed files with 228 additions and 3 deletions

View File

@ -157,6 +157,22 @@ Discourse.Category = Discourse.Model.extend({
return this.countStats('topics');
}.property('posts_year', 'posts_month', 'posts_week', 'posts_day'),
notification_level: function () {
return this.get('notification_level');
}.property('notification_level'),
setNotification: function (notification_level) {
//console.log("inside category.js");
var url = "/category/" + this.get('id')+"/notifications";
this.set('notification_level', notification_level)
return Discourse.ajax(url, {
data: {
notification_level: notification_level
},
type: 'POST'
});
},
postCountStats: function() {
return this.countStats('posts');
}.property('posts_year', 'posts_month', 'posts_week', 'posts_day'),
@ -178,6 +194,13 @@ Discourse.Category = Discourse.Model.extend({
Discourse.Category.reopenClass({
NotificationLevel: {
WATCHING: 3,
TRACKING: 2,
REGULAR: 1,
MUTED: 0
},
slugFor: function(category) {
if (!category) return "";

View File

@ -7,6 +7,8 @@
{{customHTML "extraNavItem"}}
</ul>
{{view Discourse.CategoryNotificationsButton categoryBinding="model" category=category}}
{{#if canCreateTopic}}
<button id="create-topic" class='btn btn-default' {{action createTopic}}><i class='fa fa-plus'></i>{{i18n topic.create}}</button>
{{/if}}

View File

@ -0,0 +1,50 @@
/**
This view handles rendering of a button with an associated drop down
@class CategoryNotificationDropdownButtonView
@extends Discourse.View
@namespace Discourse
@module Discourse
**/
Discourse.CategoryNotificationDropdownButtonView = Discourse.View.extend({
classNameBindings: [':btn-group', 'hidden'],
shouldRerender: Discourse.View.renderIfChanged('text', 'text'),
didInsertElement: function() {
// If there's a click handler, call it
if (this.clicked) {
var dropDownButtonView = this;
this.$('ul li').on('click.dropdown-button', function(e) {
e.preventDefault();
dropDownButtonView.clicked($(e.currentTarget).data('id'));
return false;
});
}
},
willDestroyElement: function() {
this.$('ul li').off('click.dropdown-button');
},
render: function(buffer) {
buffer.push("<button class='btn standard dropdown-toggle' data-toggle='dropdown'>");
buffer.push(this.get('text'));
buffer.push("</button>");
buffer.push("<ul class='notification-dropdown-menu'>");
_.each(this.get('dropDownContent'), function(row) {
var id = row[0],
textKey = row[1],
title = I18n.t(textKey + ".title"),
description = I18n.t(textKey + ".description");
buffer.push("<li data-id=\"" + id + "\"><a href='#'>");
buffer.push("<span class='title'>" + title + "</span>");
buffer.push("<span>" + description + "</span>");
buffer.push("</a></li>");
});
buffer.push("</ul>");
}
});

View File

@ -0,0 +1,65 @@
/**
A button to display notification options for categories.
@class NotificationsButton
@extends Discourse.DropdownButtonView
@namespace Discourse
@module Discourse
**/
Discourse.CategoryNotificationsButton = Discourse.CategoryNotificationDropdownButtonView.extend({
classNames: ['notification-options'],
//title: I18n.t('category.notifications.title'),
//longDescriptionBinding: 'topic.details.notificationReasonText',
//topic: Em.computed.alias('controller.model'),
category: Em.computed.alias('controller.model'),
hidden: Em.computed.alias('topic.deleted'),
dropDownContent: function() {
var contents = [];
_.each([
['WATCHING', 'watching'],
['TRACKING', 'tracking'],
['REGULAR', 'regular'],
['MUTED', 'muted']
], function(pair) {
if (pair[1] === 'regular') { return; }
contents.push([
Discourse.Category.NotificationLevel[pair[0]],
'category.notifications.' + pair[1]
]);
});
return contents;
}.property(),
// displayed Button
text: function() {
var key = (function() {
switch (this.get('category.notification_level')) {
case Discourse.Category.NotificationLevel.WATCHING: return 'watching';
case Discourse.Category.NotificationLevel.TRACKING: return 'tracking';
case Discourse.Category.NotificationLevel.MUTED: return 'muted';
default: return 'regular';
}
}).call(this);
var icon = (function() {
switch (key) {
case 'watching': return '<i class="fa fa-circle heatmap-high"></i>&nbsp;';
case 'tracking': return '<i class="fa fa-circle heatmap-low"></i>&nbsp;';
case 'muted': return '<i class="fa fa-times-circle"></i>&nbsp;';
default: return '';
}
})();
return icon + (I18n.t("category.notifications." + key + ".title")) + "<span class='caret'></span>";
}.property('category.notification_level'),
clicked: function(id) {
return this.get('category').setNotification(id);
}
});

View File

@ -0,0 +1,38 @@
@import "common/foundation/variables";
@import "common/foundation/mixins";
@import "common/foundation/helpers";
.notification-dropdown-menu {
position: absolute;
z-index: 100;
display: none;
width: 550px;
padding: 4px 0;
margin: 1px 0 0;
list-style: none;
background-color: $primary_background_color;
border: 1px solid $primary_border_color;
box-shadow: 0 1px 5px rgba($primary_shadow_color, .4);
background-clip: padding-box;
span {font-size: 12px;}
.title {font-weight: bold; display: block; font-size: 14px;}
}
.notification-dropdown-menu a {
display: block;
padding: 3px 15px;
clear: both;
font-weight: normal;
line-height: 18px;
color: $primary_text_color;
}
.notification-dropdown-menu li > a:hover,
.notification-dropdown-menu .active > a,
.notification-dropdown-menu .active > a:hover {
color: $tertiary_text_color;
text-decoration: none;
background-color: $emphasis_text_color;
}
.open > .notification-dropdown-menu {
display: block;
clear: both;
}

View File

@ -72,6 +72,14 @@ class CategoriesController < ApplicationController
}
end
def set_notifications
category_id = params[:category_id].to_i
notification_level = params[:notification_level].to_i
CategoryUser.set_notification_level_for_category(current_user, notification_level , category_id)
render json: success_json
end
def destroy
guardian.ensure_can_delete!(@category)
@category.destroy

View File

@ -66,7 +66,7 @@ class Category < ActiveRecord::Base
# permission is just used by serialization
# we may consider wrapping this in another spot
attr_accessor :displayable_topics, :permission, :subcategory_ids
attr_accessor :displayable_topics, :permission, :subcategory_ids, :notification_level
def self.scoped_to_permissions(guardian, permission_types)

View File

@ -6,6 +6,10 @@ class CategoryUser < ActiveRecord::Base
self.where(user: user, notification_level: notification_levels[level])
end
def self.lookup_by_category(user, category)
self.where(user: user, category: category)
end
# same for now
def self.notification_levels
TopicUser.notification_levels
@ -35,6 +39,20 @@ class CategoryUser < ActiveRecord::Base
end
end
def self.set_notification_level_for_category(user, level, category_id)
record = CategoryUser.where(user: user, category_id: category_id).first
# oder CategoryUser.where(user: user, category_id: category_id).destroy_all
# und danach mir create anlegen.
if record.present?
record.notification_level = level
record.save!
else
CategoryUser.create!(user: user, category_id: category_id, notification_level: level)
end
end
def self.auto_mute_new_topic(topic)
apply_default_to_topic(
topic,

View File

@ -45,6 +45,11 @@ class Site
by_id = {}
categories.each do |category|
# nur wenn user gesetzt ist
#unless guardian.anonymous?
category.notification_level = CategoryUser.lookup_by_category(@guardian.user, category).pluck(:notification_level)[0]
#end
category.permission = CategoryGroup.permission_types[:full] if allowed_topic_create.include?(category.id)
by_id[category.id] = category
end

View File

@ -11,10 +11,10 @@ class BasicCategorySerializer < ApplicationSerializer
:topic_url,
:read_restricted,
:permission,
:parent_category_id
:parent_category_id,
:notification_level
def include_parent_category_id?
parent_category_id
end
end

View File

@ -1142,6 +1142,21 @@ en:
default_position: "Default Position"
position_disabled: 'Categories will be displayed in order of activity. To control the order of categories in lists, enable the "fixed category positions" setting.'
parent: "Parent Category"
notifications:
title: ''
reasons:
watching:
title: "Watching"
description: "You will automatically watch all new topics in these categories. You will be notified of all new posts and topics, plus the count of unread and new posts will also appear next to the topic's listing."
tracking:
title: "Tracking"
description: "You will automatically track all new topics in these categories. The count of unread and new posts will appear next to the topic's listing."
regular:
title: "Regular"
description: "You will be notified only if someone mentions your @name or replies to your post."
muted:
title: "Muted"
description: "You will not be notified of anything about new topics in these categories, and they will not appear on your unread tab."
flagging:
title: 'Why are you privately flagging this post?'

View File

@ -278,6 +278,7 @@ Discourse::Application.routes.draw do
get "category/:category" => "list#category_latest"
get "category/:category/none" => "list#category_none_latest"
get "category/:parent_category/:category" => "list#parent_category_category_latest"
post "category/:category_id/notifications" => "categories#set_notifications"
get "top" => "list#top"
get "category/:category/l/top" => "list#category_top", as: "category_top"