Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retraction papers #1256

Merged
merged 9 commits into from
Aug 17, 2023
Merged
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
49 changes: 49 additions & 0 deletions app/controllers/dispatch_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,53 @@ def api_deposit
head :forbidden
end
end

def api_retract
if params[:secret] == ENV['BOT_SECRET']
paper = Paper.find_by_doi!(params[:doi])
return head :unprocessable_entity if paper.retracted?

if params[:metadata]
metadata = JSON.parse(Base64.decode64(params[:metadata]))
else
metadata = {}
end

retraction_paper = Paper.new
retraction_paper.doi = metadata[:doi] || "#{paper.doi}R"
retraction_paper.retraction_for_id = paper.id
retraction_paper.title = metadata[:title] || "Retraction notice for: #{paper.title}"
retraction_paper.body = "Retraction notice for: #{paper.title}"
retraction_paper.authors = "Editorial Board"
retraction_paper.repository_url = paper.repository_url
retraction_paper.software_version = paper.software_version
retraction_paper.track_id = paper.track_id
retraction_paper.citation_string = params[:citation_string]
retraction_paper.submission_kind = "new"
retraction_paper.state = "accepted"
retraction_paper.metadata = metadata
retraction_paper.accepted_at = Time.now
retraction_paper.review_issue_id = paper.review_issue_id

if paper.track.nil?
submitting_author = Editor.includes(:user).board.select {|e| e.user.present? }.first.user
else
submitting_author = paper.track.aeics.select {|e| e.user.present? }.first.user
end
submitting_author = User.where(admin: true).first if submitting_author.nil?

retraction_paper.submitting_author = submitting_author

if retraction_paper.save! && retraction_paper.accept!
paper.update(retraction_notice: params[:retraction_notice]) if params[:retraction_notice].present?
paper.retract!
render json: retraction_paper.to_json, status: '201'
else
head :unprocessable_entity
end
else
head :forbidden
end
end

end
32 changes: 27 additions & 5 deletions app/models/paper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ class Paper < ApplicationRecord
optional: true,
foreign_key: "eic_id"

belongs_to :retracted_paper,
class_name: 'Paper',
optional: true,
foreign_key: "retraction_for_id"

has_one :retraction_paper,
class_name: 'Paper',
foreign_key: "retraction_for_id",
inverse_of: :retracted_paper

has_many :invitations
has_many :notes
has_many :votes
Expand Down Expand Up @@ -62,6 +72,10 @@ class Paper < ApplicationRecord
event :withdraw do
transitions to: :withdrawn
end

event :retract do
transitions to: :retracted
end
end

