Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions app/controllers/names/base_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# frozen_string_literal: true

# Base controller for Names-related controllers.
# Contains shared logic, before_actions, and private methods.
class Names::BaseController < ApplicationController
before_action :set_tutorial

# Authentication and authorization methods
before_action :authenticate_user!, only: %i[observe unobserve observing]
before_action :authenticate_contributor!, only: %i[new create claim]
before_action :authenticate_admin!, only: %i[demote temporary_editable]
before_action :authenticate_curator!, only: %i[unranked unknown_proposal submitted endorsed draft return validate endorse edit_redirect]
before_action :authenticate_owner_or_curator!, only: %i[unclaim new_correspondence transfer_user transfer_user_commit]
before_action :authenticate_can_edit!, only: %i[edit destroy proposed_in not_validly_proposed_in emended_in assigned_in corrigendum_in corrigendum_orphan corrigendum edit_description edit_rank edit_notes edit_etymology autofill_etymology edit_parent]
before_action :authenticate_can_edit_type!, only: %i[edit_type]
before_action :authenticate_can_edit_validated!, only: %i[update edit_links]

# Setup methods
before_action :set_name_and_notifications, only: %i[show]
before_action :set_name, only: %i[edit update destroy network wiki proposed_in not_validly_proposed_in emended_in assigned_in corrigendum_in corrigendum_orphan corrigendum edit_description edit_rank edit_notes edit_etymology edit_links edit_type edit_redirect autofill_etymology edit_parent return validate endorse claim unclaim demote temporary_editable transfer_user transfer_user_commit new_correspondence observe unobserve quality_checks]

private

# Use callbacks to share common setup or constraints between actions
def set_name_and_notifications
if set_name
current_user
&.unseen_notifications
&.where(notifiable: @name)
&.update(seen: true)
end
end

def set_name
@name = Name.find(params[:id])

if @name&.can_view?(current_user, cookies[:reviewer_token])
@register = @name.try(:register)
true
else
render 'hidden'
false
end
end

def set_tutorial
return if params[:tutorial].blank?
@tutorial = Tutorial.find(params[:tutorial])
end

def authenticate_owner_or_curator!
unless current_user.try(:curator?) || @name.user?(current_user)
flash[:alert] = 'User is not the owner of the name'
redirect_to(@name)
end
end

def authenticate_can_edit_validated!
unless @name.can_edit_validated?(current_user)
flash[:alert] = 'User cannot edit this aspect of the name'
redirect_to(@name)
end
end

def authenticate_can_edit_type!
unless @name.can_edit_type?(current_user)
flash[:alert] = 'User cannot edit the nomenclatural type'
redirect_to(@name)
end
end

def authenticate_can_edit!
unless @name.can_edit?(current_user)
flash[:alert] = 'User cannot edit name'
redirect_to(@name)
end
end

# Never trust parameters from the scary internet, only allow the white list through
def name_params
fields = []
if @name.can_edit_validated?(current_user)
fields += %i[
notes ncbi_taxonomy lpsn_url gtdb_accession algaebase_species
algaebase_taxonomy wikispecies_entry
]
unless @name.type?
fields += %i[
nomenclatural_type_type nomenclatural_type_id
nomenclatural_type_entry
]
end
end

if @name.can_edit?(current_user)
fields += %i[
name rank description syllabication syllabication_reviewed
nomenclatural_type_type nomenclatural_type_id nomenclatural_type_entry
etymology_text register genome_strain
] + etymology_pars
end

fields << :redirect if current_user.try(:curator?)

@name_params ||= params.require(:name).permit(*fields.uniq)
end

def etymology_pars
Name.etymology_particles.map do |i|
Name.etymology_fields.map { |j| :"etymology_#{i}_#{j}" }
end.flatten
end

def change_status(fun, success_msg, *extra_opts)
if @name.send(fun, *extra_opts)
flash[:notice] = success_msg
else
flash[:alert] = @name.status_alert
end
redirect_to(@name)
rescue ActiveRecord::RecordInvalid => inv
flash['alert'] =
'An unexpected error occurred while updating the name: ' +
inv.record.errors.map { |e| "#{e.attribute} #{e.message}" }.to_sentence
redirect_to(inv.record)
end

def add_automatic_correspondence(message)
NameCorrespondence.new(
message: message, notify: '0', automatic: true,
user: current_user, name: @name
).save
end
end
55 changes: 55 additions & 0 deletions app/controllers/names/editing_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# frozen_string_literal: true

# Controller for editing actions on names.
class Names::EditingController < Names::BaseController
# GET /names/1/edit
def edit
end

