diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 751f3317b..a57c8ff0d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -15,7 +15,7 @@ jobs: - name: Install Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: 3.2.2 + ruby-version: 3.3.0 bundler-cache: true - name: Install Elasticsearch uses: ankane/setup-elasticsearch@v1 diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 000000000..67062932a --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,18 @@ +# Read the Docs configuration file for Sphinx projects +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details +# Required +version: 2 + +# Set the OS, Python version and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.12" + +# Build documentation in the "docs/" directory with Sphinx +sphinx: + configuration: docs/conf.py + +python: + install: + - requirements: docs/requirements.txt diff --git a/.ruby-version b/.ruby-version index be94e6f53..15a279981 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.2.2 +3.3.0 diff --git a/Gemfile b/Gemfile index a12c326fd..bed480c34 100644 --- a/Gemfile +++ b/Gemfile @@ -1,5 +1,5 @@ source 'https://rubygems.org' -ruby '3.2.2' +ruby '3.3.0' gem 'aasm', '~> 5.5.0' gem 'chartkick' @@ -14,11 +14,11 @@ gem 'net-sftp', '~> 4.0' gem 'octicons_helper' gem 'omniauth-orcid', '~> 2.1.1' gem 'omniauth-rails_csrf_protection' -gem 'octokit', '~> 6.0' +gem 'octokit' gem 'pdf-reader', '~> 2.11.0' gem 'pg', '~> 1.4.6' gem 'pagy' -gem 'rails', '7.1.0' +gem 'rails', '7.1.3' gem "importmap-rails" gem "turbo-rails" gem "stimulus-rails" @@ -49,20 +49,19 @@ group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'pry-byebug' gem 'capybara', '~> 3.39' - gem 'factory_bot_rails', '~> 6.2.0' - gem 'rspec-rails', '~> 6.0.3' - gem 'rails-controller-testing', '~> 1.0.5' + gem 'factory_bot_rails', '~> 6.4.2' + gem 'rspec-rails', '~> 6.1.0' gem 'selenium-webdriver' gem 'webmock' end group :test do - gem 'vcr', '~> 6.1', '>= 6.1.0' + gem 'vcr', '~> 6.2' end group :development do # Access an IRB console on exception pages or by using <%= console %> in views - gem 'web-console', '~> 4.2.0' + gem 'web-console', '~> 4.2.1' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' gem 'spring-commands-rspec', group: :development diff --git a/Gemfile.lock b/Gemfile.lock index 2d25a81a5..959569dd9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -4,50 +4,51 @@ GEM Ascii85 (1.1.0) aasm (5.5.0) concurrent-ruby (~> 1.0) - actioncable (7.1.0) - actionpack (= 7.1.0) - activesupport (= 7.1.0) + actioncable (7.1.3) + actionpack (= 7.1.3) + activesupport (= 7.1.3) nio4r (~> 2.0) websocket-driver (>= 0.6.1) zeitwerk (~> 2.6) - actionmailbox (7.1.0) - actionpack (= 7.1.0) - activejob (= 7.1.0) - activerecord (= 7.1.0) - activestorage (= 7.1.0) - activesupport (= 7.1.0) + actionmailbox (7.1.3) + actionpack (= 7.1.3) + activejob (= 7.1.3) + activerecord (= 7.1.3) + activestorage (= 7.1.3) + activesupport (= 7.1.3) mail (>= 2.7.1) net-imap net-pop net-smtp - actionmailer (7.1.0) - actionpack (= 7.1.0) - actionview (= 7.1.0) - activejob (= 7.1.0) - activesupport (= 7.1.0) + actionmailer (7.1.3) + actionpack (= 7.1.3) + actionview (= 7.1.3) + activejob (= 7.1.3) + activesupport (= 7.1.3) mail (~> 2.5, >= 2.5.4) net-imap net-pop net-smtp rails-dom-testing (~> 2.2) - actionpack (7.1.0) - actionview (= 7.1.0) - activesupport (= 7.1.0) + actionpack (7.1.3) + actionview (= 7.1.3) + activesupport (= 7.1.3) nokogiri (>= 1.8.5) + racc rack (>= 2.2.4) rack-session (>= 1.0.1) rack-test (>= 0.6.3) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - actiontext (7.1.0) - actionpack (= 7.1.0) - activerecord (= 7.1.0) - activestorage (= 7.1.0) - activesupport (= 7.1.0) + actiontext (7.1.3) + actionpack (= 7.1.3) + activerecord (= 7.1.3) + activestorage (= 7.1.3) + activesupport (= 7.1.3) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.1.0) - activesupport (= 7.1.0) + actionview (7.1.3) + activesupport (= 7.1.3) builder (~> 3.1) erubi (~> 1.11) rails-dom-testing (~> 2.2) @@ -55,22 +56,22 @@ GEM active_link_to (1.0.5) actionpack addressable - activejob (7.1.0) - activesupport (= 7.1.0) + activejob (7.1.3) + activesupport (= 7.1.3) globalid (>= 0.3.6) - activemodel (7.1.0) - activesupport (= 7.1.0) - activerecord (7.1.0) - activemodel (= 7.1.0) - activesupport (= 7.1.0) + activemodel (7.1.3) + activesupport (= 7.1.3) + activerecord (7.1.3) + activemodel (= 7.1.3) + activesupport (= 7.1.3) timeout (>= 0.4.0) - activestorage (7.1.0) - actionpack (= 7.1.0) - activejob (= 7.1.0) - activerecord (= 7.1.0) - activesupport (= 7.1.0) + activestorage (7.1.3) + actionpack (= 7.1.3) + activejob (= 7.1.3) + activerecord (= 7.1.3) + activesupport (= 7.1.3) marcel (~> 1.0) - activesupport (7.1.0) + activesupport (7.1.3) base64 bigdecimal concurrent-ruby (~> 1.0, >= 1.0.2) @@ -80,13 +81,13 @@ GEM minitest (>= 5.1) mutex_m tzinfo (~> 2.0) - addressable (2.8.5) + addressable (2.8.6) public_suffix (>= 2.0.2, < 6.0) afm (0.2.2) - base64 (0.1.1) - bigdecimal (3.1.4) + base64 (0.2.0) + bigdecimal (3.1.6) bindex (0.8.1) - bootsnap (1.16.0) + bootsnap (1.17.0) msgpack (~> 1.2) builder (3.2.4) byebug (11.1.3) @@ -99,19 +100,19 @@ GEM rack-test (>= 0.6.3) regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) - chartkick (5.0.4) + chartkick (5.0.5) coderay (1.1.3) commonmarker (0.23.10) - concurrent-ruby (1.2.2) + concurrent-ruby (1.2.3) connection_pool (2.4.1) crack (0.4.5) rexml crass (1.0.6) - date (3.3.3) + date (3.3.4) declarative (0.0.20) diff-lcs (1.5.0) dotenv (2.8.1) - drb (2.1.1) + drb (2.2.0) ruby2_keywords elasticsearch (7.13.3) elasticsearch-api (= 7.13.3) @@ -123,10 +124,10 @@ GEM multi_json erubi (1.12.0) execjs (2.9.1) - factory_bot (6.2.1) + factory_bot (6.4.5) activesupport (>= 5.0.0) - factory_bot_rails (6.2.0) - factory_bot (~> 6.2.0) + factory_bot_rails (6.4.3) + factory_bot (~> 6.4) railties (>= 5.0.0) faraday (1.10.3) faraday-em_http (~> 1.0) @@ -154,7 +155,7 @@ GEM ffi (1.16.3) globalid (1.2.1) activesupport (>= 6.1) - google-apis-core (0.11.1) + google-apis-core (0.11.2) addressable (~> 2.5, >= 2.5.1) googleauth (>= 0.16.2, < 2.a) httpclient (>= 2.8.1, < 3.a) @@ -163,7 +164,7 @@ GEM retriable (>= 2.0, < 4.a) rexml webrick - google-apis-drive_v3 (0.44.0) + google-apis-drive_v3 (0.46.0) google-apis-core (>= 0.11.0, < 2.a) google-apis-sheets_v4 (0.26.0) google-apis-core (>= 0.11.0, < 2.a) @@ -181,7 +182,7 @@ GEM signet (~> 0.15) groupdate (6.4.0) activesupport (>= 6.1) - hashdiff (1.0.1) + hashdiff (1.1.0) hashery (2.1.2) hashie (5.0.0) honeybadger (5.2.1) @@ -191,13 +192,14 @@ GEM httpclient (2.8.3) i18n (1.14.1) concurrent-ruby (~> 1.0) - importmap-rails (1.2.1) + importmap-rails (2.0.1) actionpack (>= 6.0.0) + activesupport (>= 6.0.0) railties (>= 6.0.0) - io-console (0.6.0) - irb (1.8.1) + io-console (0.7.2) + irb (1.11.1) rdoc - reline (>= 0.3.8) + reline (>= 0.4.2) issue (1.0.0) openssl rack @@ -208,7 +210,7 @@ GEM libv8-node (18.16.0.0) libv8-node (18.16.0.0-x86_64-darwin) libv8-node (18.16.0.0-x86_64-linux) - loofah (2.21.3) + loofah (2.22.0) crass (~> 1.0.2) nokogiri (>= 1.12.0) mail (2.8.1) @@ -221,35 +223,36 @@ GEM memoist (0.16.2) method_source (1.0.0) mini_mime (1.1.5) - mini_portile2 (2.8.4) + mini_portile2 (2.8.5) mini_racer (0.8.0) libv8-node (~> 18.16.0.0) - minitest (5.20.0) + minitest (5.21.2) msgpack (1.7.2) multi_json (1.15.0) multi_xml (0.6.0) multipart-post (2.3.0) - mutex_m (0.1.2) - net-imap (0.4.0) + mutex_m (0.2.0) + net-imap (0.4.9.1) date net-protocol net-pop (0.1.2) net-protocol - net-protocol (0.2.1) + net-protocol (0.2.2) timeout net-sftp (4.0.0) net-ssh (>= 5.0.0, < 8.0.0) - net-smtp (0.4.0) + net-smtp (0.4.0.1) net-protocol - net-ssh (7.2.0) - newrelic_rpm (9.5.0) - nio4r (2.5.9) - nokogiri (1.15.4) + net-ssh (7.2.1) + newrelic_rpm (9.6.0) + base64 + nio4r (2.7.0) + nokogiri (1.16.2) mini_portile2 (~> 2.8.2) racc (~> 1.4) - nokogiri (1.15.4-x86_64-darwin) + nokogiri (1.16.2-x86_64-darwin) racc (~> 1.4) - nokogiri (1.15.4-x86_64-linux) + nokogiri (1.16.2-x86_64-linux) racc (~> 1.4) oauth2 (2.0.9) faraday (>= 0.17.3, < 3.0) @@ -263,10 +266,10 @@ GEM actionview octicons (= 19.8.0) railties - octokit (6.1.1) + octokit (8.0.0) faraday (>= 1, < 3) sawyer (~> 0.9) - omniauth (2.1.1) + omniauth (2.1.2) hashie (>= 3.4.6) rack (>= 2.2.3) rack-protection @@ -281,7 +284,7 @@ GEM omniauth (~> 2.0) openssl (3.2.0) os (1.1.4) - pagy (6.1.0) + pagy (6.2.0) pdf-reader (2.11.0) Ascii85 (~> 1.0) afm (~> 0.2.1) @@ -295,40 +298,37 @@ GEM pry-byebug (3.10.1) byebug (~> 11.0) pry (>= 0.13, < 0.15) - psych (5.1.0) + psych (5.1.2) stringio - public_suffix (5.0.3) - puma (6.4.0) + public_suffix (5.0.4) + puma (6.4.2) nio4r (~> 2.0) - racc (1.7.1) + racc (1.7.3) rack (2.2.8) - rack-protection (3.1.0) + rack-protection (3.2.0) + base64 (>= 0.1.0) rack (~> 2.2, >= 2.2.4) - rack-session (1.0.1) + rack-session (1.0.2) rack (< 3) rack-test (2.1.0) rack (>= 1.3) rackup (1.0.0) rack (< 3) webrick - rails (7.1.0) - actioncable (= 7.1.0) - actionmailbox (= 7.1.0) - actionmailer (= 7.1.0) - actionpack (= 7.1.0) - actiontext (= 7.1.0) - actionview (= 7.1.0) - activejob (= 7.1.0) - activemodel (= 7.1.0) - activerecord (= 7.1.0) - activestorage (= 7.1.0) - activesupport (= 7.1.0) + rails (7.1.3) + actioncable (= 7.1.3) + actionmailbox (= 7.1.3) + actionmailer (= 7.1.3) + actionpack (= 7.1.3) + actiontext (= 7.1.3) + actionview (= 7.1.3) + activejob (= 7.1.3) + activemodel (= 7.1.3) + activerecord (= 7.1.3) + activestorage (= 7.1.3) + activesupport (= 7.1.3) bundler (>= 1.15.0) - railties (= 7.1.0) - rails-controller-testing (1.0.5) - actionpack (>= 5.0.1.rc1) - actionview (>= 5.0.1.rc1) - activesupport (>= 5.0.1.rc1) + railties (= 7.1.3) rails-dom-testing (2.2.0) activesupport (>= 5.0.0) minitest @@ -336,29 +336,29 @@ GEM rails-html-sanitizer (1.6.0) loofah (~> 2.21) nokogiri (~> 1.14) - railties (7.1.0) - actionpack (= 7.1.0) - activesupport (= 7.1.0) + railties (7.1.3) + actionpack (= 7.1.3) + activesupport (= 7.1.3) irb rackup (>= 1.0.0) rake (>= 12.2) thor (~> 1.0, >= 1.2.2) zeitwerk (~> 2.6) - rake (13.0.6) - rdoc (6.5.0) + rake (13.1.0) + rdoc (6.6.2) psych (>= 4.0.0) - redis (5.0.7) - redis-client (>= 0.9.0) - redis-client (0.17.0) + redis (5.0.8) + redis-client (>= 0.17.0) + redis-client (0.19.1) connection_pool - regexp_parser (2.8.1) - reline (0.3.9) + regexp_parser (2.8.3) + reline (0.4.2) io-console (~> 0.5) representable (3.2.0) declarative (< 0.1.0) trailblazer-option (>= 0.1.1, < 0.2.0) uber (< 0.2.0) - responders (3.1.0) + responders (3.1.1) actionpack (>= 5.2) railties (>= 5.2) retriable (3.1.2) @@ -371,7 +371,7 @@ GEM rspec-mocks (3.12.6) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.12.0) - rspec-rails (6.0.3) + rspec-rails (6.1.0) actionpack (>= 6.1) activesupport (>= 6.1) railties (>= 6.1) @@ -398,10 +398,10 @@ GEM sawyer (0.9.2) addressable (>= 2.3.5) faraday (>= 0.17.3, < 3) - searchkick (5.3.0) + searchkick (5.3.1) activemodel (>= 6.1) hashie - selenium-webdriver (4.13.1) + selenium-webdriver (4.16.0) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) websocket (~> 1.0) @@ -413,7 +413,7 @@ GEM snaky_hash (2.0.1) hashie version_gem (~> 1.1, >= 1.1.1) - spring (4.1.1) + spring (4.1.3) spring-commands-rspec (1.0.4) spring (>= 0.9.1) sprockets (4.2.1) @@ -423,15 +423,15 @@ GEM actionpack (>= 5.2) activesupport (>= 5.2) sprockets (>= 3.0.0) - stimulus-rails (1.2.2) + stimulus-rails (1.3.3) railties (>= 6.0.0) - stringio (3.0.8) - thor (1.2.2) + stringio (3.1.0) + thor (1.3.0) tilt (2.3.0) - timeout (0.4.0) + timeout (0.4.1) trailblazer-option (0.1.2) ttfunk (1.7.0) - turbo-rails (1.4.0) + turbo-rails (1.5.0) actionpack (>= 6.0.0) activejob (>= 6.0.0) railties (>= 6.0.0) @@ -474,7 +474,7 @@ DEPENDENCIES commonmarker (~> 0.23.10) dotenv (~> 2.8.1) elasticsearch (< 7.14) - factory_bot_rails (~> 6.2.0) + factory_bot_rails (~> 6.4.2) google_drive groupdate honeybadger (~> 5.2.0) @@ -486,7 +486,7 @@ DEPENDENCIES net-sftp (~> 4.0) newrelic_rpm octicons_helper - octokit (~> 6.0) + octokit omniauth-orcid (~> 2.1.1) omniauth-rails_csrf_protection pagy @@ -494,11 +494,10 @@ DEPENDENCIES pg (~> 1.4.6) pry-byebug puma - rails (= 7.1.0) - rails-controller-testing (~> 1.0.5) + rails (= 7.1.3) redis (~> 5.0) responders - rspec-rails (~> 6.0.3) + rspec-rails (~> 6.1.0) sanitize (~> 6.0.1) sassc-rails searchkick @@ -509,12 +508,12 @@ DEPENDENCIES stimulus-rails turbo-rails uglifier (= 4.2.0) - vcr (~> 6.1, >= 6.1.0) - web-console (~> 4.2.0) + vcr (~> 6.2) + web-console (~> 4.2.1) webmock RUBY VERSION - ruby 3.2.2p53 + ruby 3.3.0p0 BUNDLED WITH - 2.4.14 + 2.5.4 diff --git a/app/controllers/editors_controller.rb b/app/controllers/editors_controller.rb index aaf0284eb..14fd3cdc5 100644 --- a/app/controllers/editors_controller.rb +++ b/app/controllers/editors_controller.rb @@ -89,7 +89,7 @@ def set_current_editor end def editor_params - params.require(:editor).permit(:max_assignments, :availability_comment, :kind, :title, :first_name, :last_name, :login, :email, :avatar_url, :category_list, :url, :description, { track_ids: [] }) + params.require(:editor).permit(:max_assignments, :availability_comment, :kind, :title, :first_name, :last_name, :buddy_id, :login, :email, :avatar_url, :category_list, :url, :description, { track_ids: [] }) end def profile_params diff --git a/app/helpers/editors_helper.rb b/app/helpers/editors_helper.rb index e328315e8..37c6ee016 100644 --- a/app/helpers/editors_helper.rb +++ b/app/helpers/editors_helper.rb @@ -16,16 +16,29 @@ def display_availability(editor) comment = "#{editor.max_assignments} max." - display_count = editor.max_assignments + display_count = "#{active_assignments} / #{editor.max_assignments}" if editor.availability_comment.present? - display_count = "#{display_count}*" + display_count = "#{active_assignments} / #{editor.max_assignments}*" comment += " : #{editor.availability_comment}" end + "#{display_count}".html_safe end + def availability_remaining(editor) + active_assignments = @assignment_by_editor[editor.id].to_i - @paused_by_editor[editor.id].to_i + availability = editor.max_assignments - active_assignments + + return "#{availability}" + end + + def active_assignments_for_editor(editor) + active_assignments = @assignment_by_editor[editor.id].to_i - @paused_by_editor[editor.id].to_i + return "#{active_assignments}" + end + def in_progress_for_editor(editor) paused_count = @paused_by_editor[editor.id].to_i total_paper_count = @assignment_by_editor[editor.id].to_i diff --git a/app/models/editor.rb b/app/models/editor.rb index 52f78b772..fecb988cc 100644 --- a/app/models/editor.rb +++ b/app/models/editor.rb @@ -14,9 +14,11 @@ class Editor < ApplicationRecord has_and_belongs_to_many :tracks has_many :track_aeics, dependent: :destroy has_many :managed_tracks, through: :track_aeics, source: :track + belongs_to :buddy, class_name: "Editor", optional: true + has_one :buddy_editor, class_name: "Editor", foreign_key: "buddy_id" + normalizes :login, with: -> login { login.gsub(/^@/, "") } before_save :clear_title, if: :board_removed? - before_save :format_login, if: :login_changed? before_save :add_default_avatar_url ACTIVE_EDITOR_STATES = [ @@ -95,10 +97,6 @@ def board_removed? kind_changed? && kind_was == "board" end - def format_login - login.gsub!(/^@/, "") - end - def add_default_avatar_url if avatar_url.blank? && login.present? self.avatar_url = "https://github.com/#{login}.png" diff --git a/app/models/paper.rb b/app/models/paper.rb index 53402b310..daf814e4a 100644 --- a/app/models/paper.rb +++ b/app/models/paper.rb @@ -114,7 +114,9 @@ class Paper < ApplicationRecord 'Makefile', 'HTML', 'CSS', - 'CMake' + 'CMake', + 'Dockerfile', + 'Batchfile' ].freeze default_scope { order(created_at: :desc) } @@ -143,6 +145,7 @@ 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 + validates_format_of :repository_url, with: /\Ahttps?:\/\//i, on: :create, message: "Repository URL is missing the protocol segment (http/https)" validate :check_repository_address, on: :create, unless: Proc.new {|paper| paper.is_a_retraction_notice?} def notify_editors diff --git a/app/views/editors/_form.html.erb b/app/views/editors/_form.html.erb index 59cce7c5f..7474c9689 100644 --- a/app/views/editors/_form.html.erb +++ b/app/views/editors/_form.html.erb @@ -63,6 +63,11 @@ <% end %> +
+ <%= f.label :buddy %> + <%= f.select :buddy_id, Editor.active.sort_by(&:first_name).collect { |e| ["#{e.full_name} (@#{e.login})", e.id] }, { include_blank: true }, { class: "form-control" } %> +
+
<%= f.label :email %> <%= f.text_field :email, class: "form-control" %> diff --git a/app/views/editors/index.html.erb b/app/views/editors/index.html.erb index a4459f6c8..129ef296a 100644 --- a/app/views/editors/index.html.erb +++ b/app/views/editors/index.html.erb @@ -14,15 +14,15 @@ <%= render partial: "aeic_dashboard/menu" %>
- <%= link_to 'New Editor', new_editor_path, class: 'btn action-btn float-right' %> - - - + + + + - + @@ -31,13 +31,15 @@ <%- @active_editors.each do |editor| %> + - - + + + @@ -53,38 +55,4 @@

