diff --git a/app/controllers/change_requests_controller.rb b/app/controllers/change_requests_controller.rb index d46738a251..49439ea37c 100644 --- a/app/controllers/change_requests_controller.rb +++ b/app/controllers/change_requests_controller.rb @@ -5,11 +5,11 @@ class ChangeRequestsController < ApplicationController before_action :set_common_instance_variables, except: [:create] def node_obsoletion - respond_to :js + respond_to :turbo_stream end def node_rename - respond_to :js + respond_to :turbo_stream end def create_synonym @@ -27,7 +27,12 @@ def create @issue = IssueCreatorService.call(params) flash.now.notice = helpers.change_request_success_message if @issue['id'].present? - respond_to :js + # TODO: remove format.js from this block, and the create.js.erb file after the create_synonym and + # remove_synonym actions are converted from Rails UJS to Turbo Streams. + respond_to do |format| + format.js + format.turbo_stream + end end private @@ -49,17 +54,20 @@ def generate_curie(ont_acronym, concept_id) def require_login return unless session[:user].blank? - # TODO: Can this implementation be improved? For discussion: - # https://stackoverflow.com/a/18681807 - # https://stackoverflow.com/a/10607511 - # https://stackoverflow.com/a/51275445 - render js: "window.location.href='#{login_index_path}'" + # TODO: remove format.js handling after the create_synonym and remove_synonym actions are converted + # from Rails UJS to Turbo Streams. + respond_to do |format| + format.turbo_stream { redirect_to login_index_path } + format.js { render js: "window.location.href='#{login_index_path}'", status: :found } + end end def set_common_instance_variables @concept_label = params[:concept_label] @concept_id = params[:concept_id] @ont_acronym = params[:ont_acronym] - @username = session[:user].username + @user = LinkedData::Client::Models::User.get( + session[:user].id, include: 'username,githubId,orcidId', display_links: 'false', display_context: 'false' + ) end end diff --git a/app/javascript/controllers/change_requests_controller.js b/app/javascript/controllers/change_requests_controller.js new file mode 100644 index 0000000000..d573ad58fb --- /dev/null +++ b/app/javascript/controllers/change_requests_controller.js @@ -0,0 +1,10 @@ +import { Controller } from "@hotwired/stimulus" + +// Connects to data-controller="change-requests" +export default class extends Controller { + static targets = [ 'addProposalForm' ] + + clearProposalForm() { + this.addProposalFormTarget.innerHTML = ''; + } +} diff --git a/app/javascript/controllers/index.js b/app/javascript/controllers/index.js index 273754277c..9d909e52f9 100644 --- a/app/javascript/controllers/index.js +++ b/app/javascript/controllers/index.js @@ -4,6 +4,9 @@ import { application } from "./application" +import ChangeRequestsController from "./change_requests_controller" +application.register("change-requests", ChangeRequestsController) + import LanguageChangeController from "./language_change_controller" application.register("language-change", LanguageChangeController) diff --git a/app/lib/kgcl/renderers/issue_content.rb b/app/lib/kgcl/renderers/issue_content.rb new file mode 100644 index 0000000000..597e81d23c --- /dev/null +++ b/app/lib/kgcl/renderers/issue_content.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +module KGCL + module Renderers + # Base class for generating GitHub issue content for ontology change requests + class IssueContent + attr_reader :params + + def initialize(params) + @params = params + end + + def render + tr = KGCL::TemplateRenderer.new( + title_template: title_template, + body_template: body_template, + bind_klass: self + ) + tr.render + end + + def concept_id + @params[:concept_id] + end + + def concept_label + @params[:concept_label] + end + + def curie + @params[:curie] + end + + def github_id + @params[:github_id] + end + + def orcid_id + @params[:orcid_id] + end + + def username + @params[:username] + end + + # These methods should be defined in subclasses to provide unique templates + def title_template + raise NotImplementedError, 'Subclasses must define a title_template' + end + + def body_template + raise NotImplementedError, 'Subclasses must define a body_template' + end + end + end +end diff --git a/app/lib/kgcl/renderers/new_synonym_content.rb b/app/lib/kgcl/renderers/new_synonym_content.rb index d8da90f477..de149adafe 100644 --- a/app/lib/kgcl/renderers/new_synonym_content.rb +++ b/app/lib/kgcl/renderers/new_synonym_content.rb @@ -12,38 +12,11 @@ module Renderers # # @see https://github.com/INCATools/kgcl KGCL documentation # - class NewSynonymContent - attr_reader :params - - def initialize(params) - @params = params - end - - def render - tr = KGCL::TemplateRenderer.new( - title_template: 'new_synonym_title.erb', - body_template: 'new_synonym_body.erb', - bind_klass: self - ) - tr.render - end - + class NewSynonymContent < IssueContent def comment @params[:create_synonym][:comment] end - def concept_id - @params[:concept_id] - end - - def concept_label - @params[:concept_label] - end - - def curie - @params[:curie] - end - def get_binding binding end @@ -56,8 +29,12 @@ def synonym_label @params[:create_synonym][:preferred_label] end - def username - @params[:username] + def title_template + 'new_synonym_title.erb' + end + + def body_template + 'new_synonym_body.erb' end end end diff --git a/app/lib/kgcl/renderers/node_obsoletion_content.rb b/app/lib/kgcl/renderers/node_obsoletion_content.rb index cf51fbc0de..ca0b8fe3fb 100644 --- a/app/lib/kgcl/renderers/node_obsoletion_content.rb +++ b/app/lib/kgcl/renderers/node_obsoletion_content.rb @@ -9,44 +9,21 @@ module Renderers # # @see https://github.com/INCATools/kgcl KGCL documentation # - class NodeObsoletionContent - attr_reader :params - - def initialize(params) - @params = params - end - - def render - tr = KGCL::TemplateRenderer.new( - title_template: 'node_obsoletion_title.erb', - body_template: 'node_obsoletion_body.erb', - bind_klass: self - ) - tr.render - end - + class NodeObsoletionContent < IssueContent def comment @params[:node_obsoletion][:comment] end - def concept_id - @params[:concept_id] - end - - def concept_label - @params[:concept_label] - end - - def curie - @params[:curie] - end - def get_binding binding end - def username - @params[:username] + def title_template + 'node_obsoletion_title.erb' + end + + def body_template + 'node_obsoletion_body.erb' end end end diff --git a/app/lib/kgcl/renderers/node_rename_content.rb b/app/lib/kgcl/renderers/node_rename_content.rb index c2dfd4c97a..9315284f89 100644 --- a/app/lib/kgcl/renderers/node_rename_content.rb +++ b/app/lib/kgcl/renderers/node_rename_content.rb @@ -9,34 +9,11 @@ module Renderers # # @see https://github.com/INCATools/kgcl KGCL documentation # - class NodeRenameContent - attr_reader :params - - def initialize(params) - @params = params - end - - def render - tr = KGCL::TemplateRenderer.new( - title_template: 'node_rename_title.erb', - body_template: 'node_rename_body.erb', - bind_klass: self - ) - tr.render - end - + class NodeRenameContent < IssueContent def comment @params[:node_rename][:comment] end - def concept_label - @params[:concept_label] - end - - def curie - @params[:curie] - end - def get_binding binding end @@ -45,8 +22,12 @@ def new_concept_label @params[:node_rename][:new_preferred_name] end - def username - @params[:username] + def title_template + 'node_rename_title.erb' + end + + def body_template + 'node_rename_body.erb' end end end diff --git a/app/lib/kgcl/renderers/remove_synonym_content.rb b/app/lib/kgcl/renderers/remove_synonym_content.rb index f8ae83b003..84d9e4da23 100644 --- a/app/lib/kgcl/renderers/remove_synonym_content.rb +++ b/app/lib/kgcl/renderers/remove_synonym_content.rb @@ -11,34 +11,11 @@ module Renderers # # @see https://github.com/INCATools/kgcl KGCL documentation # - class RemoveSynonymContent - attr_reader :params - - def initialize(params) - @params = params - end - - def render - tr = KGCL::TemplateRenderer.new( - title_template: 'remove_synonym_title.erb', - body_template: 'remove_synonym_body.erb', - bind_klass: self - ) - tr.render - end - + class RemoveSynonymContent < IssueContent def comment @params[:remove_synonym][:comment] end - def concept_label - @params[:concept_label] - end - - def curie - @params[:curie] - end - def get_binding binding end @@ -47,8 +24,12 @@ def synonym_label @params[:remove_synonym][:synonym] end - def username - @params[:username] + def title_template + 'remove_synonym_title.erb' + end + + def body_template + 'remove_synonym_body.erb' end end end diff --git a/app/lib/kgcl/templates/footer.erb b/app/lib/kgcl/templates/footer.erb new file mode 100644 index 0000000000..e6aaf8d3f9 --- /dev/null +++ b/app/lib/kgcl/templates/footer.erb @@ -0,0 +1,9 @@ +**Comment:** <%= comment %> + +<% if github_id.present? %> +Proposal generated by: @<%= github_id %> +<% else %> +Proposal generated by: BioPortal user '<%= username %>' +<% end %> + +ORCID: <%= orcid_id %> \ No newline at end of file diff --git a/app/lib/kgcl/templates/new_synonym_body.erb b/app/lib/kgcl/templates/new_synonym_body.erb index b36f06ed68..ddd9d7d472 100644 --- a/app/lib/kgcl/templates/new_synonym_body.erb +++ b/app/lib/kgcl/templates/new_synonym_body.erb @@ -4,6 +4,5 @@ --- -Comment: <%= comment %> - -This request comes from BioPortal user: <%= username %> \ No newline at end of file +<% footer_template = File.read("#{Rails.root}/app/lib/kgcl/templates/footer.erb") %> +<%= ERB.new(footer_template, trim_mode: '<>', eoutvar: 'footer').result(binding) %> \ No newline at end of file diff --git a/app/lib/kgcl/templates/node_obsoletion_body.erb b/app/lib/kgcl/templates/node_obsoletion_body.erb index e293952193..7702614461 100644 --- a/app/lib/kgcl/templates/node_obsoletion_body.erb +++ b/app/lib/kgcl/templates/node_obsoletion_body.erb @@ -4,6 +4,5 @@ --- -Comment: <%= comment %> - -This request comes from BioPortal user: <%= username %> \ No newline at end of file +<% footer_template = File.read("#{Rails.root}/app/lib/kgcl/templates/footer.erb") %> +<%= ERB.new(footer_template, trim_mode: '<>', eoutvar: 'footer').result(binding) %> \ No newline at end of file diff --git a/app/lib/kgcl/templates/node_rename_body.erb b/app/lib/kgcl/templates/node_rename_body.erb index f84a22c3fb..c748d11369 100644 --- a/app/lib/kgcl/templates/node_rename_body.erb +++ b/app/lib/kgcl/templates/node_rename_body.erb @@ -4,6 +4,5 @@ --- -Comment: <%= comment %> - -This request comes from BioPortal user: <%= username %> \ No newline at end of file +<% footer_template = File.read("#{Rails.root}/app/lib/kgcl/templates/footer.erb") %> +<%= ERB.new(footer_template, trim_mode: '<>', eoutvar: 'footer').result(binding) %> \ No newline at end of file diff --git a/app/lib/kgcl/templates/remove_synonym_body.erb b/app/lib/kgcl/templates/remove_synonym_body.erb index c8a9b49d37..bf730ed590 100644 --- a/app/lib/kgcl/templates/remove_synonym_body.erb +++ b/app/lib/kgcl/templates/remove_synonym_body.erb @@ -4,6 +4,5 @@ --- -Comment: <%= comment %> - -This request comes from BioPortal user: <%= username %> \ No newline at end of file +<% footer_template = File.read("#{Rails.root}/app/lib/kgcl/templates/footer.erb") %> +<%= ERB.new(footer_template, trim_mode: '<>', eoutvar: 'footer').result(binding) %> \ No newline at end of file diff --git a/app/views/change_requests/_create_synonym.html.haml b/app/views/change_requests/_create_synonym.html.haml index 7c00f40bdf..ddb5b32fda 100644 --- a/app/views/change_requests/_create_synonym.html.haml +++ b/app/views/change_requests/_create_synonym.html.haml @@ -5,8 +5,10 @@ = form_with scope: :create_synonym, url: change_requests_path, local: false do |f| = hidden_field_tag 'concept_id', @concept_id = hidden_field_tag 'concept_label', @concept_label + = hidden_field_tag 'github_id', @user.githubId = hidden_field_tag 'ont_acronym', @ont_acronym - = hidden_field_tag 'username', @username + = hidden_field_tag 'orcid_id', @user.orcidId + = hidden_field_tag 'username', @user.username = hidden_field_tag 'operation', KGCL::Operations::NEW_SYNONYM %div{class: 'modal-body'} %div.mb-3 diff --git a/app/views/change_requests/_node_obsoletion.html.haml b/app/views/change_requests/_node_obsoletion.html.haml index 80f98f4a9b..182a0e2fac 100644 --- a/app/views/change_requests/_node_obsoletion.html.haml +++ b/app/views/change_requests/_node_obsoletion.html.haml @@ -1,12 +1,15 @@ -= form_with scope: :node_obsoletion, url: change_requests_path, local: false, class: 'mb-5' do |f| += form_with scope: :node_obsoletion, url: change_requests_path, data: {turbo: true}, class: 'mb-5' do |f| = hidden_field_tag 'concept_id', @concept_id = hidden_field_tag 'concept_label', @concept_label + = hidden_field_tag 'github_id', @user.githubId = hidden_field_tag 'ont_acronym', @ont_acronym - = hidden_field_tag 'username', @username + = hidden_field_tag 'orcid_id', @user.orcidId + = hidden_field_tag 'username', @user.username = hidden_field_tag 'operation', KGCL::Operations::NODE_OBSOLETION %div.mb-2 = f.label :comment, "Proposal: obsolete '#{@concept_label}'", for: 'node_obsoletion_comment', class: 'form-label' = f.text_area :comment, rows: 5, class: 'form-control' %div.form-text Optionally enter a comment describing the reason for obsoletion = submit_tag 'Submit', id: 'node_obsoletion_button', class: 'btn btn-primary' - = tag.button 'Cancel', type: 'button', id: 'cancel_kgcl_proposal', class: 'btn btn-primary' + = tag.button('Cancel', type: 'button', + 'data-action': 'click->change-requests#clearProposalForm', class: 'btn btn-primary') diff --git a/app/views/change_requests/_node_rename.html.haml b/app/views/change_requests/_node_rename.html.haml index dca4e874fe..7be776f9b1 100644 --- a/app/views/change_requests/_node_rename.html.haml +++ b/app/views/change_requests/_node_rename.html.haml @@ -1,9 +1,11 @@ = tag.p("Proposal: rename '#{@concept_label}'", class: 'lead') -= form_with scope: :node_rename, url: change_requests_path, local: false, class: 'mb-5' do |f| += form_with scope: :node_rename, url: change_requests_path, data: {turbo: true}, class: 'mb-5' do |f| = hidden_field_tag 'concept_id', @concept_id = hidden_field_tag 'concept_label', @concept_label + = hidden_field_tag 'github_id', @user.githubId = hidden_field_tag 'ont_acronym', @ont_acronym - = hidden_field_tag 'username', @username + = hidden_field_tag 'orcid_id', @user.orcidId + = hidden_field_tag 'username', @user.username = hidden_field_tag 'operation', KGCL::Operations::NODE_RENAME %div.mb-3 = f.label :new_preferred_name, 'Preferred name', class: 'form-label' @@ -16,4 +18,5 @@ = tag.div('Optionally enter a comment giving a reason for the rename', class: 'form-text', id: 'nodeRenameCommentHelpBlock') = submit_tag 'Submit', id: 'node_rename_button', class: 'btn btn-primary' - = tag.button 'Cancel', type: 'button', id: 'cancel_kgcl_proposal', class: 'btn btn-primary' + = tag.button('Cancel', type: 'button', + 'data-action': 'click->change-requests#clearProposalForm', class: 'btn btn-primary') diff --git a/app/views/change_requests/_remove_synonym.html.haml b/app/views/change_requests/_remove_synonym.html.haml index 39254fad3d..1e53b342d5 100644 --- a/app/views/change_requests/_remove_synonym.html.haml +++ b/app/views/change_requests/_remove_synonym.html.haml @@ -5,8 +5,10 @@ = form_with scope: :remove_synonym, url: change_requests_path, local: false do |f| = hidden_field_tag 'concept_id', @concept_id = hidden_field_tag 'concept_label', @concept_label + = hidden_field_tag 'github_id', @user.githubId = hidden_field_tag 'ont_acronym', @ont_acronym - = hidden_field_tag 'username', @username + = hidden_field_tag 'orcid_id', @user.orcidId + = hidden_field_tag 'username', @user.username = hidden_field_tag 'operation', KGCL::Operations::REMOVE_SYNONYM %div{class: 'modal-body'} %div.mb-3 diff --git a/app/views/change_requests/create.js.erb b/app/views/change_requests/create.js.erb index ce26058fdd..d1cba95db2 100644 --- a/app/views/change_requests/create.js.erb +++ b/app/views/change_requests/create.js.erb @@ -1,3 +1,2 @@ -jQuery("#details_content #change-request-notice").html('<%= j render partial: "notice" %>'); - +document.getElementById('change-request-notice').innerHTML = '<%= j render partial: "notice" %>' document.getElementById('addProposalFormDiv').innerHTML = ''; \ No newline at end of file diff --git a/app/views/change_requests/create.turbo_stream.haml b/app/views/change_requests/create.turbo_stream.haml new file mode 100644 index 0000000000..fd7669d806 --- /dev/null +++ b/app/views/change_requests/create.turbo_stream.haml @@ -0,0 +1,4 @@ += turbo_stream.update 'change-request-notice' do + = render partial: 'notice' + += turbo_stream.update 'addProposalFormDiv' diff --git a/app/views/change_requests/node_obsoletion.js.erb b/app/views/change_requests/node_obsoletion.js.erb deleted file mode 100644 index 4e0fdc21ea..0000000000 --- a/app/views/change_requests/node_obsoletion.js.erb +++ /dev/null @@ -1,10 +0,0 @@ -let forms = document.getElementById('addProposalFormDiv').getElementsByTagName('form'); -if (forms.length === 0) { - document.getElementById('addProposalFormDiv') - .insertAdjacentHTML('afterbegin', '<%= j render 'change_requests/node_obsoletion' %>'); -} - -let button = document.getElementById('cancel_kgcl_proposal'); -button.addEventListener('click', () => { - document.getElementById('addProposalFormDiv').innerHTML = ''; -}); diff --git a/app/views/change_requests/node_obsoletion.turbo_stream.haml b/app/views/change_requests/node_obsoletion.turbo_stream.haml new file mode 100644 index 0000000000..47d4c62e9e --- /dev/null +++ b/app/views/change_requests/node_obsoletion.turbo_stream.haml @@ -0,0 +1,2 @@ += turbo_stream.update 'addProposalFormDiv' do + = render partial: 'node_obsoletion' \ No newline at end of file diff --git a/app/views/change_requests/node_rename.js.erb b/app/views/change_requests/node_rename.js.erb deleted file mode 100644 index dd8e1700a5..0000000000 --- a/app/views/change_requests/node_rename.js.erb +++ /dev/null @@ -1,10 +0,0 @@ -let forms = document.getElementById('addProposalFormDiv').getElementsByTagName('form'); -if (forms.length === 0) { - document.getElementById('addProposalFormDiv') - .insertAdjacentHTML('afterbegin', '<%= j render 'change_requests/node_rename' %>'); -} - -let button = document.getElementById('cancel_kgcl_proposal'); -button.addEventListener('click', () => { - document.getElementById('addProposalFormDiv').innerHTML = ''; -}); diff --git a/app/views/change_requests/node_rename.turbo_stream.haml b/app/views/change_requests/node_rename.turbo_stream.haml new file mode 100644 index 0000000000..f2ddab6c42 --- /dev/null +++ b/app/views/change_requests/node_rename.turbo_stream.haml @@ -0,0 +1,2 @@ += turbo_stream.update 'addProposalFormDiv' do + = render partial: 'node_rename' \ No newline at end of file diff --git a/app/views/concepts/_details.html.haml b/app/views/concepts/_details.html.haml index cb0ff44494..908c0d229d 100644 --- a/app/views/concepts/_details.html.haml +++ b/app/views/concepts/_details.html.haml @@ -14,12 +14,13 @@ = link_to('Obsolete class', change_requests_node_obsoletion_path(concept_id: @concept.id, concept_label: @concept.prefLabel, ont_acronym: @ontology.acronym), - class: 'dropdown-item', remote: 'true') + class: 'dropdown-item', 'data-turbo': 'true', 'data-turbo-stream': 'true') = link_to('Rename class', change_requests_node_rename_path(concept_id: @concept.id, concept_label: @concept.prefLabel, ont_acronym: @ontology.acronym), - class: 'dropdown-item', remote: 'true') - %div#addProposalFormDiv + class: 'dropdown-item', 'data-turbo': 'true', 'data-turbo-stream': 'true') + %div{'data-controller': 'change-requests'} + %div{id: 'addProposalFormDiv', 'data-change-requests-target': 'addProposalForm'} %table.minimal.concept_details{cellpadding: "0", cellspacing: "0", width: "100%"} %tr diff --git a/spec/lib/issue_content_generator_spec.rb b/spec/lib/issue_content_generator_spec.rb index 1f6298b6e5..4198a8f923 100644 --- a/spec/lib/issue_content_generator_spec.rb +++ b/spec/lib/issue_content_generator_spec.rb @@ -20,9 +20,11 @@ --- - Comment: Please add this! + **Comment:** Please add this! - This request comes from BioPortal user: Daenerys Targaryen + Proposal generated by: BioPortal user 'Daenerys Targaryen' + + ORCID: HEREDOC content = KGCL::IssueContentGenerator.call(params) @@ -36,6 +38,8 @@ curie: 'MONDO:0009662', concept_label: 'mucopolysaccharidosis type 7', username: 'Sansa Stark', + github_id: 'sstark', + orcid_id: '0000-1234-5678-0000', remove_synonym: { synonym: 'Gus deficiency', comment: "I don't think this is correct!" } } @@ -47,9 +51,11 @@ --- - Comment: I don't think this is correct! + **Comment:** I don't think this is correct! + + Proposal generated by: @sstark - This request comes from BioPortal user: Sansa Stark + ORCID: 0000-1234-5678-0000 HEREDOC content = KGCL::IssueContentGenerator.call(params)