# GET /names/1/edit_description
def edit_description
end

# GET /names/1/edit_notes
def edit_notes
end

# GET /names/1/edit_rank
def edit_rank
end

# GET /names/1/edit_links
def edit_links
end

# GET /names/1/edit_type
def edit_type
unless @name.rank?
flash[:alert] = 'You must define the rank before the type material'
redirect_to(@name)
end
end

# GET /names/1/edit_redirect
def edit_redirect
end

# GET /names/1/autofill_etymology
def autofill_etymology
@name.autofill_etymology
render :edit_etymology
end

# GET /names/1/edit_etymology
def edit_etymology
end

# GET /names/1/edit_parent
def edit_parent
if @name.placement
redirect_to(edit_placement_path(@name.placement))
else
redirect_to(new_placement_path(@name))
end
end
end
144 changes: 144 additions & 0 deletions app/controllers/names/filtering_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# frozen_string_literal: true

# Controller for filtering and listing names by status, user, or type.
class Names::FilteringController < Names::BaseController
# GET /names/user
# GET /names/user?user=abc
def user
@user = current_user
if params[:user] && current_user&.admin?
@user = User.find_by(username: params[:user])
end
params[:status] ||= 'all'
index(where: { created_by: @user })
render :index
end

# GET /names/observing
def observing
user = current_user
if params[:user] && current_user.admin?
user = User.find_by(username: params[:user])
end
@title = 'Names with active alerts'
@status = 'user'
@names = user.observing_names.reverse_order
index
render :index
end

# GET /names/submitted
def submitted
@submitted = true
@status = 'submitted'
index(status: 10)
render :index
end

# GET /names/endorsed
def endorsed
@endorsed = true
@status = 'endorsed'
index(status: 12)
render :index
end

# GET /names/draft
def draft
@draft = true
@status = 'draft'
index(status: 5)
render :index
end

# GET /names/unranked
def unranked
@names = Name.where(rank: nil).order(created_at: :asc)
@names = @names.paginate(page: params[:page], per_page: 30)
end

# GET /names/unknown_proposal
def unknown_proposal
@names = Name.where(proposed_in: nil).where('name LIKE ?', 'Candidatus %').order(created_at: :asc)
@names = @names.paginate(page: params[:page], per_page: 30)
end

# GET /type-genomes
# GET /type-genomes.json
def type_genomes
@names = Name.where(status: 15, nomenclatural_type_type: :Genome)
.reorder(priority_date: :desc, updated_at: :desc)
.paginate(page: params[:page], per_page: 50)
@crumbs = [['Genomes', genomes_path], 'Type']
end

private

# Reuse the index logic from Names::MainController
def index(opts = {})
@user ||= nil
@submitted ||= false
@endorsed ||= false
@draft ||= false
@sort ||= params[:sort] || 'date'
@status ||= params[:status] || 'public'
@status = 'ICNafp' if @status == 'ICN'
@title ||= [
@status == 'all' ? nil : @status.gsub(/^\S/, &:upcase),
'Names',
@user.present? ? "by #{@user.username}" : nil
].compact.join(' ')
opts[:rank] = params[:rank] if params[:rank].present?

opts[:status] ||=
case @status.to_s.downcase
when 'public'; Name.public_status
when 'automated'; 0
when 'seqcode'; 15
when 'icnp'; 20
when 'icnafp'; 25
when 'valid'; Name.valid_status
end

@names ||=
case @sort.to_s.downcase
when 'date'
if opts[:status] == 15
Name.order(validated_at: :desc)
else
Name.order(created_at: :desc)
end
when 'citations'
Name
.left_joins(:publication_names).group(:id)
.order('COUNT(publication_names.id) DESC')
else
@sort = 'alphabetically'
Name.order(name: :asc)
end
@names = @names.where(redirect: nil)
@names = @names.where(status: opts[:status]) if opts[:status]
@names = @names.where(rank: opts[:rank]) if opts[:rank]
@names = @names.where(opts[:where]) if opts[:where]
@names = @names.paginate(page: params[:page], per_page: 30)

@count = @names.count
@count = @count.size if @count.is_a? Hash
@crumbs = [['Names', names_path]]
if @user.present?
bu = "by #{@user.username}"
if @status == 'all'
@crumbs << bu
else
@crumbs << [bu, names_path(user: @user.username)]
@crumbs << @status.gsub(/^\S/, &:upcase)
end
else
if @status == 'public'
@crumbs[0] = 'Names'
else
@crumbs << @status.gsub(/^\S/, &:upcase)
end
end
end
end
Loading
Loading