diff --git a/app/assets/javascripts/notifications.js b/app/assets/javascripts/notifications.js new file mode 100644 index 000000000..c8c697bc8 --- /dev/null +++ b/app/assets/javascripts/notifications.js @@ -0,0 +1,19 @@ +$(document.body).ready(function () { + $('.btn-more-notifications') + .on("ajax:success", function (e, data) { + var list = $('.notifications-list'); + var moreBtn = $('.btn-more-notifications'); + if (data.html) { + // Remove button if all notifications are shown + if (data.results_number < data.per_page) { + moreBtn.remove(); + // Otherwise update reference + } else { + moreBtn.attr('href', data.more_notifications_url); + } + $(list).append(data.html); + } else if (data.results_number < 1) { + moreBtn.remove(); + } + }); +}); diff --git a/app/assets/stylesheets/notifications.scss b/app/assets/stylesheets/notifications.scss new file mode 100644 index 000000000..dc7594de2 --- /dev/null +++ b/app/assets/stylesheets/notifications.scss @@ -0,0 +1,81 @@ +@import "colors"; +@import "mixins"; + +.notifications-container { + margin-bottom: 20px; + margin-top: 20px; +} + +.notifications-header { + background-color: $color-concrete; + border-left: 1px solid $color-alto; + border-right: 1px solid $color-alto; + border-top: 1px solid $color-alto; + border-top-left-radius: 10px; + border-top-right-radius: 10px; + color: $color-dove-gray; + font-weight: bold; + padding: 8px; +} + +.notifications-list { + background-color: $color-white; + border: 1px solid $color-alto; + list-style: none; + margin-bottom: 0; + padding: 0; + + .notification { + border-bottom: 1px solid $color-alto; + padding-bottom: 10px; + padding-top: 10px; + + &:hover { + background-color: $color-mystic; + } + } + + .unseen { + border-left: 4px solid $color-theme-primary; + } + + .text-center { + margin-left: 10px; + padding-top: 10px; + } + + .assignment { + background-color: $color-theme-primary; + border-radius: 50%; + color: $color-wild-sand; + font-size: 15px; + padding: 7px; + } + + .system-message { + background-color: $color-theme-secondary; + border-radius: 50%; + color: $color-wild-sand; + font-size: 13px; + padding: 7px 10px; + } +} + + +.notifications-footer { + + background-color: $color-mystic; + + .btn-more-notifications { + border-bottom: 1px solid $color-alto; + border-left: 1px solid $color-alto; + border-right: 1px solid $color-alto; + margin: 0; + padding: 8px; + text-align: center; + + &:hover { + background-color: $color-mystic; + } + } +} diff --git a/app/controllers/user_notifications_controller.rb b/app/controllers/user_notifications_controller.rb index a74e0d44b..767ddfc86 100644 --- a/app/controllers/user_notifications_controller.rb +++ b/app/controllers/user_notifications_controller.rb @@ -1,4 +1,47 @@ class UserNotificationsController < ApplicationController + layout 'main' + + def index + @last_notification_id = params[:from].to_i || 0 + @per_page = 10 + + @notifications = + UserNotification.last_notifications(@current_user, + @last_notification_id, + @per_page + 1) + + @more_notifications_url = '' + + @overflown = @notifications.length > @per_page + + @notifications = + UserNotification.last_notifications(@current_user, + @last_notification_id, + @per_page) + + if @notifications.count > 0 + @more_notifications_url = url_for( + controller: 'user_notifications', + action: 'index', + format: :json, + from: @notifications.last.id + ) + end + + respond_to do |format| + format.html + format.json do + render json: { + per_page: @per_page, + results_number: @notifications.length, + more_notifications_url: @more_notifications_url, + html: render_to_string(partial: 'list.html.erb') + } + end + end + UserNotification.seen_by_user(current_user) + end + def recent_notifications @recent_notifications = UserNotification.recent_notifications(current_user) diff --git a/app/models/user_notification.rb b/app/models/user_notification.rb index ea34f52a0..17f9eb275 100644 --- a/app/models/user_notification.rb +++ b/app/models/user_notification.rb @@ -2,6 +2,15 @@ class UserNotification < ActiveRecord::Base belongs_to :user belongs_to :notification + def self.last_notifications(user, last_notification_id = nil, per_page = 10) + last_notification_id = 999999999999999999999999 if last_notification_id < 1 + Notification.joins(:user_notifications) + .where('user_notifications.user_id = ?', user.id) + .where('notifications.id < ?', last_notification_id) + .order(created_at: :DESC) + .limit(per_page) + end + def self.recent_notifications(user) Notification.joins(:user_notifications) .where('user_notifications.user_id = ?', user.id) diff --git a/app/views/user_notifications/_list.html.erb b/app/views/user_notifications/_list.html.erb new file mode 100644 index 000000000..831906c3f --- /dev/null +++ b/app/views/user_notifications/_list.html.erb @@ -0,0 +1,27 @@ +<% @notifications.each do |notification| %> +
  • +
    +
    + <% if notification.type_of == 'recent_changes' %> +
    + <%= image_tag avatar_path(notification.generator_user, :icon_small), class: 'avatar' %> +
    + <% end %> + <% if notification.type_of == 'assignment' %> +
    + <%= fa_icon 'newspaper-o' %> +
    + <% end %> + <% if notification.type_of == 'system_message' %> +
    + +
    + <% end %> +
    +
    + <%= notification.title.html_safe %>
    + <%= l(notification.created_at, format: :full) %> | <%= notification.message %> +
    +
    +
  • +<% end %> diff --git a/app/views/user_notifications/index.html.erb b/app/views/user_notifications/index.html.erb new file mode 100644 index 000000000..3a20af3b0 --- /dev/null +++ b/app/views/user_notifications/index.html.erb @@ -0,0 +1,20 @@ +<% provide(:head_title, raw(t("notifications.title"))) %> +
    +
    + <%= t('notifications.title') %><%= t('nav.user.settings') %> +
    +
    + +
    + +
    + +<%= javascript_include_tag("notifications") %> diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index f50042763..11ad88bd0 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -59,6 +59,7 @@ Rails.application.config.assets.precompile += %w(assets.js) Rails.application.config.assets.precompile += %w(comments.js) Rails.application.config.assets.precompile += %w(projects/show.js) Rails.application.config.assets.precompile += %w(projects/introdutory_popup.js) +Rails.application.config.assets.precompile += %w(notifications.js) # Libraries needed for Handsontable formulas Rails.application.config.assets.precompile += %w(lodash.js) diff --git a/config/locales/en.yml b/config/locales/en.yml index 791bbc36b..39c7e7fff 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1514,6 +1514,9 @@ en: form: assignments: "Assignments notifications" recent_notification: "Change notifications" + filter: "Filter" + show_all: "Show all notifications" + show_more: "Show more notifications" # This section contains general words that can be used in any parts of # application. diff --git a/config/routes.rb b/config/routes.rb index c050277be..dabeaaef2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -47,6 +47,10 @@ Rails.application.routes.draw do as: 'unseen_notification', defaults: { format: 'json' } + get 'users/notifications', + to: 'user_notifications#index', + as: 'notifications' + resources :organizations, only: [] do resources :samples, only: [:new, :create] resources :sample_types, only: [:new, :create]