VISIBLE_STATES = [
Expand Down Expand Up @@ -128,14 +142,14 @@ class Paper < ApplicationRecord
validates_presence_of :track_id, on: :create, message: "You must select a valid subject for the paper", if: Proc.new { JournalFeatures.tracks? }
validates :kind, inclusion: { in: Rails.application.settings["paper_types"] }, allow_nil: true
validates :submission_kind, inclusion: { in: SUBMISSION_KINDS, message: "You must select a submission type" }, allow_nil: false
validate :check_repository_address, on: :create
validate :check_repository_address, on: :create, unless: Proc.new {|paper| paper.is_a_retraction_notice?}

def notify_editors
Notifications.submission_email(self).deliver_now
Notifications.submission_email(self).deliver_now unless self.is_a_retraction_notice?
end

def notify_author
Notifications.author_submission_email(self).deliver_now
Notifications.author_submission_email(self).deliver_now unless self.is_a_retraction_notice?
end

# Only index papers that are visible
Expand Down Expand Up @@ -172,6 +186,10 @@ def published?
accepted? || retracted?
end

def is_a_retraction_notice?
retraction_for_id.present?
end

def invite_editor(editor_handle)
return false unless editor = Editor.find_by_login(editor_handle)
Notifications.editor_invite_email(self, editor).deliver_now
Expand Down Expand Up @@ -286,8 +304,12 @@ def archive_doi_url

# A 5-figure integer used to produce the JOSS DOI
def joss_id
id = "%05d" % review_issue_id
"#{setting(:abbreviation).downcase}.#{id}"
if self.is_a_retraction_notice?
return retracted_paper.joss_id + "R"
else
id = "%05d" % review_issue_id
return "#{setting(:abbreviation).downcase}.#{id}"
end
end

# This URL returns the 'DOI optimized' representation of a URL for a paper
Expand Down
56 changes: 2 additions & 54 deletions app/views/papers/_show_published.html.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="container paper-show">
<%= render partial: "shared/retraction_notice" if @paper.retracted? %>
<%= render partial: "shared/retraction_info" %>

<div class="paper-title">
<span class="__dimensions_badge_embed__" data-doi="<%= @paper.doi %>" data-hide-zero-citations="true"></span>
Expand All @@ -22,58 +22,6 @@
<embed src="<%= @paper.pdf_url %>#toolbar=0&navpanes=0&scrollbar=0&statusbar=0&messages=0" type="application/pdf" style="width:100%; height:100%;" />
</object>
</div>

<div class="col-md-3 paper-sidebar">
<div class="btn-group-vertical" role="group" aria-label="...">
<%= link_to @paper.repository_url, class: 'btn paper-btn' do %>
<%= image_tag "gh-icon.svg" %>
Software repository
<% end %>

<%= link_to @paper.review_url, class: 'btn paper-btn' do %>
<%= image_tag "icon_docs.svg" %>
Paper review
<% end %>

<%= link_to @paper.pdf_url, class: 'btn paper-btn' do %>
<%= image_tag "dl-icon.svg" %>
Download paper
<% end %>

<%= link_to @paper.archive_doi_url, class: 'btn paper-btn' do %>
<%= image_tag "hist-icon.svg" %>
Software archive
<% end %>
</div>

<div class="label">Review</div>
<p>Editor: <%= github_link @paper.metadata_editor %> (<%= link_to "all papers", papers_by_editor_path(@paper.metadata_editor) %>)<br>Reviewers: <%= pretty_reviewers(@paper.metadata_reviewers) %></p>

<div class="label">Authors</div>
<p><%= pretty_authors(@paper.metadata_authors) %></p>

<div class="label">Citation</div>
<p id="citationstring" style="padding-bottom: 0px;margin: 0px;"><%= @paper.citation_string %></p>

<div id="bibtex" style="position:absolute;left:-10000px;height:0px;padding:0px;"><%= render partial: "bibtex", locals: { paper: @paper } %></div>
<div style="margin-bottom: 10px;"><%= link_to "Copy citation string".html_safe, "#", class: "clipboard-btn", "data-clipboard-action": "copy", "data-clipboard-target": "#citationstring" %> &middot; <%= link_to "Copy BibTeX".html_safe, "#", class: "clipboard-btn", "data-clipboard-action": "copy", "data-clipboard-target": "#bibtex" %>&nbsp;&nbsp;<%= octicon "paste", height: 16, class: "", "aria-label": "Copy" %></div>

<div class="label">Tags</div>
<p>
<% @paper.author_tags.compact.each do |tag| %>
<span class="badge-lang"><%= link_to tag, papers_by_tag_path(tag: tag) %></span>
<% end %>
</p>
<div class="label">Altmetrics</div>
<div style='padding-bottom: 10px;' data-badge-type='donut' class='altmetric-embed' data-badge-popover='right' data-hide-no-mentions='false' data-doi="<%= @paper.doi %>"></div>

<div class="label">Markdown badge</div>
<p><%= image_tag @paper.status_badge_url %> &nbsp; <a href="#" class="clipboard-btn" data-clipboard-action="copy" data-clipboard-text="<%= @paper.markdown_code %>"><%= octicon "paste", height: 16, class: "", "aria-label": "Copy" %></a></p>

<div class="label">License</div>
<p>Authors of <%= Rails.application.settings['abbreviation'] %> papers retain copyright.</p>
<p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>.</p>
<p><a rel="license" href="http://creativecommons.org/licenses/by/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by/4.0/88x31.png" /></a></p>
</div>
<%= render partial: "sidebar_published" %>
</div>
</div>
73 changes: 73 additions & 0 deletions app/views/papers/_sidebar_published.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<div class="col-md-3 paper-sidebar">
<div class="btn-group-vertical" role="group" aria-label="...">
<% if @paper.is_a_retraction_notice? %>
<%= link_to @paper.pdf_url, class: 'btn paper-btn' do %>
<%= image_tag "dl-icon.svg" %>
Download Retraction Notice
<% end %>

<%= link_to @paper.retracted_paper.seo_url, class: 'btn paper-btn danger' do %>
<%= image_tag "icon_docs.svg" %>
Retracted Paper
<% end %>
<% else %>

<% if @paper.retracted? && @paper.retraction_paper.present? %>
<%= link_to @paper.retraction_paper.seo_url, class: 'btn paper-btn' do %>
<%= image_tag "icon_docs.svg" %>
Retraction notice
<% end %>
<% end %>
<%= link_to @paper.repository_url, class: 'btn paper-btn' do %>
<%= image_tag "gh-icon.svg" %>
Software repository
<% end %>

<%= link_to @paper.review_url, class: 'btn paper-btn' do %>
<%= image_tag "icon_docs.svg" %>
Paper review
<% end %>

<%= link_to @paper.pdf_url, class: 'btn paper-btn' do %>
<%= image_tag "dl-icon.svg" %>
Download paper
<% end %>

<%= link_to @paper.archive_doi_url, class: 'btn paper-btn' do %>
<%= image_tag "hist-icon.svg" %>
Software archive
<% end %>
<% end %>
</div>

<% unless @paper.is_a_retraction_notice? %>
<div class="label">Review</div>
<p>Editor: <%= github_link @paper.metadata_editor %> (<%= link_to "all papers", papers_by_editor_path(@paper.metadata_editor) %>)<br>Reviewers: <%= pretty_reviewers(@paper.metadata_reviewers) %></p>
<% end %>

<div class="label">Authors</div>
<p><%= pretty_authors(@paper.metadata_authors) %></p>

<div class="label">Citation</div>
<p id="citationstring" style="padding-bottom: 0px;margin: 0px;"><%= @paper.citation_string %></p>

<div id="bibtex" style="position:absolute;left:-10000px;height:0px;padding:0px;"><%= render partial: "bibtex", locals: { paper: @paper } %></div>
<div style="margin-bottom: 10px;"><%= link_to "Copy citation string".html_safe, "#", class: "clipboard-btn", "data-clipboard-action": "copy", "data-clipboard-target": "#citationstring" %> &middot; <%= link_to "Copy BibTeX".html_safe, "#", class: "clipboard-btn", "data-clipboard-action": "copy", "data-clipboard-target": "#bibtex" %>&nbsp;&nbsp;<%= octicon "paste", height: 16, class: "", "aria-label": "Copy" %></div>

<div class="label">Tags</div>
<p>
<% @paper.author_tags.compact.each do |tag| %>
<span class="badge-lang"><%= link_to tag, papers_by_tag_path(tag: tag) %></span>
<% end %>
</p>
<div class="label">Altmetrics</div>
<div style='padding-bottom: 10px;' data-badge-type='donut' class='altmetric-embed' data-badge-popover='right' data-hide-no-mentions='false' data-doi="<%= @paper.doi %>"></div>

<div class="label">Markdown badge</div>
<p><%= image_tag @paper.status_badge_url %> &nbsp; <a href="#" class="clipboard-btn" data-clipboard-action="copy" data-clipboard-text="<%= @paper.markdown_code %>"><%= octicon "paste", height: 16, class: "", "aria-label": "Copy" %></a></p>

<div class="label">License</div>
<p>Authors of <%= Rails.application.settings['abbreviation'] %> papers retain copyright.</p>
<p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>.</p>
<p><a rel="license" href="http://creativecommons.org/licenses/by/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by/4.0/88x31.png" /></a></p>
</div>
4 changes: 2 additions & 2 deletions app/views/papers/show.json.jbuilder
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ if @paper.published?
json.editor_orcid @paper.editor.orcid if @paper.editor.orcid
end
json.reviewers @paper.metadata_reviewers
json.languages @paper.language_tags.join(', ')
json.tags @paper.author_tags.join(', ')
json.languages @paper.language_tags
json.tags @paper.author_tags
json.paper_review @paper.review_url
json.meta_review_issue_id @paper.meta_review_issue_id
json.pdf_url @paper.seo_pdf_url
Expand Down
17 changes: 17 additions & 0 deletions app/views/shared/_retraction_info.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<% if @paper.retracted? %>
<div class="alert alert-danger">
<% if @paper.retraction_notice.present? %>
<%= @paper.retraction_notice.html_safe %>
<% elsif @paper.retraction_paper.present? %>
This paper has been retracted, <%= link_to "read details here", @paper.retraction_paper.seo_url %>
<% else %>
This paper has been retracted
<% end %>
</div>
<% end %>

<% if @paper.is_a_retraction_notice? %>
<div class="alert alert-danger">
This paper is a retraction notice for: <%= link_to @paper.retracted_paper.title, @paper.retracted_paper.seo_url %>
</div>
<% end %>
3 changes: 0 additions & 3 deletions app/views/shared/_retraction_notice.html.erb

This file was deleted.

7 changes: 4 additions & 3 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@

doi_prefix_name = Rails.application.settings[:abbreviation].downcase || "joss"

get '/papers/:doi/status.svg', to: "papers#status", format: "svg", constraints: { doi: /10.21105\/#{doi_prefix_name}\.\d{5}/}
get '/papers/:doi', to: "papers#show", constraints: { doi: /10.21105\/#{doi_prefix_name}\.\d{5}/}
get '/papers/:doi.:format', to: "papers#show", constraints: { doi: /10.21105\/#{doi_prefix_name}\.\d{5}/}
get '/papers/:doi/status.svg', to: "papers#status", format: "svg", constraints: { doi: /10.21105\/#{doi_prefix_name}\.\d{5}R?/}
get '/papers/:doi', to: "papers#show", constraints: { doi: /10.21105\/#{doi_prefix_name}\.\d{5}R?/}
get '/papers/:doi.:format', to: "papers#show", constraints: { doi: /10.21105\/#{doi_prefix_name}\.\d{5}R?/}

get '/editor_profile', to: 'editors#profile', as: 'editor_profile'
patch '/update_editor_profile', to: 'editors#update_profile', as: 'update_editor_profile'
Expand All @@ -95,6 +95,7 @@
post '/papers/api_editor_invite', to: 'dispatch#api_editor_invite'
post '/papers/api_start_review', to: 'dispatch#api_start_review'
post '/papers/api_deposit', to: 'dispatch#api_deposit'
post '/papers/api_retract', to: 'dispatch#api_retract'
post '/papers/api_assign_editor', to: 'dispatch#api_assign_editor'
post '/papers/api_update_paper_info', to: 'dispatch#api_update_paper_info'
post '/papers/api_assign_reviewers', to: 'dispatch#api_assign_reviewers'
Expand Down
5 changes: 5 additions & 0 deletions db/migrate/20230609104144_add_retraction_for_id_to_papers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddRetractionForIdToPapers < ActiveRecord::Migration[7.0]
def change
add_reference :papers, :retraction_for, foreign_key: { to_table: :papers }, null: true
end
end
5 changes: 4 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.0].define(version: 2022_06_16_085520) do
ActiveRecord::Schema[7.0].define(version: 2023_06_09_104144) do
# These are extensions that must be enabled in order to support this database
enable_extension "hstore"
enable_extension "plpgsql"
Expand Down Expand Up @@ -110,10 +110,12 @@
t.string "git_branch"
t.bigint "track_id"
t.string "suggested_subject"
t.bigint "retraction_for_id"
t.index ["editor_id"], name: "index_papers_on_editor_id"
t.index ["eic_id"], name: "index_papers_on_eic_id"
t.index ["labels"], name: "index_papers_on_labels", using: :gin
t.index ["last_activity"], name: "index_papers_on_last_activity"
t.index ["retraction_for_id"], name: "index_papers_on_retraction_for_id"
t.index ["reviewers"], name: "index_papers_on_reviewers", using: :gin
t.index ["sha"], name: "index_papers_on_sha"
t.index ["track_id"], name: "index_papers_on_track_id"
Expand Down Expand Up @@ -178,4 +180,5 @@
t.index ["paper_id"], name: "index_votes_on_paper_id"
end

add_foreign_key "papers", "papers", column: "retraction_for_id"
end
Loading