-
-
-
-
- <%= image_tag "icon_papers.svg", height: "32px" %>

Editors Emeritus

-
-
-
- -
EditorCategoriesNameHandleCategoriesStart date EditingCapacitySpace Invites
<%= link_to editor.full_name, editor %> > - <%= link_to(image_tag(avatar(editor.login), size: "24x24", class: "avatar", title: editor.full_name), github_user_link(editor.login), target: "_blank") %> + <%= link_to(image_tag(avatar(editor.login), size: "32x32", class: "avatar", title: editor.full_name), github_user_link(editor.login), target: "_blank") %> <%= link_to editor.login, editor, title: editor.full_name %> <%= editor.category_list %><%= link_to in_progress_for_editor(editor), "/dashboard/#{editor.login}" %><%= display_availability(editor) %><%= editor.created_at.strftime('%Y-%m-%d') %> class="text-center" title="Limit: <%= editor.max_assignments %>"><%= link_to display_availability(editor), "/dashboard/#{editor.login}" %> class="text-center" title="Limit: <%= editor.max_assignments %>"><%= availability_remaining(editor) %> class="text-center" title="Invites"><%= open_invites_for_editor(editor) %> <%= link_to 'Edit', edit_editor_path(editor), title: 'Edit' %>
- - - - - - - - - - - - <%- @emeritus_editors.each do |editor| %> - - - - - - - - <%- end %> - -
NameLoginCategoriesDescription
<%= link_to editor.full_name, editor %>> - <%= link_to image_tag(avatar(editor.login), size: "24x24", class: "avatar", title: github_user_link(editor.login)), github_user_link(editor.login), target: "_blank" %> - <%= link_to editor.login, "/dashboard/#{editor.login}" %><%= editor.category_list %><%= editor.description.html_safe %><%= link_to 'Edit', edit_editor_path(editor), title: 'Edit' %>
diff --git a/app/views/editors/show.html.erb b/app/views/editors/show.html.erb index 4d48e014a..1eba0e2ef 100644 --- a/app/views/editors/show.html.erb +++ b/app/views/editors/show.html.erb @@ -32,6 +32,15 @@ <%= @editor.email %>

