Add main global activities bussiness logic [SCI-3014]

This commit is contained in:
Oleksii Kriuchykhin 2019-02-26 11:01:15 +01:00
parent 3ad6cee766
commit 61147b480c
12 changed files with 197 additions and 13 deletions

View file

@ -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

View 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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View 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

View file

@ -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

View file

@ -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