diff --git a/plugins/environment_notification/controllers/environment_notification_plugin_admin_controller.rb b/plugins/environment_notification/controllers/environment_notification_plugin_admin_controller.rb new file mode 100644 index 0000000..0e72bdd --- /dev/null +++ b/plugins/environment_notification/controllers/environment_notification_plugin_admin_controller.rb @@ -0,0 +1,81 @@ +class EnvironmentNotificationPluginAdminController < AdminController + before_filter :admin_required, :except => [:hide_notification] + def index + @notifications = environment.notifications.order('updated_at DESC') + end + + def new + @notification = Notification.new + if request.post? + @notification = Notification.new(params[:notifications]) + @notification.message = @notification.message.html_safe + @notification.environment_id = environment.id + if @notification.save + session[:notice] = _("Notification successfully created") + redirect_to :action => :index + else + session[:notice] = _("Notification couldn't be created") + end + end + end + + def destroy + if request.delete? + notification = environment.notifications.find_by_id(params[:id]) + if notification && notification.destroy + session[:notice] = _('The notification was deleted.') + else + session[:notice] = _('Could not remove the notification') + end + end + redirect_to :action => :index + end + + def edit + @notification = environment.notifications.find_by_id(params[:id]) + if request.post? + if @notification.update_attributes(params[:notifications]) + session[:notice] = _('The notification was edited.') + else + session[:notice] = _('Could not edit the notification.') + end + redirect_to :action => :index + end + end + + def change_status + @notification = environment.notifications.find_by_id(params[:id]) + + @notification.active = !@notification.active + + if @notification.save! + session[:notice] = _('The status of the notification was changed.') + else + session[:notice] = _('Could not change the status of the notification.') + end + + redirect_to :action => :index + end + + def hide_notification + result = false + + if logged_in? + @notification = environment.notifications.find_by_id(params[:notification_id]) + + if @notification + # Fix-me. I need validation on sucess and fail + @notification.users << current_user + result = @notification.users.include?(current_user) + end + end + + render json: result + end + + protected + def admin_required + redirect_to :root unless current_user.person.is_admin? + end + +end diff --git a/plugins/environment_notification/db/migrate/20150721132025_create_notification_table.rb b/plugins/environment_notification/db/migrate/20150721132025_create_notification_table.rb new file mode 100644 index 0000000..ee06abf --- /dev/null +++ b/plugins/environment_notification/db/migrate/20150721132025_create_notification_table.rb @@ -0,0 +1,22 @@ +class CreateNotificationTable < ActiveRecord::Migration + def up + create_table :notifications do |t| + t.text :message + t.integer :environment_id + t.string :type + t.boolean :active + t.column :created_at, :datetime + t.column :updated_at, :datetime + end + + create_table :notifications_users, id: false do |t| + t.belongs_to :notification, index: true + t.belongs_to :user, index: true + end + end + + def down + drop_table :notifications + drop_table :notifications_users + end +end diff --git a/plugins/environment_notification/init.rb b/plugins/environment_notification/init.rb new file mode 100644 index 0000000..27f794b --- /dev/null +++ b/plugins/environment_notification/init.rb @@ -0,0 +1 @@ +require environment_notification_plugin.rb diff --git a/plugins/environment_notification/lib/danger_notification.rb b/plugins/environment_notification/lib/danger_notification.rb new file mode 100644 index 0000000..e327119 --- /dev/null +++ b/plugins/environment_notification/lib/danger_notification.rb @@ -0,0 +1,2 @@ +class DangerNotification < Notification +end diff --git a/plugins/environment_notification/lib/environment_notification_plugin.rb b/plugins/environment_notification/lib/environment_notification_plugin.rb new file mode 100644 index 0000000..584c392 --- /dev/null +++ b/plugins/environment_notification/lib/environment_notification_plugin.rb @@ -0,0 +1,29 @@ +class EnvironmentNotificationPlugin < Noosfero::Plugin + + def self.plugin_name + "Environment Notifications Plugin" + end + + def self.plugin_description + _("A plugin for environment notifications.") + end + + def stylesheet? + true + end + + def js_files + %w( + public/app.js + ) + end + + def body_beginning + expanded_template('environment_notification_plugin_admin/show_notification.html.erb') + end + + def admin_panel_links + {:title => _('Notification Manager'), :url => {:controller => 'environment_notification_plugin_admin', :action => 'index'}} + end + +end diff --git a/plugins/environment_notification/lib/ext/environment.rb b/plugins/environment_notification/lib/ext/environment.rb new file mode 100644 index 0000000..3ce080b --- /dev/null +++ b/plugins/environment_notification/lib/ext/environment.rb @@ -0,0 +1,5 @@ +require_dependency 'environment' + +class Environment + has_many :notifications +end diff --git a/plugins/environment_notification/lib/ext/user.rb b/plugins/environment_notification/lib/ext/user.rb new file mode 100644 index 0000000..6ea5769 --- /dev/null +++ b/plugins/environment_notification/lib/ext/user.rb @@ -0,0 +1,6 @@ +require_dependency 'user' + +class User + has_many :notifications_users + has_many :notifications, :through => :notifications_users +end diff --git a/plugins/environment_notification/lib/information_notification.rb b/plugins/environment_notification/lib/information_notification.rb new file mode 100644 index 0000000..b1dcf00 --- /dev/null +++ b/plugins/environment_notification/lib/information_notification.rb @@ -0,0 +1,2 @@ +class InformationNotification < Notification +end diff --git a/plugins/environment_notification/lib/notification.rb b/plugins/environment_notification/lib/notification.rb new file mode 100644 index 0000000..1122ec5 --- /dev/null +++ b/plugins/environment_notification/lib/notification.rb @@ -0,0 +1,21 @@ +class Notification < ActiveRecord::Base + + TYPE_LIST = ["WarningNotification", "SuccessNotification", "InformationNotification", + "DangerNotification"] + + attr_accessible :message, :environment_id, :active, :type + + has_many :notifications_users + has_many :users, :through => :notifications_users + + validates_presence_of :message + validates_presence_of :environment_id + validate :notification_type_must_be_in_type_list + + def notification_type_must_be_in_type_list + unless TYPE_LIST.include?(type) + errors.add(:type, "invalid notification type") + end + end + +end diff --git a/plugins/environment_notification/lib/notifications_user.rb b/plugins/environment_notification/lib/notifications_user.rb new file mode 100644 index 0000000..6f02112 --- /dev/null +++ b/plugins/environment_notification/lib/notifications_user.rb @@ -0,0 +1,8 @@ +class NotificationsUser < ActiveRecord::Base + belongs_to :user + belongs_to :notification + + attr_accessible :user_id, :notification_id + + validates_uniqueness_of :user_id, :scope => :notification_id +end diff --git a/plugins/environment_notification/lib/success_notification.rb b/plugins/environment_notification/lib/success_notification.rb new file mode 100644 index 0000000..bc20adb --- /dev/null +++ b/plugins/environment_notification/lib/success_notification.rb @@ -0,0 +1,2 @@ +class SuccessNotification < Notification +end diff --git a/plugins/environment_notification/lib/warning_notification.rb b/plugins/environment_notification/lib/warning_notification.rb new file mode 100644 index 0000000..397a6f9 --- /dev/null +++ b/plugins/environment_notification/lib/warning_notification.rb @@ -0,0 +1,2 @@ +class WarningNotification < Notification +end diff --git a/plugins/environment_notification/public/app.js b/plugins/environment_notification/public/app.js new file mode 100644 index 0000000..68caee4 --- /dev/null +++ b/plugins/environment_notification/public/app.js @@ -0,0 +1,40 @@ +(function($) { + "use strict"; + function repositioning_notification_bar() { + var complete_message = $(".notification-bar").remove(); + + $("#content-inner").before(complete_message); + } + + jQuery(document).ready(function(){ + repositioning_notification_bar(); + $(".notification-close").on("click", hideNotification) + mceRestrict(); + }); + + function hideNotification(){ + var notification = $(this).parent(); + var id = notification.attr("data-notification"); + + $.ajax({ + url: noosfero_root()+"/admin/plugin/environment_notification/hide_notification", + type: "POST", + data: {notification_id: id}, + success: function(response) { + notification.fadeOut(); + } + }); + } + + function mceRestrict() { + tinyMCE.init({ + menubar : false, + selector: "textarea", + plugins: [ + "autolink link" + ], + toolbar: "bold italic underline | link" + }); + } + +})(jQuery); diff --git a/plugins/environment_notification/public/images/close.png b/plugins/environment_notification/public/images/close.png new file mode 100644 index 0000000..e51bbb9 Binary files /dev/null and b/plugins/environment_notification/public/images/close.png differ diff --git a/plugins/environment_notification/public/images/hide.png b/plugins/environment_notification/public/images/hide.png new file mode 100644 index 0000000..5804c92 Binary files /dev/null and b/plugins/environment_notification/public/images/hide.png differ diff --git a/plugins/environment_notification/public/images/show.png b/plugins/environment_notification/public/images/show.png new file mode 100644 index 0000000..477815e Binary files /dev/null and b/plugins/environment_notification/public/images/show.png differ diff --git a/plugins/environment_notification/style.css b/plugins/environment_notification/style.css new file mode 100644 index 0000000..a8d9d12 --- /dev/null +++ b/plugins/environment_notification/style.css @@ -0,0 +1,141 @@ +.notification-bar { + display: block; +} + +.notification:hover { + opacity: 0.8; +} + +#notification-manager { + overflow: auto; +} + +.notification .notification-close { + background: url(public/images/close.png) no-repeat; + background-position: center; + width: 20px; + height: 20px; +} + +.warningnotification, +.informationnotification, +.successnotification, +.dangernotification { + margin-bottom: 10px; + padding: 7px 10px; + border-radius: 5px; + border: 1px solid blue; + font-size: 16px; + color: white; + overflow: auto; +} + +.warningnotification p, +.informationnotification p, +.successnotification p, +.dangernotification p { + margin: 0px; +} + +.warningnotification { + background: #EEA236; + border: 1px solid #EEA236; +} + +.informationnotification { + background: #5BC0DE; + border: 1px solid #46B8DA; +} + +.successnotification { + background: #5CB85C; + border: 1px solid #4CAE4C; +} + +.dangernotification { + background: #C9302C; + border: 1px solid #AC2925; +} + +a.button.icon-deactivate { + background: url(public/images/hide.png) no-repeat; + background-position: center; +} + +a.button.icon-activate { + background: url(public/images/show.png) no-repeat; + background-position: center; +} + +.notification-line { + display: inline; + padding-top: 10px; + vertical-align: middle; + border-bottom: 1px solid #ccc; +} + +.notification-title-bar { + float: left; + width: 100%; + font-style: 14px; + font-weight: 700; + border-bottom: 2px solid black; + padding: 9px 0; +} + +.notification-title { + width: 80%; + float: left; + text-align: center; +} + +.action-title { + width: 20%; + float: left; + text-align: center; +} + +.notification-action { + width: 18%; + float: left; + height: 30px; + padding-top: 9px; +} + +.main-bar .button, +.notification-action .button { + border-radius: 3px; +} + +.notification-message { + width: 82%; + float: left; +} + +.new-notification { + float: right; + width: auto; +} + +.back-button { + float: left; +} + +.main-bar { + display: inline; + width: 100%; +} + +.notification-bar .notification .notification-message { + width: 90%; + float: left; +} + +.notification-bar .notification .notification-close { + background: url(public/images/close.png) no-repeat; + background-position: center; + width: 20px; + height: 20px; + float: right; + cursor: pointer; +} diff --git a/plugins/environment_notification/test/functional/environment_notification_plugin_admin_controller_test.rb b/plugins/environment_notification/test/functional/environment_notification_plugin_admin_controller_test.rb new file mode 100644 index 0000000..6b4548d --- /dev/null +++ b/plugins/environment_notification/test/functional/environment_notification_plugin_admin_controller_test.rb @@ -0,0 +1,144 @@ +require File.expand_path(File.dirname(__FILE__)) + '/../../../../test/test_helper' +require( + File.expand_path(File.dirname(__FILE__)) + + '/../../controllers/environment_notification_plugin_admin_controller' +) + +class EnvironmentNotificationPluginAdminController; def rescue_action(e) raise e end; +end + +class EnvironmentNotificationPluginAdminControllerTest < ActionController::TestCase + def setup + @controller = EnvironmentNotificationPluginAdminController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + @person = create_user('person').person + + @environment = Environment.default + @environment.enable_plugin('EnvironmentNotificationPlugin') + @environment.save! + + login_as(@person.user.login) + end + + attr_accessor :person + + should 'an admin be able to create a notification' do + @environment.add_admin(@person) + post :new, :notifications => { :message => "Message", + :active => true, + :type => "DangerNotification" + } + assert_redirected_to :action => 'index' + notification = Notification.last + assert_equal "Message", notification.message + assert notification.active + assert_equal "DangerNotification", notification.type + end + + should 'an user not to be able to create a notification' do + post :new, :notifications => { :message => "Message", + :active => true, + :type => "DangerNotification" + } + assert_redirected_to :root + assert_nil Notification.last + end + + should 'an admin be able to edit a notification' do + @environment.add_admin(@person) + @notification = Notification.create( :environment_id => @environment.id, + :message => "Message", + :active => true, + :type => "DangerNotification" + ) + post :edit, :id => @notification.id, + :notifications => { + :message => "Edited Message", + :active => false, + :type => "WarningNotification" + } + @notification = Notification.last + assert_redirected_to :action => 'index' + assert_equal "Edited Message", @notification.message + assert !@notification.active + assert_equal "WarningNotification", @notification.type + end + + should 'an user not to be able to edit a notification' do + @notification = Notification.create( :environment_id => @environment.id, + :message => "Message", + :active => true, + :type => "DangerNotification" + ) + post :edit, :notifications => { :message => "Edited Message", + :active => false, + :type => "DangerNotification" + } + @notification.reload + assert_redirected_to :root + assert_equal "Message", @notification.message + assert @notification.active + end + + should 'an admin be able to destroy a notification' do + @environment.add_admin(@person) + @notification = Notification.create( :environment_id => @environment.id, + :message => "Message", + :active => true, + :type => "DangerNotification" + ) + delete :destroy, :id => @notification.id + assert_nil Notification.find_by_id(@notification.id) + end + + should 'an user not to be able to destroy a notification' do + @notification = Notification.create( :environment_id => @environment.id, + :message => "Message", + :active => true, + :type => "DangerNotification" + ) + delete :destroy, :id => @notification.id + + assert_redirected_to :root + assert_not_nil Notification.find_by_id(@notification.id) + end + + should 'an admin be able to change Notification status' do + @environment.add_admin(@person) + @notification = Notification.create( :environment_id => @environment.id, + :message => "Message", + :active => true, + :type => "DangerNotification" + ) + post :change_status, :id => @notification.id + assert_redirected_to :action => 'index' + + @notification.reload + assert !@notification.active + end + + should 'an user not be able to change Notification status' do + @notification = Notification.create( :environment_id => @environment.id, + :message => "Message", + :active => true, + :type => "DangerNotification" + ) + post :change_status, :id => @notification.id + assert_redirected_to :root + + @notification.reload + assert @notification.active + end + + should 'a logged in user be able to permanently hide notifications' do + @notification = Notification.create( :environment_id => @environment.id, + :message => "Message", + :active => true, + :type => "DangerNotification" + ) + post :hide_notification, :notification_id => @notification.id + assert_equal "true", @response.body + assert_equal true, @notification.users.include?(@person.user) + end +end diff --git a/plugins/environment_notification/test/functional/home_controller_test.rb b/plugins/environment_notification/test/functional/home_controller_test.rb new file mode 100644 index 0000000..904f9f7 --- /dev/null +++ b/plugins/environment_notification/test/functional/home_controller_test.rb @@ -0,0 +1,88 @@ +require File.expand_path(File.dirname(__FILE__)) + '/../../../../test/test_helper' +require 'home_controller' + +class HomeController; def rescue_action(e) raise e end; +end + +class HomeControllerTest < ActionController::TestCase + def setup + @controller = HomeController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + @person = create_user('person').person + + @environment = Environment.default + @environment.enable_plugin('EnvironmentNotificationPlugin') + @environment.save! + end + + attr_accessor :person + + should 'an active notification be displayed on home page for a logged in user' do + login_as(@person.user.login) + @notification = Notification.create( :environment_id => @environment.id, + :message => "Hello, this is a Notification Message", + :active => true, + :type => "DangerNotification" + ) + get :index + assert_match /Hello, this is a Notification Message/, @response.body + end + + + should 'an active notification be displayed on home page for unlogged user' do + @notification = Notification.create( :environment_id => @environment.id, + :message => "Hello, this is a Notification Message", + :active => true, + :type => "DangerNotification" + ) + get :index + assert_match /Hello, this is a Notification Message/, @response.body + end + + + should 'only the last notification be displayed on home page for unlogged user' do + @notification1 = Notification.create( :environment_id => @environment.id, + :message => "Hello, this is an old Notification Message", + :active => true, + :type => "DangerNotification" + ) + + @notification2 = Notification.create( :environment_id => @environment.id, + :message => "Hello, this is a new Notification Message", + :active => true, + :type => "DangerNotification" + ) + + + get :index + assert_no_match /Hello, this is a Notification Message/, @response.body + assert_match /Hello, this is a new Notification Message/, @response.body + end + + should 'an inactive notification not be displayed on home page' do + @notification = Notification.create( :environment_id => @environment.id, + :message => "Hello, this is a Notification Message", + :active => false, + :type => "DangerNotification" + ) + get :index + assert_no_match /Hello, this is a Notification Message/, @response.body + end + + + should 'an active notification not be displayed to a logged in user after been closed by him' do + login_as(@person.user.login) + @notification = Notification.create( :environment_id => @environment.id, + :message => "Hello, this is a Notification Message", + :active => true, + :type => "DangerNotification" + ) + @notification.users << @person.user + @notification.save! + assert_equal true, @notification.users.include?(@person.user) + get :index + assert_no_match /Hello, this is a Notification Message/, @response.body + end + +end diff --git a/plugins/environment_notification/views/environment_notification_plugin_admin/_form.html.erb b/plugins/environment_notification/views/environment_notification_plugin_admin/_form.html.erb new file mode 100644 index 0000000..5f0064c --- /dev/null +++ b/plugins/environment_notification/views/environment_notification_plugin_admin/_form.html.erb @@ -0,0 +1,19 @@ +<% abstract_options = {:value => @notification.message, :style => 'width: 100%; height: 200px;'} %> + +<%= button :back, _('Back'), :controller => 'environment_notification_plugin_admin' %> + +<%= form_for :notifications do |f| %> + + <%= render :file => 'shared/tiny_mce' %> + + <%= labelled_form_field(_("Enter your message here:"), f.text_area(:message, abstract_options)) %> + + <%= labelled_form_field(_('Notifications Status'), select(:notifications, :active, options_for_select_with_title({"Active" => true, "Inactive" => false}, @notification.active))) %> + + <%= labelled_form_field(_('Notifications Type'), select(:notifications, :type, options_for_select_with_title({"Information" => "InformationNotification", "Warning" => "WarningNotification", "Success" => "SuccessNotification", "Danger" => "DangerNotification"}, @notification.type))) %> + + <% button_bar do %> + <%= submit_button 'save', _('Save'), :cancel => { :action => 'index' } %> + <% end %> + +<% end %> diff --git a/plugins/environment_notification/views/environment_notification_plugin_admin/edit.html.erb b/plugins/environment_notification/views/environment_notification_plugin_admin/edit.html.erb new file mode 100644 index 0000000..2872e82 --- /dev/null +++ b/plugins/environment_notification/views/environment_notification_plugin_admin/edit.html.erb @@ -0,0 +1 @@ +<%= render :partial => "form" %> diff --git a/plugins/environment_notification/views/environment_notification_plugin_admin/index.html.erb b/plugins/environment_notification/views/environment_notification_plugin_admin/index.html.erb new file mode 100644 index 0000000..a17d8be --- /dev/null +++ b/plugins/environment_notification/views/environment_notification_plugin_admin/index.html.erb @@ -0,0 +1,40 @@ +