+

+ Buddy: + <% if @editor.buddy.present? %> + <%= "#{@editor.buddy.full_name} (@#{@editor.buddy.login})" %> + <% else %> + None + <% end %> +

+

Avatar url: <%= @editor.avatar_url %> diff --git a/app/views/papers/_vote_summary.html.erb b/app/views/papers/_vote_summary.html.erb index a7ecae948..e838503d0 100644 --- a/app/views/papers/_vote_summary.html.erb +++ b/app/views/papers/_vote_summary.html.erb @@ -9,7 +9,7 @@

- <%= f.text_field :comment, class: "form-control", placeholder: "Include a comment with your vote (required)" %> + <%= f.text_area :comment, class: "form-control", placeholder: "Include a comment with your vote (required)" %>
diff --git a/db/migrate/20240109210521_add_start_date_to_editors.rb b/db/migrate/20240109210521_add_start_date_to_editors.rb new file mode 100644 index 000000000..197d8c93c --- /dev/null +++ b/db/migrate/20240109210521_add_start_date_to_editors.rb @@ -0,0 +1,6 @@ +class AddStartDateToEditors < ActiveRecord::Migration[7.1] + def change + add_column :editors, :buddy_id, :integer + add_index :editors, :buddy_id + end +end diff --git a/db/schema.rb b/db/schema.rb index 2df47d9d8..ed566b3ce 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_06_09_104144) do +ActiveRecord::Schema[7.1].define(version: 2024_01_09_210521) do # These are extensions that must be enabled in order to support this database enable_extension "hstore" enable_extension "plpgsql" @@ -31,6 +31,8 @@ t.integer "user_id" t.string "availability_comment" t.integer "max_assignments", default: 4, null: false + t.integer "buddy_id" + t.index ["buddy_id"], name: "index_editors_on_buddy_id" t.index ["user_id"], name: "index_editors_on_user_id" end @@ -78,7 +80,7 @@ t.index ["token"], name: "index_onboarding_invitations_on_token" end - create_table "papers", force: :cascade do |t| + create_table "papers", id: :serial, force: :cascade do |t| t.string "title" t.string "state" t.string "repository_url" @@ -93,10 +95,10 @@ t.string "doi" t.text "paper_body" t.integer "meta_review_issue_id" - t.string "kind" t.text "authors" t.text "citation_string" t.datetime "accepted_at", precision: nil + t.string "kind" t.integer "editor_id" t.string "reviewers", default: [], array: true t.text "activities" @@ -149,7 +151,7 @@ t.index ["name"], name: "index_tracks_on_name" end - create_table "users", force: :cascade do |t| + create_table "users", id: :serial, force: :cascade do |t| t.string "provider" t.string "uid" t.string "name" diff --git a/docs/conf.py b/docs/conf.py index f628e3c3e..a76237029 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -39,6 +39,7 @@ extensions = [ 'sphinx.ext.mathjax', 'recommonmark', + 'sphinx_rtd_theme', ] # Add any paths that contain templates here, relative to this directory. diff --git a/docs/editing.md b/docs/editing.md index 8a89c90b2..1cea4278f 100644 --- a/docs/editing.md +++ b/docs/editing.md @@ -22,7 +22,7 @@ Editors can flag submissions of questionable scope using the command `@editorial The TEiC assigns an editor (or a volunteering editor self-assigns) with the command `@editorialbot assign @username as editor` in a comment. ```eval_rst -.. note:: Please check in on the [dashboard](https://joss.theoj.org/dashboard/incoming) semi-regularly to see which papers are currently without an editor, and if possible, volunteer to edit papers that look to be in your domain. If you choose to be an editor in the issue thread type the command ``@editorialbot assign @yourhandle as editor`` or simply ``@editorialbot assign me as editor`` +.. note:: Please check in on the `dashboard `_ semi-regularly to see which papers are currently without an editor, and if possible, volunteer to edit papers that look to be in your domain. If you choose to be an editor in the issue thread type the command ``@editorialbot assign @yourhandle as editor`` or simply ``@editorialbot assign me as editor`` ``` ### How papers are assigned to editors @@ -35,11 +35,11 @@ By default, unless an editor volunteers, the Track Editor-in-chief (TEiC) on dut In most cases, the TEiC will ask one or more editors to edit a submission (e.g. `@editor1, @editor 2 - would one of you be willing to edit this submission for JOSS`). If the editor doesn't respond within ~3 working days, the TEiC may assign the paper to the editor regardless. -Editors may also be invited to edit over email when an TEiC runs the command `@editorialbot invite @editor1 as editor`. +Editors may also be invited to edit over email when an TEiC runs the command `@editorialbot invite @editor1 as editor`. ### Finding reviewers -At this point, the handling editor's job is to identify reviewers who have sufficient expertise in the field of software and in the field of the submission. JOSS papers have to have a minimum of two reviewers per submission, except for papers that have previously been peer-reviewed via rOpenSci. In some cases, the editor also might want to formally add themself as one of the reviewers. If the editor feels particularly unsure of the submission, a third (or fourth) reviewer can be recruited. +At this point, the handling editor's job is to identify reviewers who have sufficient expertise in the field of software and in the field of the submission. JOSS papers have to have a minimum of two reviewers per submission, except for papers that have previously been peer-reviewed via rOpenSci. In some cases, the editor also might want to formally add themselves as one of the reviewers. If the editor feels particularly unsure of the submission, a third (or fourth) reviewer can be recruited. To recruit reviewers, the handling editor can mention them in the `PRE-REVIEW` issue with their GitHub handle, ping them on Twitter, or email them. After expressing initial interest, candidate reviewers may need a longer explanation via email. See sample reviewer invitation email, below. @@ -62,7 +62,7 @@ Finding reviewers can be challenging, especially if a submission is outside of y - Ask on social networks: Sometimes asking on Twitter for reviewers can identify good candidates. - Check the work being referenced in the submission: - Authors of software that is being built on might be interested in reviewing the submission. - - Users of the the software that is being submission be interested in reviewing the submission + - Users of the software that is being submission be interested in reviewing the submission - Avoid asking JOSS editors to review: If at all possible, avoid asking JOSS editors to review as they are generally very busy editing their own papers. Once a reviewer accepts, the handling editor runs the command `@editorialbot add @username as reviewer` in the `PRE-REVIEW` issue. Add more reviewers with the same command. @@ -92,7 +92,7 @@ Sometimes you'll need to add a new reviewer once the main review (i.e. post pre- ## After reviewers recommend acceptance -When a submission is ready to be accepted, we ask that the authors issue a new tagged release of the software (if changed), and archive it (on [Zenodo](https://zenodo.org/), [fig**share**](https://figshare.com/), or other). The authors then post the version number and archive DOI in the `REVIEW` issue. The handling editor executes the pre-publication steps, and pings the Track Editor in Chief for final processing. +When a submission is ready to be accepted, we ask that the authors issue a new tagged release of the software (if changed), and archive it (on [Zenodo](https://zenodo.org/), [fig**share**](https://figshare.com/), or other). The authors then post the version number and archive DOI in the `REVIEW` issue. The handling editor executes the pre-publication steps, and pings the Track Editor-in-Chief for final processing. Optionally you can ask EditorialBot to generate a checklist with all the post-review steps running the command: `@editorialbot create post-review checklist` @@ -156,9 +156,14 @@ If a paper has already been reviewed and accepted by rOpenSci or pyOpenSci, the If you believe a submission should be rejected, for example, because it is out of scope for JOSS, then you should: - Ask EditorialBot to flag the submission as potentially out of scope with the command `@editorialbot query scope`. This command adds the `query-scope` label to the issue. -- Mention to the author your reasons for flagging the submission as possibly out of scope, and give them an opportunity to defend their submission. +- Mention to the author your reasons for flagging the submission as possibly out of scope, and _optionally_ give them an opportunity to defend their submission. +- During the scope review process, the editorial team may ask the authors to provide additional information about their submission to assist the editorial board with their decision. - The TEiC will make a final determination of whether a submission is in scope, taking into account the feedback of other editors. +**Scope reviews for resubmissions** + +In the event that an author re-submits a paper to JOSS that was previously rejected, the TEiC will use their discretion to determine: 1) whether a full scope review by the entire editorial team is necessary, 2) if the previous reasons for rejection remain valid, or 3) if there have been enough updates to warrant sending the submission out for review. + ### Voting on papers flagged as potentially out of scope Once per week, an email is sent to all JOSS editors with a summary of the papers that are currently flagged as potentially out of scope. Editors are asked to review these submissions and vote on the JOSS website if they have an opinion about a submission. @@ -246,16 +251,18 @@ Please feel free to ping me (@editorname) if you have any questions/concerns. ``` At this point could you: -- [ ] Make a tagged release of your software, and list the version tag of the archived version here. -- [ ] Archive the reviewed software in Zenodo or a similar service (e.g., figshare, an institutional repository) -- [ ] Check the archival deposit (e.g., in Zenodo) has the correct metadata. This includes the title (should match the paper title) and author list (make sure the list is correct and people who only made a small fix are not on it). You may also add the authors' ORCID. -- [ ] Please list the DOI of the archived version here. +- Make a tagged release of your software, and list the version tag of the archived version here. +- Archive the reviewed software in Zenodo or a similar service (e.g., figshare, an institutional repository) +- Check the archival deposit (e.g., in Zenodo) has the correct metadata. This includes the title (should match the paper title) and author list (make sure the list is correct and people who only made a small fix are not on it). You may also add the authors' ORCID. +- Please list the DOI of the archived version here. I can then move forward with recommending acceptance of the submission. ``` ### Rejection due to out of scope/failing substantial scholarly effort test +(Note that rejections are handled by EiCs and not individual editors). + ``` @authorname - thanks for your submission to JOSS. Unfortunately, after review by the JOSS editorial team we've determined that this submission doesn't meet our [substantial scholarly effort](https://joss.readthedocs.io/en/latest/submitting.html#substantial-scholarly-effort) criterion. @@ -286,7 +293,8 @@ This doesn’t mean that you’re the editor, just that you’ve been suggested **Step 6: The editor finds >= 2 reviewers** -- Use the list of reviewers: type the command `@editorialbot list reviewers` or look at list of reviewers in a Google [spreadsheet](https://docs.google.com/spreadsheets/d/1PAPRJ63yq9aPC1COLjaQp8mHmEq3rZUzwUYxTulyu78/edit?usp=sharing) +- Use the list of reviewers: type the command `@editorialbot list reviewers` or + look at use the [Reviewers Management System](https://reviewers.joss.theoj.org) - If people are in the review list, the editor can @-mention them on the issue to see if they will review: e.g. `@person1 @person2 can you review this submission for JOSS?` - Or solicit reviewers outside the list. Send an email to people describing what JOSS is and asking if they would be interested in reviewing. - If you ask the author to suggest potential reviewers, please be sure to tell the author not to @-tag their suggestions. @@ -294,7 +302,7 @@ This doesn’t mean that you’re the editor, just that you’ve been suggested **Step 7: Editor tells EditorialBot to assign the reviewers to the paper** - Use `@editorialbot add @reviewer as reviewer` -- To add a second reviewer use `@editorialbot add @reviwer2 as reviewer` +- To add a second reviewer use `@editorialbot add @reviewer2 as reviewer` **Step 8: Create the actual review issue** @@ -312,6 +320,7 @@ This doesn’t mean that you’re the editor, just that you’ve been suggested - Make a final check of the paper with `@editorialbot generate pdf` and that all references have DOIs (where appropriate) with `@editorialbot check references`. - If everything looks good, ask the author to make a new release (if possible) of the software being reviewed and deposit a new archive the software with Zenodo/figshare. Update the review thread with this archive DOI: `@editorialbot set 10.5281/zenodo.xxxxxx as archive`. +- Editors can get a checklist of the final steps using the `@editorialbot create post-review checklist` command - Finally, use `@editorialbot recommend-accept` on the review thread to ping the `@openjournals/joss-eics` team letting them know the paper is ready to be accepted. **Step 12: Celebrate publication! Tweet! Thank reviewers! Say thank you on issue.** @@ -322,6 +331,20 @@ This doesn’t mean that you’re the editor, just that you’ve been suggested ## Expectations on JOSS editors +### Editorial load + +Our goal is for editors to handle between 3-4 submissions at any one time, and 8-12 submissions per year. During the trial period for editors (usually the first 90 days), we recommend new editors handle 1-2 submissions as they learn the JOSS editorial system and processes. + +### Completing the trial period + +JOSS has a 90-day trial period for new editors. At the end of the trial, the editor or JOSS editorial board can decide to part ways if either party determines editing for JOSS isn't a good fit for the editor. The most important traits the editorial board will be looking for with new editors are: + +- Demonstrating professionalism in communications with authors, reviewers, and the wider editorial team. +- Editorial responsibility, including [keeping up with their assigned submissions](editing.html#continued-attention-to-assigned-submissions). +- Encouraging good social (software community) practices. For example, thanking reviewers and making them feel like they are part of a team working together. + +If you're struggling with your editorial work, please let your buddy or an EiC know. + ### Responding to editorial assignments As documented above, usually, papers will be assigned to you by one of the TEiCs. We ask that editors do their best to respond in a timely fashion (~ 3 working days) to invites to edit a new submission. @@ -367,16 +390,6 @@ Being on the JOSS editorial team means that there can be a _lot_ of notification ### Things you should do when joining the editorial team -**Unsubscribe from the reviews repository on GitHub** - -When you're added to the editorial team on GitHub, you will almost certainly find yourself subscribed (watching) to the [`joss-reviews`](https://github.com/openjournals/joss-reviews) repository. The first thing you should do is set yourself to 'not watching': - -![Repository notifications settings](https://cloud.githubusercontent.com/assets/4483/20250593/64d7ce48-a9de-11e6-9225-d3dfb3e48e68.png) - -Please note, that by not watching the reviews repository, you will still receive notifications for issues (reviews) where you are `@mentioned`. - -Sometimes another editor might mention you in a review issue (for example to ask you a question). If you've responded and no-longer want to receive messages for that review, you can manually unsubscribe by clicking the button in the right-hand column on the review issue page. - **Curate your GitHub notifications experience** GitHub has extensive documentation on [managing notifications](https://help.github.com/en/articles/managing-your-notifications) which explains when and why different notifications are sent from a repository. @@ -398,3 +411,135 @@ If you use Gmail: For papers that you are already assigned to edit, the dedicated JOSS dashboard aggregates notifications associated with each paper. The dashboard is available at: `https://joss.theoj.org/dashboard/` Another tool you might want to try out is [Octobox](https://octobox.io/). + +## Top tips for JOSS editors + +**Aim for reviewer redundancy** + +If you have 3 people agree to review, take them up on their offer(s), that way if one person drops out, you'll have a backup and won't have to look for more reviewers. Also, when sending invites, try pinging a number of people at the same time rather than doing it one-by-one. + +**Email is a good backup** + +Email is often the most reliable way of contacting people. Whether it's inviting reviewers, following up with reviewers or authors etc., if you've not heard back from someone on GitHub, try emailing them (their email is often available on their GitHub profile page). + +**Default to over-communicating** + +When you take an action (even if it isn't on GitHub), share on the review thready what you're up to. For example, if you're looking for reviewers and are sending emails – leave a note on the review thread saying as much. + +**Use the JOSS Slack** + +There's lots of historical knowledge in our Slack, and it's a great way to get questions answered. + +**Ask reviewers to complete their review in 4-6 weeks** + +We aim for a total submission ... publication time of ~3 months. This means we ideally want reviewers to complete their review in 4-6 weeks (max). + +**Use saved replies on GitHub** + +[Saved replies](https://docs.github.com/en/get-started/writing-on-github/working-with-saved-replies/using-saved-replies) on GitHub can be a huge productivity boost. Try making some using the example messages listed above. + +**Ping reviewers if they’ve not started after 2 weeks** + +If a reviewer hasn't started within 1-2 weeks, you should probably give them a nudge. People often agree to review, and then forget about the review. + +**Learn how to nudge gently, and often** + +One of your jobs as the editor is to ensure the review keeps moving at a reasonable pace. If nothing has happened for a week or so, consider nudging the author or reviewers (depending upon who you're waiting for). A friendly _"👋 reviewer, how are you getting along here"_ can often be sufficient to get things moving again. + +**Check in twice a week** + +Try to check in on your JOSS submissions twice per week, even if only for 5 minutes. Use your dashboard to stay on top of the current status of your submissions (i.e., who was the last person to comment on the thread). + +**Leave feedback on reviewers** + +Leave feedback on the [reviewers application](https://reviewers.joss.theoj.org/) at the end of the review. This helps future editors when they're seeking out good reviewer candidates. + +## Onboarding a new JOSS editor + +All new editors at JOSS have an onboarding call with an Editor-in-Chief. You can use the structure below to make sure you highlight the most important aspects of being an editor. + +**Thing to check before the call** + +- Have they reviewed or published in JOSS before? If not, you'll need to spend significantly more time explaining how the review process works. +- Check on their research background (e.g., what tracks they might edit most actively in). +- Make sure to send them the [editorial guide](https://joss.readthedocs.io/en/latest/editing.html) to read before the call. + +### The onboarding call + +**Preamble/introductions** + +- Welcome! Thank them for their application to join the team. +- Point out that this isn't an interview. Rather, this is an informational call designed to give the candidate the information they need to make an informed decision about editing at JOSS. +- 90-day trial period/try out. Editor or JOSS editorial board can decide to part ways after that period. +- No strict term limits. Some editors have been with us for 7+ years, others do 1-2 years. Most important thing is to be proactive with your editing responsibilities and communicating any issues with the EiCs. +- Confirm with them their level of familiarity with JOSS/our review process. +- Point out that they *do not* need to make a decision on the call today. They are welcome to have a think about joining and get back to us. + +**Share your screen** + +- Visit JOSS (https://joss.theoj.org) +- Pick a recently-published paper (you might want to identify this before the call one that shows off the review process well). +- Show the paper on the JOSS site, and then go to the linked review issue. +- Explain that there are *two* issues per submission – the pre-review issue and the main review issue. + +**The pre-review issue** + +- The 'meeting room for the paper'. Where author meets editor, and reviewers are identified. +- Note that the EiC may have initiated a scope review. The editor should not start editing until this has completed. Also, editors are able to query the scope (as are reviewers) if they think the EiC should have (but didn't). +- Walk them through what is happening in the pre-review issue... +- Editor is invited (likely with GitHub mention but also via email invite (`@editorialbot invite @editor as editor`)) +- Once editor accepts they start looking for reviewers. + +**Finding reviewers** + +- Explain that this is one of the more time-intensive aspects of editing. +- Explain where you can look for editors (your own professional network, asking the authors for recommendations, the [reviewers application](https://reviewers.joss.theoj.org/), similar papers identified by Editorialbot, ) +- Point out that we have a minimum of two reviewers, but if more than that accept (e.g., 3/4 then take them all – this gives you redundancy if one drops out). +- Don't invite only one reviewer at a time! If you do this, it may take many weeks to find two reviewers who accept. Try 3/4/5 invites simultaneously. +- The [sample messages](editing.html#sample-messages-for-authors-and-reviewers) section of the documentation has some example language you can use. + +**The review** + +- Once at least two reviewers are assigned, time to get going! +- Encourage reviewers to complete their review in 4-6 weeks. +- Make sure to check in on the review – if reviewers haven't started after ~1-2 weeks, time to remind them. +- Your role as editor is not to do the review yourself, rather, your job is to ensure that both reviewers give a good review and to facilitate discussion and consensus on what the author needs to do. +- Walk the editor through the various review artifacts: The checklist, comments/questions/discussion between reviewers and author, issues opened on the upstream repository (and cross-linked into the review thread). +- Point editors to the ['top tips'](editing.html#top-tips-for-joss-editors) section of our docs. Much of what makes an editor successful is regular check-ins on the review, and nudging people if nothing is happening. +- Do *not* let a review go multiple weeks without checking in. + +**Wrapping up the review** + +- Once the review is wrapping up, show the candidate the checks that an editor should be doing (reading the paper, suggested edits, asking for an archive etc.) +- Show the `recommend-accept` step which is the formal hand-off between editor and editor-in-chief. +- The [sample messages](editing.html#sample-messages-for-authors-and-reviewers) section of the documentation has a checklist for the last steps of the review (for both authors and editors). + + +**Show them the dashboard on the JOSS site** + +- Point out that this means you *do not* need to stay on top of all of your notifications (the dashboard has the latest information). +- Highlight here that we ask editors to handle 8-12 submissions per year on average. +- ...and that means 3-4 submissions on their desk at any one time (once they have completed their initial probationary period). +- Show them the backlog for a track, and how they are welcome to pick papers from it (ideally oldest first). +- Show them their profile page, and how they can list their tracks there, and also what their availability is. + +**Other important things to highlight** + +- Don't invite other editors as reviewers. We're all busy editing our own papers... +- Please be willing to edit outside of your specialisms. This helps JOSS run smoothly – often we don't have the 'ideal' editor for a submission and someone has to take it. +- Highlight that editors will have a buddy to work with for the first few months, and that it's very common for editors to ask questions in Slack (and people generally respond quickly). +- Scope reviews only work if editors vote! Please respond and vote on the weekly scope review email if you can. The process is private (authors don't know what editors are saying). Detailed comments are really helpful for the EiCs. + +**Wrapping up** + +- Make sure you've highlighted everything in the ['top tips'](editing.html#top-tips-for-joss-editors) section of our docs. +- Reinforce that this is a commitment, and thay regular attention to their submissions is absolutely critical (i.e., check in a couple of times per week). +- Ask if they would like to move forward or would like time to consider the opportunity. +- If they want to move forward, highlight they will receive a small number of invites: One to the JOSS editors GitHub team, a Slack invite, a Google Group invite, and an invite to the JOSS website to fill out their profile. +- Thank them again, and welcome them to the team. + +**Communicate outcome to EiC** + +- Let the EiC know what the outcome was, and ask them to send out the invites to our various systems. +- Work with EiC to identify onboarding buddy. +- Decide who is going to identify the first couple of papers for the editor to work on. diff --git a/docs/editorial_bot.md b/docs/editorial_bot.md index 922da3603..31acd2364 100644 --- a/docs/editorial_bot.md +++ b/docs/editorial_bot.md @@ -10,6 +10,10 @@ The Open Journals' editorial bot or `@editorialbot` on GitHub, is our editorial @editorialbot commands ``` +```eval_rst +.. note:: EditorialBot commands must be placed in the first line of a comment. Other text can be added after the first line with the command. Multiple commands are not allowed in the same comment, only the first one will be interpreted. +``` + ## Author and reviewers commands A subset of the EditorialBot commands are available to authors and reviewers: @@ -298,7 +302,7 @@ JOSS editors-in-chief can withdraw a submission with the following command: @editorialbot check references # Perform checks on the repository -@editorialbot check repository +@editorialbot check repository [from branch ] # Adds a checklist for the reviewer using this command @editorialbot generate my checklist diff --git a/docs/installing.md b/docs/installing.md index 58622a843..482976793 100644 --- a/docs/installing.md +++ b/docs/installing.md @@ -111,7 +111,7 @@ see [the official docs](https://devcenter.heroku.com/articles/heroku-postgresql# Some times you may not want to launch an exact copy of JOSS, but a modified version. This can be especially useful if you're planning to spin up your own platform based on the Open Journals framework. -[NeuroLibre](https://neurolibre.herokuapp.com) is one such example use-case. +[NeuroLibre](https://neurolibre.org/) is one such example use-case. ### Modifying your site configuration diff --git a/docs/reviewer_guidelines.md b/docs/reviewer_guidelines.md index a6f5aa5d8..d20b57eb4 100644 --- a/docs/reviewer_guidelines.md +++ b/docs/reviewer_guidelines.md @@ -21,6 +21,6 @@ The definition of a conflict of Interest in peer review is a circumstance that m As a reviewer (or editor), COIs are your present or previous association with any authors of a submission: recent (past four years) collaborators in funded research or work that is published; and lifetime for the family members, business partners, and thesis student/advisor or mentor. In addition, your recent (past year) association with the same organization of a submitter is a COI, for example, being employed at the same institution. -If you have a conflict of interest with a submission, you should disclose the specific reason to the submissions' editor (or to an EiC if you are an editor, or to the other EiCs if you are an EiC). This may lead to you not being able to review or edit the submission, but some conflicts may be recorded and then waived, and if you think you are able to make an impartial assessment of the work, you should request that the conflict be waived. For example, if you and a submitter were two of 2000 authors of a high energy physics paper but did not actually collaborate. Or if you and a submitter worked together 6 years ago, but due to delays in the publishing industry, a paper from that collaboration with both of you as authors was published 2 year ago. Or if you and a submitter are both employed by the same very large organization but in different units without any knowledge of each other. +If you have a conflict of interest with a submission, you should disclose the specific reason to the submissions' editor (or to an EiC if you are an editor, or to the other EiCs if you are an EiC). This may lead to you not being able to review or edit the submission, but some conflicts may be recorded and then waived, and if you think you are able to make an impartial assessment of the work, you should request that the conflict be waived. For example, if you and a submitter were two of 2000 authors of a high energy physics paper but did not actually collaborate. Or if you and a submitter worked together 6 years ago, but due to delays in the publishing industry, a paper from that collaboration with both of you as authors was published 2 years ago. Or if you and a submitter are both employed by the same very large organization but in different units without any knowledge of each other. Declaring actual, perceived, and potential conflicts of interest is required under professional ethics. If in doubt: ask the editors. diff --git a/docs/submitting.md b/docs/submitting.md index c0577fa56..3b15d25b3 100644 --- a/docs/submitting.md +++ b/docs/submitting.md @@ -390,7 +390,7 @@ Please start headings on the first level. The maximum supported level is 5, but ###### Deeper nesting -Fourth- and fifth-level subsections – like this one and the following heading – are supported by the system; however, their use is discouraged. Use lists instead of forth- and fifth-level headings. +Fourth- and fifth-level subsections – like this one and the following heading – are supported by the system; however, their use is discouraged. Use lists instead of fourth- and fifth-level headings. #### Lists @@ -690,6 +690,6 @@ If you want to learn more details about the review process, take a look at the [ Please write admin@theoj.org with confidential matters such as retraction requests, report of misconduct, and retroactive author name changes. -In case of a name change, the DOI will be unchanged and the paper will be updated without publishing a correction notice or notifying co-authors. +In the event of a name change request, the DOI will remain unchanged, and the paper will be updated without the publication of a correction notice. Please note that because JOSS submissions are managed publicly, updates to papers are visible in the public record (e.g., in the [JOSS papers repository](https://github.com/openjournals/joss-papers) commit history). JOSS will also update Crossref metadata. diff --git a/lib/tasks/stats.rake b/lib/tasks/stats.rake index 513f2a2b7..e988d8843 100644 --- a/lib/tasks/stats.rake +++ b/lib/tasks/stats.rake @@ -55,4 +55,20 @@ namespace :stats do end sheet.save end + + desc "Find most published authors of all time" + task most_published_authors: :environment do + # Find all the users who have published papers + users = User.joins(:papers).where(papers: { state: 'accepted' }).distinct + + # Sort them by the number of papers they've published + users = users.sort_by { |u| u.papers.accepted.count }.reverse + + # Print out the authors with more than one published paper in JOSS, + # with a link to published papers on JOSS (format https://joss.theoj.org/papers/by/username) + # the number of papers they've published, name, and email address, and whether they're an editor + users.select { |u| u.papers.accepted.count > 1 }.each do |u| + puts "#{u.papers.accepted.count},#{u.name},#{u.email},#{u.editor? ? 'editor' : 'non-editor'},(https://joss.theoj.org/papers/by/#{u.github_username})" + end;nil + end end diff --git a/lib/tracks.yml b/lib/tracks.yml index 7867d8f1a..7d87c099a 100644 --- a/lib/tracks.yml +++ b/lib/tracks.yml @@ -10,8 +10,8 @@ tracks: - dfm code: 1 fields: - - General Physics and Astronomy [Physical Sciences] - - Physics and Astronomy (miscellaneous) [Physical Sciences] + - General Astronomy [Physical Sciences] + - Astronomy (miscellaneous) [Physical Sciences] - Astronomy and Astrophysics [Physical Sciences] - Space and Planetary Science [Physical Sciences] bcm: @@ -212,7 +212,9 @@ tracks: - Fluid Flow and Transfer Processes [Physical Sciences] - Process Chemistry and Technology [Physical Sciences] - General Engineering [Physical Sciences] + - General Physics [Physical Sciences] - Engineering (miscellaneous) [Physical Sciences] + - Physics (miscellaneous) [Physical Sciences] - Aerospace Engineering [Physical Sciences] - Automotive Engineering [Physical Sciences] - Civil and Structural Engineering [Physical Sciences] @@ -282,7 +284,7 @@ tracks: name: Data Science, Artificial Intelligence, and Machine Learning short_name: dsais eics: - - gkthiruvathukal + - arfon code: 5 fields: - Artificial Intelligence & Machine Learning (General) [Physical Sciences] diff --git a/spec/controllers/editors_controller_spec.rb b/spec/controllers/editors_controller_spec.rb index 6729b0f14..1e3438ea0 100644 --- a/spec/controllers/editors_controller_spec.rb +++ b/spec/controllers/editors_controller_spec.rb @@ -59,14 +59,14 @@ create(:editor, kind: "pending", track_ids: [track.id]) get :index - expect(assigns(:active_editors)).to eq([current_user.editor, board, editor]) - expect(assigns(:emeritus_editors)).to eq([emeritus]) + expect(@controller.view_assigns["active_editors"]).to eq([current_user.editor, board, editor]) + expect(@controller.view_assigns["emeritus_editors"]).to eq([emeritus]) end it "assigns grouped availability information" do get :index - expect(assigns(:assignment_by_editor)).to be - expect(assigns(:paused_by_editor)).to be + expect(@controller.view_assigns["assignment_by_editor"]).to be + expect(@controller.view_assigns["paused_by_editor"]).to be end end @@ -74,14 +74,14 @@ it "assigns the requested editor as @editor" do editor = create(:editor) get :show, params: {id: editor.to_param} - expect(assigns(:editor)).to eq(editor) + expect(@controller.view_assigns["editor"]).to eq(editor) end end describe "#new" do it "assigns a new editor as @editor" do get :new, params: {} - expect(assigns(:editor)).to be_a_new(Editor) + expect(@controller.view_assigns["editor"]).to be_a_new(Editor) end end @@ -89,7 +89,7 @@ it "assigns the requested editor as @editor" do editor = create(:editor) get :edit, params: {id: editor.to_param} - expect(assigns(:editor)).to eq(editor) + expect(@controller.view_assigns["editor"]).to eq(editor) end end @@ -105,8 +105,8 @@ it "assigns a newly created editor as @editor" do new_editor = build(:editor) post :create, params: {editor: new_editor.attributes.merge(track_ids: new_editor.track_ids)} - expect(assigns(:editor)).to be_a(Editor) - expect(assigns(:editor)).to be_persisted + expect(@controller.view_assigns["editor"]).to be_a(Editor) + expect(@controller.view_assigns["editor"]).to be_persisted end it "redirects to the created editor" do @@ -119,12 +119,15 @@ context "with invalid params" do it "assigns a newly created but unsaved editor as @editor" do post :create, params: {editor: {login: nil}} - expect(assigns(:editor)).to be_a_new(Editor) + expect(@controller.view_assigns["editor"]).to be_a_new(Editor) end - it "re-renders the 'new' template" do + it "goes back to the 'new' form" do + editor_count = Editor.count post :create, params: {editor: {login: nil}} - expect(response).to render_template("new") + + expect(response).to_not be_redirect + expect(Editor.count).to eq(editor_count) end end end @@ -141,7 +144,7 @@ it "assigns the requested editor as @editor" do editor = create(:editor) put :update, params: {id: editor.to_param, editor: {first_name: "Different"}} - expect(assigns(:editor)).to eq(editor) + expect(@controller.view_assigns["editor"]).to eq(editor) end it "redirects to the editor" do @@ -155,13 +158,16 @@ it "assigns the editor as @editor" do editor = create(:editor) put :update, params: {id: editor.to_param, editor: {login: nil}} - expect(assigns(:editor)).to eq(editor) + expect(@controller.view_assigns["editor"]).to eq(editor) end - it "re-renders the 'edit' template" do + it "goes back to the 'edit' form" do editor = create(:editor) + editor_login = editor.login put :update, params: {id: editor.to_param, editor: {login: nil}} - expect(response).to render_template("edit") + + expect(response).to_not be_redirect + expect(editor.reload.login).to eq(editor_login) end end end diff --git a/spec/controllers/papers_controller_spec.rb b/spec/controllers/papers_controller_spec.rb index aa38498cb..77cebdd7e 100644 --- a/spec/controllers/papers_controller_spec.rb +++ b/spec/controllers/papers_controller_spec.rb @@ -327,21 +327,24 @@ request.headers["HTTP_ACCEPT"] = "*/*" get :show, params: {doi: paper.doi} - expect(response).to render_template("papers/show") + expect(response.status).to eq(200) + expect(response).to_not be_redirect end it "should not redirect for URLs with DOIs when asking for HTML response" do paper = create(:accepted_paper) get :show, params: {doi: paper.doi}, format: "html" - expect(response).to render_template("papers/show") + expect(response.status).to eq(200) + expect(response).to_not be_redirect end it "should not redirect for URLs with DOIs when asking for any response" do paper = create(:accepted_paper) get :show, params: {doi: paper.doi} - expect(response).to render_template("papers/show") + expect(response.status).to eq(200) + expect(response).to_not be_redirect end it "should redirect URLs with the paper SHA to the URL with the DOI in the path" do @@ -378,7 +381,8 @@ paper = create(:retracted_paper) get :show, params: {doi: paper.doi}, format: "json" expect(response).to be_successful - expect(response).to render_template("papers/show") + expect(response.body).to include(paper.title) + expect(response.body).to include("retracted") expect(response.media_type).to eq("application/json") expect { JSON.parse(response.body) }.not_to raise_error end @@ -417,14 +421,12 @@ it "returns an Atom feed for #index" do get :index, format: "atom" expect(response).to be_successful - expect(response).to render_template("papers/index") expect(response.media_type).to eq("application/atom+xml") end it "returns a valid Atom feed for #popular (published)" do get :popular, format: "atom" expect(response).to be_successful - expect(response).to render_template("papers/index") expect(response.media_type).to eq("application/atom+xml") end end diff --git a/spec/fixtures/reference-tracks.yml b/spec/fixtures/reference-tracks.yml index e86f8e664..01689ab82 100644 --- a/spec/fixtures/reference-tracks.yml +++ b/spec/fixtures/reference-tracks.yml @@ -225,8 +225,10 @@ - Numerical Analysis [Physical Sciences] - Statistics and Probability [Physical Sciences] - Theoretical Computer Science [Physical Sciences] -- General Physics and Astronomy [Physical Sciences] -- Physics and Astronomy (miscellaneous) [Physical Sciences] +- General Astronomy [Physical Sciences] +- General Physics [Physical Sciences] +- Astronomy (miscellaneous) [Physical Sciences] +- Physics (miscellaneous) [Physical Sciences] - Acoustics and Ultrasonics [Physical Sciences] - Astronomy and Astrophysics [Physical Sciences] - Condensed Matter Physics [Physical Sciences] @@ -353,4 +355,4 @@ - Podiatry [Health Sciences] - Radiological and Ultrasound Technology [Health Sciences] - Respiratory Care [Health Sciences] -- Speech and Hearing [Health Sciences] \ No newline at end of file +- Speech and Hearing [Health Sciences] diff --git a/spec/lib/tracks_spec.rb b/spec/lib/tracks_spec.rb index 23be60970..6708efab4 100644 --- a/spec/lib/tracks_spec.rb +++ b/spec/lib/tracks_spec.rb @@ -8,12 +8,12 @@ end describe "Reference tracks" do - it "should be 344 in total" do - expect(reference_tracks.size).to eq(344) + it "should be 346 in total" do + expect(reference_tracks.size).to eq(346) end it "should be not have any dupes" do - expect(reference_tracks.uniq.size).to eq(344) + expect(reference_tracks.uniq.size).to eq(346) end end @@ -36,7 +36,7 @@ it "should have no dupes" do all_tracks = joss_tracks['tracks'].collect {|k,v| v['fields']}.flatten.uniq - expect(all_tracks.size).to eq(344) + expect(all_tracks.size).to eq(346) end it "should include all of the reference tracks" do @@ -47,4 +47,4 @@ end end end -end \ No newline at end of file +end diff --git a/spec/models/editor_spec.rb b/spec/models/editor_spec.rb index f8c616a17..5db4b5472 100644 --- a/spec/models/editor_spec.rb +++ b/spec/models/editor_spec.rb @@ -71,11 +71,10 @@ end end - describe "#format_login" do - let(:editor) { build(:editor, login: "@somebody") } - - it "removes @'s" do - expect { editor.save }.to change { editor.login }.to "somebody" + describe "normalize login" do + it "removes initial @'s" do + editor = create(:editor, login: "@somebody") + expect(editor.login).to eq("somebody") end end @@ -136,17 +135,35 @@ end describe "#by_track" do - it "should filter by track" do - track_A, track_B = create_list(:track, 2) - editor_A = create(:editor, tracks: [track_A]) - editor_AB = create(:editor, tracks: [track_A, track_B]) - editor_B = create(:editor, tracks: [track_B]) - - track_A_editors = Editor.by_track(track_A.id) - expect(track_A_editors.size).to eq(2) - expect(track_A_editors.include?(editor_A)).to be true - expect(track_A_editors.include?(editor_AB)).to be true + it "should filter by track" do + track_A, track_B = create_list(:track, 2) + editor_A = create(:editor, tracks: [track_A]) + editor_AB = create(:editor, tracks: [track_A, track_B]) + editor_B = create(:editor, tracks: [track_B]) + + track_A_editors = Editor.by_track(track_A.id) + expect(track_A_editors.size).to eq(2) + expect(track_A_editors.include?(editor_A)).to be true + expect(track_A_editors.include?(editor_AB)).to be true + end end + + describe "#status" do + it "should be Retired for emeritus editors" do + emeritus_editor = create(:editor, kind: "emeritus") + + expect(emeritus_editor.status).to eq "Retired" + end + + it "should be Active otherwise" do + board_editor = create(:editor, kind: "board") + topic_editor = create(:editor, kind: "topic") + pending_editor = create(:editor, kind: "pending") + + expect(board_editor.status).to eq "Active" + expect(topic_editor.status).to eq "Active" + expect(pending_editor.status).to eq "Active" + end end describe "#accept!" do diff --git a/spec/models/paper_spec.rb b/spec/models/paper_spec.rb index a9087fd40..cf9d95228 100644 --- a/spec/models/paper_spec.rb +++ b/spec/models/paper_spec.rb @@ -47,14 +47,31 @@ expect(paper.submitting_author).to eq(user) end + it "should have a complete value for repository url" do + params = { title: 'Test paper', + body: 'A test paper description', + repository_url: 'github.com/arfon/fidgit', + software_version: 'v1.0.0', + submitting_author: create(:user), + submission_kind: 'new', + track: create(:track) } + + paper = Paper.create(params) + expect(paper).to_not be_valid + expect(paper.errors.messages[:repository_url].first).to eq("Repository URL is missing the protocol segment (http/https)") + + paper = Paper.create(params.merge(repository_url: 'http://github.com/arfon/fidgit')) + expect(paper).to be_valid + end + it "must have a track assigned on creation if tracks are enabled" do enable_feature(:tracks) do no_track_params = { title: 'Test paper', - body: 'A test paper description', - repository_url: 'http://github.com/arfon/fidgit', - software_version: 'v1.0.0', - submitting_author: create(:user), - submission_kind: 'new' } + body: 'A test paper description', + repository_url: 'http://github.com/arfon/fidgit', + software_version: 'v1.0.0', + submitting_author: create(:user), + submission_kind: 'new' } valid_params = no_track_params.merge track: create(:track) diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index c7eb50e7c..0ad0d1555 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -39,7 +39,7 @@ RSpec.configure do |config| # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures - config.fixture_path = "#{::Rails.root}/spec/fixtures" + config.fixture_paths = ["#{::Rails.root}/spec/fixtures"] # If you're not using ActiveRecord, or you'd prefer not to run each of your # examples within a transaction, remove the following line or assign false