mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-11-18 23:21:30 +08:00
Merge pull request #6469 from aignatov-bio/ai-sci-9512-implement-acitvity-notifications
Implement acitvity notifications [SCI-9512]
This commit is contained in:
commit
3bf218b5f6
16 changed files with 255 additions and 173 deletions
|
@ -94,7 +94,7 @@
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
color: $color-white;
|
color: $color-white;
|
||||||
display: flex;
|
display: flex;
|
||||||
grid-row: 1 / 4;
|
grid-row: 1 / 5;
|
||||||
height: 2rem;
|
height: 2rem;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-right: .75rem;
|
margin-right: .75rem;
|
||||||
|
|
|
@ -2,13 +2,10 @@
|
||||||
|
|
||||||
class UserNotificationsController < ApplicationController
|
class UserNotificationsController < ApplicationController
|
||||||
def index
|
def index
|
||||||
page = (params[:page] || 1).to_i
|
page = (params.dig(:page, :number) || 1).to_i
|
||||||
notifications = load_notifications.page(page).per(Constants::INFINITE_SCROLL_LIMIT).without_count
|
notifications = load_notifications.page(page).per(Constants::INFINITE_SCROLL_LIMIT)
|
||||||
|
|
||||||
render json: {
|
render json: notifications, each_serializer: NotificationSerializer
|
||||||
notifications: notification_serializer(notifications),
|
|
||||||
next_page: notifications.next_page
|
|
||||||
}
|
|
||||||
|
|
||||||
notifications.mark_as_read!
|
notifications.mark_as_read!
|
||||||
end
|
end
|
||||||
|
@ -26,17 +23,4 @@ class UserNotificationsController < ApplicationController
|
||||||
.order(created_at: :desc)
|
.order(created_at: :desc)
|
||||||
end
|
end
|
||||||
|
|
||||||
def notification_serializer(notifications)
|
|
||||||
notifications.map do |notification|
|
|
||||||
{
|
|
||||||
id: notification.id,
|
|
||||||
type_of: notification.type,
|
|
||||||
title: notification.to_notification.title,
|
|
||||||
message: notification.to_notification.message,
|
|
||||||
created_at: I18n.l(notification.created_at, format: :full),
|
|
||||||
today: notification.created_at.today?,
|
|
||||||
checked: notification.read_at.present?
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,15 +1,23 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="sci-navigation--notificaitons-flyout-notification">
|
<div class="sci-navigation--notificaitons-flyout-notification">
|
||||||
<div class="sci-navigation--notificaitons-flyout-notification-icon" :class="notification.type_of">
|
<div class="sci-navigation--notificaitons-flyout-notification-icon" :class="notification.attributes.type_of">
|
||||||
<i :class="icon"></i>
|
<i :class="icon"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="sci-navigation--notificaitons-flyout-notification-date">
|
<div class="sci-navigation--notificaitons-flyout-notification-date">
|
||||||
{{ notification.created_at }}
|
{{ notification.attributes.created_at }}
|
||||||
</div>
|
</div>
|
||||||
<div class="sci-navigation--notificaitons-flyout-notification-title"
|
<div class="sci-navigation--notificaitons-flyout-notification-title"
|
||||||
v-html="notification.title"
|
v-html="notification.attributes.title"
|
||||||
:data-seen="notification.checked"></div>
|
:data-seen="notification.attributes.checked"></div>
|
||||||
<div v-html="notification.message" class="sci-navigation--notificaitons-flyout-notification-message"></div>
|
<div v-html="notification.attributes.message" class="sci-navigation--notificaitons-flyout-notification-message"></div>
|
||||||
|
<div v-if="notification.attributes.breadcrumbs" class="flex items-center flex-wrap gap-0.5">
|
||||||
|
<template v-for="(breadcrumb, index) in notification.attributes.breadcrumbs">
|
||||||
|
<div :key="index" class="flex items-center gap-0.5">
|
||||||
|
<i v-if="index > 0" class="sn-icon sn-icon-right"></i>
|
||||||
|
<a :href="breadcrumb.url" :title="breadcrumb.name" class="truncate max-w-[20ch] inline-block">{{ breadcrumb.name }}</a>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -21,7 +29,7 @@ export default {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
icon() {
|
icon() {
|
||||||
switch(this.notification.type_of) {
|
switch(this.notification.attributes.type_of) {
|
||||||
case 'deliver':
|
case 'deliver':
|
||||||
return 'fas fa-truck';
|
return 'fas fa-truck';
|
||||||
case 'assignment':
|
case 'assignment':
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import NotificationItem from './notification_item.vue'
|
import NotificationItem from './notification_item.vue'
|
||||||
|
import axios from '../../../packs/custom_axios.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'NotificationsFlyout',
|
name: 'NotificationsFlyout',
|
||||||
|
@ -37,12 +38,13 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
notifications: [],
|
notifications: [],
|
||||||
nextPage: 1,
|
nextPageUrl: null,
|
||||||
scrollBar: null,
|
scrollBar: null,
|
||||||
loadingPage: false
|
loadingPage: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
this.nextPageUrl = this.notificationsUrl;
|
||||||
this.loadNotifications();
|
this.loadNotifications();
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
@ -58,23 +60,29 @@ export default {
|
||||||
this.loadNotifications();
|
this.loadNotifications();
|
||||||
},
|
},
|
||||||
todayNotifications() {
|
todayNotifications() {
|
||||||
return this.notifications.filter(n => n.today);
|
return this.notifications.filter(n => n.attributes.today);
|
||||||
},
|
},
|
||||||
olderNotifications() {
|
olderNotifications() {
|
||||||
return this.notifications.filter(n => !n.today);
|
return this.notifications.filter(n => !n.attributes.today);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
loadNotifications() {
|
loadNotifications() {
|
||||||
if (this.nextPage == null || this.loadingPage) return;
|
if (this.nextPageUrl == null || this.loadingPage) return;
|
||||||
|
|
||||||
this.loadingPage = true;
|
this.loadingPage = true;
|
||||||
$.getJSON(this.notificationsUrl, { page: this.nextPage }, (result) => {
|
|
||||||
this.notifications = this.notifications.concat(result.notifications);
|
axios.get(this.nextPageUrl)
|
||||||
this.nextPage = result.next_page;
|
.then(response => {
|
||||||
this.loadingPage = false;
|
this.notifications = this.notifications.concat(response.data.data);
|
||||||
this.$emit('update:unseenNotificationsCount');
|
this.nextPageUrl = response.data.links.next;
|
||||||
});
|
this.loadingPage = false;
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.loadingPage = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,100 +9,14 @@ module GenerateNotificationModel
|
||||||
end
|
end
|
||||||
|
|
||||||
def generate_notification_from_activity
|
def generate_notification_from_activity
|
||||||
return if notification_recipients.none?
|
params = { activity_id: id, type: "#{type_of}_activity".to_sym }
|
||||||
|
ActivityNotification.send_notifications(params, later: true)
|
||||||
message = generate_activity_content(self, no_links: true, no_custom_links: true)
|
|
||||||
description = generate_notification_description_elements(subject).reverse.join(' | ')
|
|
||||||
|
|
||||||
notification_recipients.each do |user|
|
|
||||||
ActivityNotification.with(
|
|
||||||
title: sanitize_input(message),
|
|
||||||
message: sanitize_input(description)
|
|
||||||
).deliver_later(user)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def notification_recipients
|
|
||||||
users = []
|
|
||||||
|
|
||||||
case subject
|
|
||||||
when Project
|
|
||||||
users = subject.users
|
|
||||||
when Experiment
|
|
||||||
users = subject.users
|
|
||||||
when MyModule
|
|
||||||
users = subject.designated_users
|
|
||||||
# Also send to the user that was unassigned,
|
|
||||||
# and is therefore no longer present on the module.
|
|
||||||
if type_of == 'undesignate_user_from_my_module'
|
|
||||||
users += User.where(id: values.dig('message_items', 'user_target', 'id'))
|
|
||||||
end
|
|
||||||
when Protocol
|
|
||||||
users = subject.in_repository? ? [] : subject.my_module.designated_users
|
|
||||||
when Result
|
|
||||||
users = subject.my_module.designated_users
|
|
||||||
when Repository
|
|
||||||
users = subject.team.users
|
|
||||||
when Team
|
|
||||||
users = subject.users
|
|
||||||
when Report
|
|
||||||
users = subject.team.users
|
|
||||||
when ProjectFolder
|
|
||||||
users = subject.team.users
|
|
||||||
end
|
|
||||||
users - [owner]
|
|
||||||
end
|
|
||||||
|
|
||||||
# This method returns unsanitized elements. They must be sanitized before saving to DB
|
|
||||||
def generate_notification_description_elements(object, elements = [])
|
|
||||||
case object
|
|
||||||
when Project
|
|
||||||
path = Rails.application.routes.url_helpers.project_path(object)
|
|
||||||
elements << "#{I18n.t('search.index.project')} <a href='#{path}'>#{object.name}</a>"
|
|
||||||
when Experiment
|
|
||||||
path = Rails.application.routes.url_helpers.my_modules_experiment_path(object)
|
|
||||||
elements << "#{I18n.t('search.index.experiment')} <a href='#{path}'>#{object.name}</a>"
|
|
||||||
generate_notification_description_elements(object.project, elements)
|
|
||||||
when MyModule
|
|
||||||
path = if object.archived?
|
|
||||||
Rails.application.routes.url_helpers.my_modules_experiment_path(object.experiment, view_mode: :archived)
|
|
||||||
else
|
|
||||||
Rails.application.routes.url_helpers.protocols_my_module_path(object)
|
|
||||||
end
|
|
||||||
elements << "#{I18n.t('search.index.module')} <a href='#{path}'>#{object.name}</a>"
|
|
||||||
generate_notification_description_elements(object.experiment, elements)
|
|
||||||
when Protocol
|
|
||||||
if object.in_repository?
|
|
||||||
path = Rails.application.routes.url_helpers.protocols_path(team: object.team.id)
|
|
||||||
elements << "#{I18n.t('search.index.protocol')} <a href='#{path}'>#{object.name}</a>"
|
|
||||||
generate_notification_description_elements(object.team, elements)
|
|
||||||
else
|
|
||||||
generate_notification_description_elements(object.my_module, elements)
|
|
||||||
end
|
|
||||||
when Result
|
|
||||||
generate_notification_description_elements(object.my_module, elements)
|
|
||||||
when Repository
|
|
||||||
path = Rails.application.routes.url_helpers.repository_path(object, team: object.team.id)
|
|
||||||
elements << "#{I18n.t('search.index.repository')} <a href='#{path}'>#{object.name}</a>"
|
|
||||||
generate_notification_description_elements(object.team, elements)
|
|
||||||
when Team
|
|
||||||
path = Rails.application.routes.url_helpers.projects_path(team: object.id)
|
|
||||||
elements << "#{I18n.t('search.index.team')} <a href='#{path}'>#{object.name}</a>"
|
|
||||||
when Report
|
|
||||||
path = Rails.application.routes.url_helpers.reports_path(team: object.team.id)
|
|
||||||
elements << "#{I18n.t('search.index.report')} <a href='#{path}'>#{object.name}</a>"
|
|
||||||
generate_notification_description_elements(object.team, elements)
|
|
||||||
when ProjectFolder
|
|
||||||
generate_notification_description_elements(object.team, elements)
|
|
||||||
end
|
|
||||||
|
|
||||||
elements
|
|
||||||
end
|
|
||||||
|
|
||||||
def notifiable?
|
def notifiable?
|
||||||
type_of.in? ::Extends::NOTIFIABLE_ACTIVITIES
|
NotificationExtends::NOTIFICATIONS_TYPES.key?("#{type_of}_activity".to_sym)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -110,14 +24,4 @@ module GenerateNotificationModel
|
||||||
def generate_notification
|
def generate_notification
|
||||||
CreateNotificationFromActivityJob.perform_later(self) if notifiable?
|
CreateNotificationFromActivityJob.perform_later(self) if notifiable?
|
||||||
end
|
end
|
||||||
|
|
||||||
def notification_type
|
|
||||||
return :recent_changes unless instance_of?(Activity)
|
|
||||||
|
|
||||||
if type_of.in? Activity::ASSIGNMENT_TYPES
|
|
||||||
:assignment
|
|
||||||
else
|
|
||||||
:recent_changes
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class UserNotification < ApplicationRecord
|
|
||||||
include NotificationsHelper
|
|
||||||
|
|
||||||
belongs_to :user, optional: true
|
|
||||||
belongs_to :notification, optional: true
|
|
||||||
|
|
||||||
after_create :send_email
|
|
||||||
|
|
||||||
def self.unseen_notification_count(user)
|
|
||||||
where('user_id = ? AND checked = false', user.id).count
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.seen_by_user(user)
|
|
||||||
where(user: user).where(checked: false).update_all(checked: true)
|
|
||||||
end
|
|
||||||
|
|
||||||
def send_email
|
|
||||||
send_email_notification(user, notification) if user.enabled_notifications_for?(notification.type_of.to_sym, :email)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -5,10 +5,16 @@
|
||||||
# ActivityNotification.with(post: @post).deliver_later(current_user)
|
# ActivityNotification.with(post: @post).deliver_later(current_user)
|
||||||
# ActivityNotification.with(post: @post).deliver(current_user)
|
# ActivityNotification.with(post: @post).deliver(current_user)
|
||||||
|
|
||||||
class ActivityNotification < Noticed::Base
|
class ActivityNotification < BaseNotification
|
||||||
|
include SearchHelper
|
||||||
|
include GlobalActivitiesHelper
|
||||||
|
include InputSanitizeHelper
|
||||||
|
include ActionView::Helpers::TextHelper
|
||||||
|
include ApplicationHelper
|
||||||
|
include ActiveRecord::Sanitization::ClassMethods
|
||||||
|
include Rails.application.routes.url_helpers
|
||||||
# Add your delivery methods
|
# Add your delivery methods
|
||||||
#
|
#
|
||||||
deliver_by :database
|
|
||||||
# deliver_by :email, mailer: "UserMailer"
|
# deliver_by :email, mailer: "UserMailer"
|
||||||
# deliver_by :slack
|
# deliver_by :slack
|
||||||
# deliver_by :custom, class: "MyDeliveryMethod"
|
# deliver_by :custom, class: "MyDeliveryMethod"
|
||||||
|
@ -18,21 +24,35 @@ class ActivityNotification < Noticed::Base
|
||||||
# param :post
|
# param :post
|
||||||
|
|
||||||
def message
|
def message
|
||||||
# if params[:legacy]
|
params[:message] if params[:legacy]
|
||||||
params[:message]
|
|
||||||
#else
|
|
||||||
# new logic
|
|
||||||
# end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def title
|
def title
|
||||||
# if params[:legacy]
|
if params[:legacy]
|
||||||
params[:title]
|
params[:title]
|
||||||
# else
|
else
|
||||||
# new logic
|
generate_activity_content(activity)
|
||||||
# end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def subject
|
||||||
|
activity.subject unless params[:legacy]
|
||||||
end
|
end
|
||||||
# def url
|
# def url
|
||||||
# post_path(params[:post])
|
# post_path(params[:post])
|
||||||
# end
|
# end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def current_team
|
||||||
|
@current_team ||= recipient.teams.find_by(id: recipient.current_team_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def current_user
|
||||||
|
recipient
|
||||||
|
end
|
||||||
|
|
||||||
|
def activity
|
||||||
|
@activity ||= Activity.find_by(id: params[:activity_id])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
29
app/notifications/base_notification.rb
Normal file
29
app/notifications/base_notification.rb
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class BaseNotification < Noticed::Base
|
||||||
|
deliver_by :database, if: :database_notification?
|
||||||
|
|
||||||
|
def self.send_notifications(params, later: false)
|
||||||
|
recipients_class = "Recipients::#{NotificationExtends::NOTIFICATIONS_TYPES[params[:type]][:recipients_module]}".constantize
|
||||||
|
recipients_class.new(params).recipients.each do |recipient|
|
||||||
|
if later
|
||||||
|
with(params).deliver_later(recipient)
|
||||||
|
else
|
||||||
|
with(params).deliver(recipient)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def subject; end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def database_notification?
|
||||||
|
recipient.notifications_settings.dig(notification_subgroup.to_s, 'in_app')
|
||||||
|
end
|
||||||
|
|
||||||
|
def notification_subgroup
|
||||||
|
NotificationExtends::NOTIFICATIONS_GROUPS.values.reduce({}, :merge)
|
||||||
|
.find { |_sg, n| n.include?(params[:type].to_sym) }[0]
|
||||||
|
end
|
||||||
|
end
|
|
@ -5,10 +5,9 @@
|
||||||
# DeliveryNotification.with(post: @post).deliver_later(current_user)
|
# DeliveryNotification.with(post: @post).deliver_later(current_user)
|
||||||
# DeliveryNotification.with(post: @post).deliver(current_user)
|
# DeliveryNotification.with(post: @post).deliver(current_user)
|
||||||
|
|
||||||
class DeliveryNotification < Noticed::Base
|
class DeliveryNotification < BaseNotification
|
||||||
# Add your delivery methods
|
# Add your delivery methods
|
||||||
#
|
#
|
||||||
deliver_by :database
|
|
||||||
# deliver_by :email, mailer: "UserMailer"
|
# deliver_by :email, mailer: "UserMailer"
|
||||||
# deliver_by :slack
|
# deliver_by :slack
|
||||||
# deliver_by :custom, class: "MyDeliveryMethod"
|
# deliver_by :custom, class: "MyDeliveryMethod"
|
||||||
|
|
|
@ -5,10 +5,9 @@
|
||||||
# GeneralNotification.with(post: @post).deliver_later(current_user)
|
# GeneralNotification.with(post: @post).deliver_later(current_user)
|
||||||
# GeneralNotification.with(post: @post).deliver(current_user)
|
# GeneralNotification.with(post: @post).deliver(current_user)
|
||||||
|
|
||||||
class GeneralNotification < Noticed::Base
|
class GeneralNotification < BaseNotification
|
||||||
# Add your delivery methods
|
# Add your delivery methods
|
||||||
#
|
#
|
||||||
deliver_by :database
|
|
||||||
# deliver_by :email, mailer: "UserMailer"
|
# deliver_by :email, mailer: "UserMailer"
|
||||||
# deliver_by :slack
|
# deliver_by :slack
|
||||||
# deliver_by :custom, class: "MyDeliveryMethod"
|
# deliver_by :custom, class: "MyDeliveryMethod"
|
||||||
|
|
13
app/notifications/recipients/assigned_group_recipients.rb
Normal file
13
app/notifications/recipients/assigned_group_recipients.rb
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Recipients::AssignedGroupRecipients
|
||||||
|
def initialize(params)
|
||||||
|
@params = params
|
||||||
|
end
|
||||||
|
|
||||||
|
def recipients
|
||||||
|
activity = Activity.find(@params[:activity_id])
|
||||||
|
project = activity.subject
|
||||||
|
project.team.users.where.not(id: project.user_assignments.where(assigned: 'manually').select(:user_id))
|
||||||
|
end
|
||||||
|
end
|
12
app/notifications/recipients/assigned_recipients.rb
Normal file
12
app/notifications/recipients/assigned_recipients.rb
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Recipients::AssignedRecipients
|
||||||
|
def initialize(params)
|
||||||
|
@params = params
|
||||||
|
end
|
||||||
|
|
||||||
|
def recipients
|
||||||
|
activity = Activity.find(@params[:activity_id])
|
||||||
|
User.where(id: activity.values.dig('message_items', 'user_target', 'id'))
|
||||||
|
end
|
||||||
|
end
|
11
app/notifications/recipients/item_creator_recipients.rb
Normal file
11
app/notifications/recipients/item_creator_recipients.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Recipients::ItemCreatorRecipients
|
||||||
|
def initialize(params)
|
||||||
|
@params = params
|
||||||
|
end
|
||||||
|
|
||||||
|
def recipients
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,31 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Recipients::MyModuleDesignatedRecipients
|
||||||
|
def initialize(params)
|
||||||
|
@params = params
|
||||||
|
end
|
||||||
|
|
||||||
|
def recipients
|
||||||
|
if @params[:activity_id]
|
||||||
|
activity_recipients
|
||||||
|
else
|
||||||
|
# other recipients
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def activity_recipients
|
||||||
|
activity = Activity.find(@params[:activity_id])
|
||||||
|
case activity.subject_type
|
||||||
|
when 'MyModule'
|
||||||
|
users = activity.subject.designated_users
|
||||||
|
when 'Protocol', 'Result'
|
||||||
|
users = activity.subject.my_module.designated_users
|
||||||
|
when 'Step'
|
||||||
|
users = activity.subject.protocol.my_module.designated_users
|
||||||
|
end
|
||||||
|
|
||||||
|
users.where.not(id: activity.owner_id)
|
||||||
|
end
|
||||||
|
end
|
82
app/serializers/notification_serializer.rb
Normal file
82
app/serializers/notification_serializer.rb
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class NotificationSerializer < ActiveModel::Serializer
|
||||||
|
include Rails.application.routes.url_helpers
|
||||||
|
|
||||||
|
attributes :id, :title, :message, :created_at, :read_at, :type, :breadcrumbs, :checked, :today
|
||||||
|
|
||||||
|
def title
|
||||||
|
object.to_notification.title
|
||||||
|
end
|
||||||
|
|
||||||
|
def breadcrumbs
|
||||||
|
subject = object.to_notification.subject
|
||||||
|
generate_breadcrumbs(subject, []) if subject
|
||||||
|
end
|
||||||
|
|
||||||
|
def message
|
||||||
|
object.to_notification.message
|
||||||
|
end
|
||||||
|
|
||||||
|
def created_at
|
||||||
|
I18n.l(object.created_at, format: :full)
|
||||||
|
end
|
||||||
|
|
||||||
|
def today
|
||||||
|
object.created_at.today?
|
||||||
|
end
|
||||||
|
|
||||||
|
def checked
|
||||||
|
object.read_at.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def generate_breadcrumbs(subject, breadcrumbs)
|
||||||
|
case subject
|
||||||
|
when Project
|
||||||
|
parent = subject.team
|
||||||
|
url = project_path(subject)
|
||||||
|
when Experiment
|
||||||
|
parent = subject.project
|
||||||
|
url = experiment_path(subject)
|
||||||
|
when MyModule
|
||||||
|
parent = subject.experiment
|
||||||
|
url = protocols_my_module_path(subject)
|
||||||
|
when Protocol
|
||||||
|
if subject.in_repository?
|
||||||
|
parent = subject.team
|
||||||
|
url = protocol_path(subject)
|
||||||
|
else
|
||||||
|
parent = subject.my_module
|
||||||
|
url = protocols_my_module_path(subject.my_module)
|
||||||
|
end
|
||||||
|
when Result
|
||||||
|
parent = subject.my_module
|
||||||
|
url = my_module_results_path(subject.my_module)
|
||||||
|
when ProjectFolder
|
||||||
|
parent = subject.team
|
||||||
|
url = project_folder_path(subject)
|
||||||
|
when RepositoryBase
|
||||||
|
parent = subject.team
|
||||||
|
url = repository_path(subject)
|
||||||
|
when RepositoryRow
|
||||||
|
parent = subject.team
|
||||||
|
url = repository_path(subject.repository)
|
||||||
|
when LabelTemplate
|
||||||
|
parent = subject.team
|
||||||
|
url = label_template_path(subject)
|
||||||
|
when Team
|
||||||
|
parent = nil
|
||||||
|
url = projects_path
|
||||||
|
end
|
||||||
|
|
||||||
|
breadcrumbs << { name: subject.name, url: url } if subject.name.present?
|
||||||
|
|
||||||
|
if parent
|
||||||
|
generate_breadcrumbs(parent, breadcrumbs)
|
||||||
|
else
|
||||||
|
breadcrumbs.reverse
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,6 +1,10 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class MigrateNotificationToNoticed < ActiveRecord::Migration[7.0]
|
class MigrateNotificationToNoticed < ActiveRecord::Migration[7.0]
|
||||||
|
class UserNotification < ApplicationRecord
|
||||||
|
belongs_to :notification
|
||||||
|
end
|
||||||
|
|
||||||
def up
|
def up
|
||||||
add_column :notifications, :params, :jsonb, default: {}, null: false
|
add_column :notifications, :params, :jsonb, default: {}, null: false
|
||||||
add_column :notifications, :type, :string
|
add_column :notifications, :type, :string
|
||||||
|
|
Loading…
Reference in a new issue