mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-01-30 19:48:18 +08:00
Add project view JSON endpoints [SCI-2728]
This commit is contained in:
parent
f9d771d01a
commit
84428b37c2
11 changed files with 223 additions and 15 deletions
|
@ -3,7 +3,7 @@ AllCops:
|
|||
- "vendor/**/*"
|
||||
- "db/schema.rb"
|
||||
UseCache: false
|
||||
TargetRubyVersion: 2.2
|
||||
TargetRubyVersion: 2.4
|
||||
|
||||
##################### Style ####################################
|
||||
|
||||
|
|
|
@ -382,7 +382,7 @@ class MyModulesController < ApplicationController
|
|||
current_user,
|
||||
@my_module)
|
||||
@assigned_rows = records.assigned_rows
|
||||
@repository_row_count = records.repository_rows.count
|
||||
@repository_row_count = records.repository_rows.length
|
||||
@columns_mappings = records.mappings
|
||||
@repository_rows = records.repository_rows.page(page).per(per_page)
|
||||
render 'repository_rows/index.json'
|
||||
|
|
|
@ -9,7 +9,7 @@ class ProjectsController < ApplicationController
|
|||
notifications reports
|
||||
samples experiment_archive
|
||||
delete_samples samples_index)
|
||||
before_action :load_projects_tree, only: %i(index show samples archive
|
||||
before_action :load_projects_tree, only: %i(show samples archive
|
||||
experiment_archive)
|
||||
before_action :load_archive_vars, only: :archive
|
||||
before_action :check_view_permissions, only: %i(show reports notifications
|
||||
|
@ -25,14 +25,32 @@ class ProjectsController < ApplicationController
|
|||
DELETE_SAMPLES = 'Delete'.freeze
|
||||
|
||||
def index
|
||||
if params[:team]
|
||||
current_team_switch(Team.find_by_id(params[:team]))
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
@current_team = current_team if current_team
|
||||
@current_team ||= current_user.teams.first
|
||||
@projects = ProjectsOverviewService.new(@current_team, current_user)
|
||||
.project_cards(params)
|
||||
end
|
||||
|
||||
format.html do
|
||||
current_team_switch(Team.find_by_id(params[:team])) if params[:team]
|
||||
@teams = current_user.teams
|
||||
|
||||
# New project for create new project modal
|
||||
@project = Project.new
|
||||
load_projects_tree
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def index_dt
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
@current_team = current_team if current_team
|
||||
@current_team ||= current_user.teams.first
|
||||
@projects = ProjectsOverviewService.new(@current_team, current_user)
|
||||
.projects_datatable(params)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def archive
|
||||
|
|
|
@ -23,7 +23,7 @@ class RepositoryRowsController < ApplicationController
|
|||
params,
|
||||
current_user)
|
||||
@assigned_rows = records.assigned_rows
|
||||
@repository_row_count = records.repository_rows.count
|
||||
@repository_row_count = records.repository_rows.length
|
||||
@columns_mappings = records.mappings
|
||||
@repository_rows = records.repository_rows.page(page).per(per_page)
|
||||
end
|
||||
|
|
|
@ -66,6 +66,13 @@ class MyModule < ApplicationRecord
|
|||
has_many :protocols, inverse_of: :my_module, dependent: :destroy
|
||||
|
||||
scope :is_archived, ->(is_archived) { where('archived = ?', is_archived) }
|
||||
scope :active, -> { where(archived: false) }
|
||||
scope :overdue, -> { where('my_modules.due_date < ?', Time.current.utc) }
|
||||
scope :one_day_prior, (lambda do
|
||||
where('my_modules.due_date > ? AND my_modules.due_date < ?',
|
||||
Time.current.utc,
|
||||
Time.current.utc + 1.day)
|
||||
end)
|
||||
|
||||
# A module takes this much space in canvas (x, y) in database
|
||||
WIDTH = 30
|
||||
|
|
|
@ -150,11 +150,7 @@ class Project < ApplicationRecord
|
|||
end
|
||||
|
||||
def user_role(user)
|
||||
unless self.users.include? user
|
||||
return nil
|
||||
end
|
||||
|
||||
return (self.user_projects.select { |up| up.user == user }).first.role
|
||||
user_projects.find_by_user_id(user)&.role
|
||||
end
|
||||
|
||||
def sorted_active_experiments(sort_by = :new)
|
||||
|
|
134
app/services/projects_overview_service.rb
Normal file
134
app/services/projects_overview_service.rb
Normal file
|
@ -0,0 +1,134 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ProjectsOverviewService
|
||||
def initialize(team, user)
|
||||
@team = team
|
||||
@user = user
|
||||
end
|
||||
|
||||
def project_cards(params)
|
||||
records = fetch_records
|
||||
records = records.where(archived: true) if params[:archived] == 'true'
|
||||
records = records.where(archived: false) if params[:archived] == 'false'
|
||||
return records unless params[:sort]
|
||||
case params[:sort]
|
||||
when 'new'
|
||||
records.order(created_at: :desc)
|
||||
when 'old'
|
||||
records.order(:created_at)
|
||||
when 'atoz'
|
||||
records.order(:name)
|
||||
when 'ztoa'
|
||||
records.order(name: :desc)
|
||||
else
|
||||
records
|
||||
end
|
||||
end
|
||||
|
||||
def projects_datatable(params)
|
||||
per_page = params[:length] == '-1' ? 10 : params[:length].to_i
|
||||
page = params[:start] ? (params[:start].to_i / per_page) + 1 : 1
|
||||
records = fetch_dt_records
|
||||
records = records.where(archived: true) if params[:archived] == 'true'
|
||||
records = records.where(archived: false) if params[:archived] == 'false'
|
||||
search_value = params.dig(:search, :value)
|
||||
records = search(records, search_value) if search_value.present?
|
||||
sort(records, params).page(page).per(per_page)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fetch_records
|
||||
due_modules =
|
||||
MyModule.active
|
||||
.overdue
|
||||
.or(MyModule.one_day_prior)
|
||||
.distinct
|
||||
.joins(experiment: :project)
|
||||
.joins('LEFT OUTER JOIN user_projects ON '\
|
||||
'user_projects.project_id = projects.id')
|
||||
.left_outer_joins(:user_my_modules)
|
||||
.where('user_my_modules.user_id = :user_id '\
|
||||
'OR (user_projects.role = 0 '\
|
||||
'AND user_projects.user_id = :user_id)', user_id: @user.id)
|
||||
.select('my_modules.id', 'my_modules.experiment_id')
|
||||
projects = @team.projects.joins(
|
||||
'LEFT OUTER JOIN experiments ON experiments.project_id = projects.id '\
|
||||
'AND experiments.archived = false'
|
||||
).joins(
|
||||
"LEFT OUTER JOIN (#{due_modules.to_sql}) due_modules "\
|
||||
"ON due_modules.experiment_id = experiments.id"
|
||||
).left_outer_joins(:user_projects, :project_comments)
|
||||
|
||||
# Only admins see all projects of the team
|
||||
unless @user.is_admin_of_team?(@team)
|
||||
projects = projects.where(
|
||||
'visibility = 1 OR user_projects.user_id = :user_id', user_id: @user.id
|
||||
)
|
||||
end
|
||||
projects = projects
|
||||
.select('projects.*')
|
||||
.select('COUNT(DISTINCT user_projects.id) AS user_count')
|
||||
.select('COUNT(DISTINCT comments.id) AS comment_count')
|
||||
.select('COUNT(DISTINCT due_modules.id) AS notification_count')
|
||||
.group('projects.id')
|
||||
.limit(1_000_000)
|
||||
Project.from(projects, 'projects')
|
||||
end
|
||||
|
||||
def fetch_dt_records
|
||||
projects = @team.projects.joins(
|
||||
'LEFT OUTER JOIN user_projects ON user_projects.project_id = projects.id'
|
||||
).joins(
|
||||
'LEFT OUTER JOIN experiments ON experiments.project_id = projects.id'\
|
||||
' AND experiments.archived = projects.archived'
|
||||
).joins(
|
||||
'LEFT OUTER JOIN my_modules ON my_modules.experiment_id = experiments.id'\
|
||||
' AND my_modules.archived = projects.archived'
|
||||
)
|
||||
|
||||
# Only admins see all projects of the team
|
||||
unless @user.is_admin_of_team?(@team)
|
||||
projects = projects.where(
|
||||
'visibility = 1 OR user_projects.user_id = :user_id', user_id: @user.id
|
||||
)
|
||||
end
|
||||
projects = projects
|
||||
.select('projects.*')
|
||||
.select('COUNT(DISTINCT user_projects.id) AS user_count')
|
||||
.select('COUNT(DISTINCT experiments.id) AS experiment_count')
|
||||
.select('COUNT(DISTINCT my_modules.id) AS task_count')
|
||||
.group('projects.id')
|
||||
Project.from(projects, 'projects')
|
||||
end
|
||||
|
||||
def search(records, value)
|
||||
records.where_attributes_like('projects.name', value)
|
||||
end
|
||||
|
||||
def sortable_columns
|
||||
{
|
||||
'1' => 'projects.archived',
|
||||
'2' => 'projects.name',
|
||||
'3' => 'projects.created_at',
|
||||
'4' => 'projects.visibility',
|
||||
'5' => 'projects.user_count',
|
||||
'6' => 'projects.experiment_count',
|
||||
'7' => 'projects.task_count'
|
||||
}
|
||||
end
|
||||
|
||||
def sort(records, params)
|
||||
order = params[:order]&.values&.first
|
||||
if order
|
||||
dir = order[:dir] == 'DESC' ? 'DESC' : 'ASC'
|
||||
column_index = order[:column]
|
||||
else
|
||||
dir = 'ASC'
|
||||
column_index = '1'
|
||||
end
|
||||
sort_column = sortable_columns[column_index]
|
||||
sort_column ||= sortable_columns['1']
|
||||
records.order("#{sort_column} #{dir}")
|
||||
end
|
||||
end
|
20
app/views/projects/index.json.jbuilder
Normal file
20
app/views/projects/index.json.jbuilder
Normal file
|
@ -0,0 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
json.data do
|
||||
json.array! @projects do |project|
|
||||
json.set! 'id', project.id
|
||||
json.set! 'archived', project.archived
|
||||
json.set! 'name', project.name
|
||||
json.set! 'created_at', I18n.l(project.created_at, format: :full)
|
||||
json.set! 'visibility', if project.visibility == 'hidden'
|
||||
'<i class="fas fa-eye-slash"></i>' +
|
||||
I18n.t('projects.index.hidden')
|
||||
else
|
||||
'<i class="fas fa-eye"></i>' +
|
||||
I18n.t('projects.index.visible')
|
||||
end
|
||||
json.set! 'user_count', project.user_count
|
||||
json.set! 'notification_count', project.notification_count
|
||||
json.set! 'comment_count', project.comment_count
|
||||
end
|
||||
end
|
28
app/views/projects/index_dt.json.jbuilder
Normal file
28
app/views/projects/index_dt.json.jbuilder
Normal file
|
@ -0,0 +1,28 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
json.recordsTotal @projects.total_count
|
||||
json.recordsFiltered @projects.length
|
||||
json.data do
|
||||
json.array! @projects do |project|
|
||||
json.set! 'DT_RowId', project.id
|
||||
json.set! '1', if project.archived
|
||||
'<i class="fas fa-archive"></i>' +
|
||||
I18n.t('projects.index.archived')
|
||||
else
|
||||
'<i class="fas fa-arrow-alt-circle-right"></i>' +
|
||||
I18n.t('projects.index.active')
|
||||
end
|
||||
json.set! '2', project.name
|
||||
json.set! '3', I18n.l(project.created_at, format: :full)
|
||||
json.set! '4', if project.visibility == 'hidden'
|
||||
'<i class="fas fa-eye-slash"></i>' +
|
||||
I18n.t('projects.index.hidden')
|
||||
else
|
||||
'<i class="fas fa-eye"></i>' +
|
||||
I18n.t('projects.index.visible')
|
||||
end
|
||||
json.set! '5', project.user_count
|
||||
json.set! '6', project.experiment_count
|
||||
json.set! '7', project.task_count
|
||||
end
|
||||
end
|
|
@ -211,6 +211,10 @@ en:
|
|||
index:
|
||||
head_title: "Home"
|
||||
archive: "Archive"
|
||||
archived: "Archived"
|
||||
active: "Active"
|
||||
hidden: "Project members only"
|
||||
visible: "All team members"
|
||||
no_projects:
|
||||
text: "You don't have any active projects."
|
||||
title: "Please create your Project"
|
||||
|
|
|
@ -188,6 +188,7 @@ Rails.application.routes.draw do
|
|||
end
|
||||
|
||||
get 'projects/archive', to: 'projects#archive', as: 'projects_archive'
|
||||
get 'projects/index_dt', to: 'projects#index_dt', as: 'projects_index_dt'
|
||||
|
||||
resources :reports, only: :index
|
||||
get 'reports/datatable', to: 'reports#datatable'
|
||||
|
|
Loading…
Reference in a new issue