mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-11-10 17:36:33 +08:00
Add main global activities bussiness logic [SCI-3014]
This commit is contained in:
parent
3ad6cee766
commit
61147b480c
12 changed files with 197 additions and 13 deletions
|
@ -1,18 +1,66 @@
|
|||
class GlobalActivitiesController < ApplicationController
|
||||
before_action :set_placeholder_variables, only: [:index]
|
||||
# frozen_string_literal: true
|
||||
|
||||
class GlobalActivitiesController < ApplicationController
|
||||
def index
|
||||
teams = activity_filters[:teams]
|
||||
teams = current_user.teams if teams.blank?
|
||||
@teams = teams
|
||||
@grouped_activities, more_activities =
|
||||
ActivitiesService.load_activities(teams, activity_filters)
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render json: {
|
||||
activities_html: @grouped_activities,
|
||||
from: @grouped_activities.keys.first,
|
||||
to: @grouped_activities.keys.last,
|
||||
more_activities: more_activities
|
||||
}
|
||||
end
|
||||
format.html do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def search_subjects
|
||||
query = subject_search_params[:query]
|
||||
teams =
|
||||
if subject_search_params[:teams].present?
|
||||
current_user.teams.where(id: subject_search_params[:teams])
|
||||
else
|
||||
current_user.teams
|
||||
end
|
||||
subject_types =
|
||||
if subject_search_params[:subject_types].present?
|
||||
Extends::SEARCHABLE_ACTIVITY_SUBJECT_TYPES &
|
||||
subject_search_params[:subject_types]
|
||||
else
|
||||
Extends::SEARCHABLE_ACTIVITY_SUBJECT_TYPES
|
||||
end
|
||||
results = {}
|
||||
subject_types.each do |subject|
|
||||
matched = subject.constantize
|
||||
.search_by_name(current_user, teams, query)
|
||||
.limit(Constants::SEARCH_LIMIT)
|
||||
.pluck(:id, :name)
|
||||
next if matched.length.zero?
|
||||
results[subject] = matched.map { |pr| { id: pr[0], name: pr[1] } }
|
||||
end
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render json: results
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Whoever will be implementig the filters
|
||||
# will delete this method and before action
|
||||
def set_placeholder_variables
|
||||
@teams = %w(team1 team2 team3)
|
||||
@notification_types = %w(notificationType1 notificationType2 notificationType3)
|
||||
@activity_types = %w(activityType1 activityType2 activityType3)
|
||||
@users = %w(user1 User2 User3 User4)
|
||||
@subjects = %w(Subject1 Subject2 Subject3)
|
||||
def activity_filters
|
||||
params.permit(
|
||||
:from_date, :to_date, types: [], subjects: [], users: [], teams: []
|
||||
)
|
||||
end
|
||||
|
||||
def subject_search_params
|
||||
params.permit(:query, teams: [], subject_types: [])
|
||||
end
|
||||
end
|
||||
|
|
14
app/models/concerns/searchable_by_name_model.rb
Normal file
14
app/models/concerns/searchable_by_name_model.rb
Normal file
|
@ -0,0 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module SearchableByNameModel
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
def self.search_by_name(user, teams = [], query = nil, options = {})
|
||||
return if user.blank? || teams.blank?
|
||||
viewable_by_user(user, teams)
|
||||
.where_attributes_like("#{table_name}.name", query, options)
|
||||
.limit(Constants::SEARCH_LIMIT)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +1,7 @@
|
|||
class Experiment < ApplicationRecord
|
||||
include ArchivableModel
|
||||
include SearchableModel
|
||||
include SearchableByNameModel
|
||||
|
||||
belongs_to :project, inverse_of: :experiments, touch: true, optional: true
|
||||
belongs_to :created_by,
|
||||
|
@ -100,6 +101,10 @@ class Experiment < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def self.viewable_by_user(user, teams)
|
||||
where(project: Project.viewable_by_user(user, teams))
|
||||
end
|
||||
|
||||
def active_modules
|
||||
my_modules.where(archived: false)
|
||||
end
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
class MyModule < ApplicationRecord
|
||||
include ArchivableModel, SearchableModel
|
||||
include ArchivableModel
|
||||
include SearchableModel
|
||||
include SearchableByNameModel
|
||||
|
||||
enum state: Extends::TASKS_STATES
|
||||
|
||||
|
@ -134,6 +136,10 @@ class MyModule < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def self.viewable_by_user(user, teams)
|
||||
where(experiment: Experiment.viewable_by_user(user, teams))
|
||||
end
|
||||
|
||||
# Removes assigned samples from module and connections with other
|
||||
# modules.
|
||||
def archive (current_user)
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
class Project < ApplicationRecord
|
||||
include ArchivableModel, SearchableModel
|
||||
include ArchivableModel
|
||||
include SearchableModel
|
||||
include SearchableByNameModel
|
||||
|
||||
enum visibility: { hidden: 0, visible: 1 }
|
||||
|
||||
|
@ -132,6 +134,20 @@ class Project < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def self.viewable_by_user(user, teams)
|
||||
# Admins see all projects in the team
|
||||
# Member of the projects can view
|
||||
# If project is visible everyone from the team can view it
|
||||
Project.where(team: teams)
|
||||
.left_outer_joins(team: :user_teams)
|
||||
.left_outer_joins(:user_projects)
|
||||
.where('projects.visibility = 1 OR '\
|
||||
'user_projects.user_id = :user_id OR '\
|
||||
'(user_teams.user_id = :user_id AND user_teams.role = 2)',
|
||||
user_id: user.id)
|
||||
.distinct
|
||||
end
|
||||
|
||||
def last_activities(count = Constants::ACTIVITY_AND_NOTIF_SEARCH_LIMIT)
|
||||
activities.order(created_at: :desc).first(count)
|
||||
end
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
class Protocol < ApplicationRecord
|
||||
include SearchableModel
|
||||
include RenamingUtil
|
||||
include SearchableByNameModel
|
||||
extend TinyMceHelper
|
||||
|
||||
after_save :update_linked_children
|
||||
|
@ -196,6 +197,14 @@ class Protocol < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def self.viewable_by_user(user, teams)
|
||||
where(my_module: MyModule.viewable_by_user(user, teams))
|
||||
.or(where(team: teams)
|
||||
.where('protocol_type = 3 OR '\
|
||||
'(protocol_type = 2 AND added_by_id = :user_id)',
|
||||
user_id: user.id))
|
||||
end
|
||||
|
||||
def linked_modules
|
||||
MyModule.joins(:protocols).where('protocols.parent_id = ?', id)
|
||||
end
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
class Repository < ApplicationRecord
|
||||
include SearchableModel
|
||||
include SearchableByNameModel
|
||||
include RepositoryImportParser
|
||||
include Discard::Model
|
||||
|
||||
|
@ -64,6 +65,10 @@ class Repository < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def self.viewable_by_user(_user, teams)
|
||||
where(team: teams)
|
||||
end
|
||||
|
||||
def self.name_like(query)
|
||||
where('repositories.name ILIKE ?', "%#{query}%")
|
||||
end
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
class Result < ApplicationRecord
|
||||
include ArchivableModel, SearchableModel
|
||||
include ArchivableModel
|
||||
include SearchableModel
|
||||
include SearchableByNameModel
|
||||
|
||||
auto_strip_attributes :name, nullify: false
|
||||
validates :user, :my_module, presence: true
|
||||
|
@ -64,6 +66,10 @@ class Result < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def self.viewable_by_user(user, teams)
|
||||
where(my_module: MyModule.viewable_by_user(user, teams))
|
||||
end
|
||||
|
||||
def space_taken
|
||||
is_asset ? result_asset.space_taken : 0
|
||||
end
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
class Step < ApplicationRecord
|
||||
include SearchableModel
|
||||
include SearchableByNameModel
|
||||
|
||||
auto_strip_attributes :name, :description, nullify: false
|
||||
validates :name,
|
||||
|
@ -84,6 +85,10 @@ class Step < ApplicationRecord
|
|||
super()
|
||||
end
|
||||
|
||||
def self.viewable_by_user(user, teams)
|
||||
where(protocol: Protocol.viewable_by_user(user, teams))
|
||||
end
|
||||
|
||||
def can_destroy?
|
||||
!assets.map(&:locked?).any?
|
||||
end
|
||||
|
|
58
app/services/activities_service.rb
Normal file
58
app/services/activities_service.rb
Normal file
|
@ -0,0 +1,58 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ActivitiesService
|
||||
def self.load_activities(team_ids, filters = {})
|
||||
if filters[:subjects].present?
|
||||
first_type, first_ids = filters[:subjects].first
|
||||
query = Activity.where(subject_type: first_type, subject_id: first_ids)
|
||||
if filters[:subjects].count > 1
|
||||
filters[:subjects].except(first_type).each do |type, ids|
|
||||
query = query.or(Activity.where(subject_type: type, subject_id: ids))
|
||||
end
|
||||
end
|
||||
else
|
||||
query = Activity
|
||||
end
|
||||
|
||||
query = query.where(team_id: team_ids)
|
||||
query = query.where(owner_id: filters[:users]) if filters[:users]
|
||||
query = query.where(type_of: filters[:types]) if filters[:types]
|
||||
|
||||
if filters[:from_date] && filters[:to_date]
|
||||
activities = query.where(
|
||||
'created_at >= :from AND created_at <= :to',
|
||||
from: Time.zone.parse(filters[:from_date]).beginning_of_day.utc,
|
||||
to: Time.zone.parse(filters[:to_date]).end_of_day.utc
|
||||
)
|
||||
elsif filters[:from_date] && !filters[:to_date]
|
||||
activities = query.where(
|
||||
'created_at >= :from',
|
||||
from: Time.zone.parse(filters[:from_date]).beginning_of_day.utc
|
||||
)
|
||||
else
|
||||
activities = query
|
||||
end
|
||||
|
||||
activities = activities.order(created_at: :desc)
|
||||
.limit(Constants::ACTIVITY_AND_NOTIF_SEARCH_LIMIT)
|
||||
loaded = activities.length
|
||||
results = activities.group_by do |activity|
|
||||
Time.zone.at(activity.created_at).to_date.to_s
|
||||
end
|
||||
|
||||
return results if loaded < Constants::ACTIVITY_AND_NOTIF_SEARCH_LIMIT
|
||||
|
||||
last_date = results.keys.last
|
||||
activities = query.where(
|
||||
'created_at >= :from AND created_at <= :to',
|
||||
from: Time.zone.parse(last_date).beginning_of_day.utc,
|
||||
to: Time.zone.parse(last_date).end_of_day.utc
|
||||
)
|
||||
more_left = query.where(
|
||||
'created_at > :from',
|
||||
from: Time.zone.parse(last_date).end_of_day.utc
|
||||
).exists?
|
||||
results[last_date] = activities.to_a
|
||||
[results, more_left]
|
||||
end
|
||||
end
|
|
@ -83,4 +83,12 @@ class Extends
|
|||
# Hash used for mapping file extensions to custom font awesome icon classes,
|
||||
# 'extension' => 'fa class'
|
||||
FILE_FA_ICON_MAPPINGS = {}
|
||||
|
||||
ACTIVITY_SUBJECT_TYPES = %w(
|
||||
Team Repository Project Experiment MyModule Result Protocol Step
|
||||
)
|
||||
|
||||
SEARCHABLE_ACTIVITY_SUBJECT_TYPES = %w(
|
||||
Repository Project Experiment MyModule Result Protocol Step
|
||||
)
|
||||
end
|
||||
|
|
|
@ -649,6 +649,10 @@ Rails.application.routes.draw do
|
|||
end
|
||||
|
||||
resources :global_activities, only: [:index]
|
||||
namespace :global_activities do
|
||||
get 'search_subjects', to: 'global_activities#search_subjects',
|
||||
as: 'search_subjects'
|
||||
end
|
||||
|
||||
constraints WopiSubdomain do
|
||||
# Office integration
|
||||
|
|
Loading…
Reference in a new issue