diff --git a/app/assets/javascripts/change_current_provider.coffee b/app/assets/javascripts/change_current_provider.coffee index 540b4124c..321d72a24 100644 --- a/app/assets/javascripts/change_current_provider.coffee +++ b/app/assets/javascripts/change_current_provider.coffee @@ -74,6 +74,8 @@ $(document).ready -> "Managing this service's collection associations" when 'edit-tool' 'Editing this tool' + when 'clone-tool' + 'Cloning this tool' $link.data('type', action) $modal.find('span.provider').text(provider) diff --git a/app/controllers/tools_controller.rb b/app/controllers/tools_controller.rb index d92f31a8e..2c5686dbe 100644 --- a/app/controllers/tools_controller.rb +++ b/app/controllers/tools_controller.rb @@ -2,10 +2,10 @@ class ToolsController < BasePublishedRecordController include ManageMetadataHelper - before_action :set_tool, only: [:show, :edit, :revisions] #, :clone, :destroy, :revert, :download_json] - before_action :set_schema, only: [:show, :edit] #, :clone, :destroy] + before_action :set_tool, only: [:show, :edit, :clone, :revisions] #, :destroy, :revert, :download_json] + before_action :set_schema, only: [:show, :edit, :clone] #, :destroy] before_action :ensure_supported_version, only: [:show, :edit] - before_action :ensure_correct_provider, only: [:edit] #, :clone, :destroy] + before_action :ensure_correct_provider, only: [:edit, :clone] #, :destroy] before_action :set_preview, only: [:show] # If clone is not defined like this performing the clone action leads to a `action not found error` diff --git a/app/helpers/tools_helper.rb b/app/helpers/tools_helper.rb new file mode 100644 index 000000000..19a5d5e6c --- /dev/null +++ b/app/helpers/tools_helper.rb @@ -0,0 +1,12 @@ +module ToolsHelper + def render_change_provider_tool_action_link(tool_action, concept_id, revision_id = nil) + case tool_action + when 'edit' + link_to('Edit Service', edit_tool_path(concept_id, revision_id: revision_id), class: 'is-invisible', id: 'change-provider-tool-edit') + when 'clone' + link_to('Clone Service', clone_tool_path(concept_id, revision_id: revision_id), class: 'is-invisible', id: 'change-provider-tool-clone') + when 'delete' + link_to('Delete Service', tool_path(concept_id), method: :delete, class: 'is-invisible', id: 'change-provider-tool-delete') + end + end +end \ No newline at end of file diff --git a/app/models/tool_draft.rb b/app/models/tool_draft.rb index 7695bc77f..a5282947c 100644 --- a/app/models/tool_draft.rb +++ b/app/models/tool_draft.rb @@ -15,11 +15,11 @@ def create_from_tool(tool, user, native_id) draft = self.find_or_initialize_by(native_id: native_id) draft.entry_title = tool['LongName'] draft.short_name = tool['Name'] - # else - # # Cloned Record - # draft = self.new - # tool.delete('Name') - # tool.delete('LongName') + else + # Cloned Record + draft = self.new + tool.delete('Name') + tool.delete('LongName') end draft.set_user_and_provider(user) diff --git a/app/views/shared/_not_current_provider_modal.html.erb b/app/views/shared/_not_current_provider_modal.html.erb index 3843bc179..aeb5182bc 100644 --- a/app/views/shared/_not_current_provider_modal.html.erb +++ b/app/views/shared/_not_current_provider_modal.html.erb @@ -33,7 +33,7 @@ <%= link_to 'Yes', service_collection_associations_path(options[:concept_id]), class: 'eui-btn--blue spinner is-invisible', id: 'not-current-provider-manage-service-associations-link' %> <% elsif options[:tool] %> <%= link_to 'Yes', edit_tool_path(options[:concept_id], revision_id: options[:revision_id]), class: 'eui-btn--blue spinner is-invisible', id: 'not-current-provider-edit-tool-link' %> - <%#= link_to 'Yes', clone_tool_path(options[:concept_id], revision_id: options[:revision_id]), class: 'eui-btn--blue spinner is-invisible', id: 'not-current-provider-clone-tool-link' %> + <%= link_to 'Yes', clone_tool_path(options[:concept_id], revision_id: options[:revision_id]), class: 'eui-btn--blue spinner is-invisible', id: 'not-current-provider-clone-tool-link' %> <%#= link_to 'Yes', tool_path(options[:concept_id]), method: :delete, class: 'eui-btn--blue spinner is-invisible', id: 'not-current-provider-delete-tool-link' %> <% end %> diff --git a/app/views/tools/show.html.erb b/app/views/tools/show.html.erb index 6665cf2bb..14240393e 100644 --- a/app/views/tools/show.html.erb +++ b/app/views/tools/show.html.erb @@ -23,9 +23,7 @@ "#", id: "change-current-provider-banner-link", data: { "provider": @provider_id, action_link: "change-provider-tool-#{@record_action}" }) %>

- <%# TODO: this method does not exist yet. It should be created and used when %> - <%# additional actions are added to published Tool records %> - <%#= render_change_provider_tool_action_link(@record_action, @concept_id, @revision_id) %> + <%= render_change_provider_tool_action_link(@record_action, @concept_id, @revision_id) %> <% end %> @@ -94,14 +92,11 @@ <% end %> <% end %> - <%# TODO: All links commented out and disabled links added for MMT-2238 %> - <%# links should be re-enabled with the appropriate ticket %> - <%= link_to 'Clone Tool Record', '#', class: 'eui-btn--link bar-after disabled' %> - <%# if current_provider?(@provider_id) %> - <%#= link_to 'Clone Tool Record', clone_tool_path(revision_id: @revision_id), class: 'eui-btn--link bar-after' %> - <%# elsif available_provider?(@provider_id) %> - <%#= link_to 'Clone Tool Record', '#not-current-provider-modal', class: 'display-modal not-current-provider eui-btn--link bar-after', data: { 'provider': @provider_id, record_action: 'clone-tool' } %> - <%# end %> + <% if current_provider?(@provider_id) %> + <%= link_to 'Clone Tool Record', clone_tool_path(revision_id: @revision_id), class: 'eui-btn--link bar-after' %> + <% elsif available_provider?(@provider_id) %> + <%= link_to 'Clone Tool Record', '#not-current-provider-modal', class: 'display-modal not-current-provider eui-btn--link bar-after', data: { 'provider': @provider_id, record_action: 'clone-tool' } %> + <% end %> <%= link_to 'Download JSON', '#', class: 'eui-btn--link disabled' %> <%#= link_to 'Download JSON', download_json_tool_path(@concept_id, revision_id: @revision_id), class: 'eui-btn--link', target: '_blank' %> diff --git a/config/locales/en.yml b/config/locales/en.yml index bf9d5b6cb..d420d9298 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -198,6 +198,9 @@ en: flash: success: 'Tool Draft Published Successfully!' error: 'Tool Draft was not published successfully' + clone: + flash: + notice: 'Records must have a unique Name and Long Name within a provider. Click here to enter a new Name and Long Name.' collection_associations: destroy: flash: diff --git a/config/routes.rb b/config/routes.rb index 6e8cc5c8a..ce35fbe4d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -104,6 +104,7 @@ get '/services/:id/download_json(/:revision_id)' => 'services#download_json', as: 'download_json_service' resources :tools, only: [:show, :create, :edit] + get '/tools/:id/clone' => 'tools#clone', as: 'clone_tool' get '/tools/:id/revisions' => 'tools#revisions', as: 'tool_revisions' resources :variable_drafts, controller: 'variable_drafts', draft_type: 'VariableDraft' do diff --git a/spec/features/tool_drafts/create_tool_draft_from_cloning_spec.rb b/spec/features/tool_drafts/create_tool_draft_from_cloning_spec.rb new file mode 100644 index 000000000..76a02c85c --- /dev/null +++ b/spec/features/tool_drafts/create_tool_draft_from_cloning_spec.rb @@ -0,0 +1,62 @@ +describe 'Creating a tool draft from cloning a tool', reset_provider: true, js: true do + before :all do + @ingest_response, _concept_response, @native_id = publish_tool_draft + end + + after :all do + delete_response = cmr_client.delete_tool('MMT_2', @native_id, 'token') + + raise unless delete_response.success? + end + + context 'when cloning a published tool' do + before do + login + + visit tool_path(@ingest_response['concept-id']) + + click_on 'Clone Tool Record' + end + + it 'displays the draft preview page' do + within '.eui-breadcrumbs' do + expect(page).to have_content('Tool Drafts') + end + + expect(page).to have_content('Publish Tool Draft') + expect(page).to have_content('Delete Tool Draft') + expect(page).to have_content('Metadata Fields') + expect(page).to have_content('Tool Information') + end + + it 'removes the Name and Long Name from the metadata' do + within '#tool_draft_draft_name_preview' do + expect(page).to have_css('p', text: 'No value for Name provided.') + end + + within '#tool_draft_draft_long_name_preview' do + expect(page).to have_css('p', text: 'No value for Long Name provided.') + end + end + + it 'creates a new native id for the draft' do + draft = ToolDraft.last + expect(draft.native_id).to eq("mmt_tool_#{draft.id}") + end + + it 'displays a message that the draft needs a unique Name' do + expect(page).to have_content('Records must have a unique Name and Long Name within a provider. Click here to enter a new Name and Long Name.') + end + + context 'when clicking the banner message to enter a new Name' do + before do + click_on 'Click here to enter a new Name and Long Name.' + end + + it 'displays the empty Name and Long Name fields' do + expect(page).to have_field('Name', with: '') + expect(page).to have_field('Long Name', with: '') + end + end + end +end diff --git a/spec/features/tools/tool_permissions_spec.rb b/spec/features/tools/tool_permissions_spec.rb new file mode 100644 index 000000000..f01413565 --- /dev/null +++ b/spec/features/tools/tool_permissions_spec.rb @@ -0,0 +1,238 @@ +describe 'Tools permissions', reset_provider: true, js: true do + let(:modal_text) { 'requires you change your provider context to MMT_2' } + + context 'when viewing a tool' do + before do + login + end + + context "when the tool's provider is in the users available providers" do + before :all do + @ingested_tool, _concept_response, @native_id_1 = publish_tool_draft +# @ingested_tool_for_delete_modal, _concept_response, _native_id_2 = publish_tool_draft + end + + after :all do + delete_response = cmr_client.delete_tool('MMT_2', @native_id_1, 'token') + # Second tool should be deleted in the delete test + + raise unless delete_response.success? + end + + before do + login(provider: 'MMT_1', providers: %w(MMT_1 MMT_2)) + + visit tool_path(@ingested_tool['concept-id']) + end + + it 'displays the action links' do + expect(page).to have_link('Edit Tool Record') + expect(page).to have_link('Clone Tool Record') + expect(page).to have_link('Delete Tool Record') + end + + context 'when clicking the edit link' do + before do + click_on 'Edit Tool Record' + end + + it 'displays a modal informing the user they need to switch providers' do + expect(page).to have_content("Editing this tool #{modal_text}") + end + + context 'when clicking Yes' do + before do + # click_on 'Yes' + find('.not-current-provider-link').click + wait_for_jQuery + end + + it 'switches the provider context' do + expect(User.first.provider_id).to eq('MMT_2') + end + + it 'creates a draft from the tool' do + expect(page).to have_content('Tool Draft Created Successfully!') + expect(Draft.where(provider_id: 'MMT_2').size).to eq(1) + end + end + end + + context 'when clicking the clone link' do + before do + click_on 'Clone Tool Record' + end + + it 'displays a modal informing the user they need to switch providers' do + expect(page).to have_content("Cloning this tool #{modal_text}") + end + + context 'when clicking Yes' do + before do + find('.not-current-provider-link').click + wait_for_jQuery + end + + it 'switches the provider context' do + expect(User.first.provider_id).to eq('MMT_2') + end + + it 'creates a draft from the tool' do + expect(page).to have_content('Records must have a unique Name and Long Name within a provider. Click here to enter a new Name and Long Name.') + expect(Draft.where(provider_id: 'MMT_2').size).to eq(1) + end + end + end + +# TODO: Uncomment in MMT-2229 +# context 'when clicking the delete link' do +# context 'when the tool has no associated collections' do +# before do +# visit tool_path(@ingested_tool_for_delete_modal['concept-id']) +# +# click_on 'Delete Tool Record' +# end +# +# it 'displays a modal informing the user they need to switch providers' do +# expect(page).to have_content("Deleting this tool #{modal_text}") +# end +# +# it 'does not display a message about collection associations that will also be deleted' do +# expect(page).to have_no_content('This tool is associated with') +# expect(page).to have_no_content('collections. Deleting this tool will also delete the collection associations') +# end +# end +# +# context 'when deleting the tool' do +# before do +# ingested_tool_to_delete, _concept_response = publish_tool_draft +# +# visit tool_path(ingested_tool_to_delete['concept-id']) +# +# click_on 'Delete Tool Record' +# +# find('.not-current-provider-link').click +# wait_for_jQuery +# end +# +# it 'switches the provider context' do +# expect(User.first.provider_id).to eq('MMT_2') +# end +# +# it 'deletes the record' do +# expect(page).to have_content('Tool Deleted Successfully!') +# end +# end +# end + + context 'when trying to visit the action paths directly' do + context 'when visiting the edit path directly' do + before do + edit_link = page.current_path + '/edit' + visit edit_link + end + + it 'displays warning banner link to change provider' do + expect(page).to have_css('.eui-banner--warn') + expect(page).to have_content('You need to change your current provider to edit this tool') + end + + context 'when clicking the warning banner link' do + before do + click_link('You need to change your current provider to edit this tool') + wait_for_jQuery + end + + it 'switches the provider context' do + expect(User.first.provider_id).to eq('MMT_2') + end + + it 'creates a draft from the tool' do + expect(page).to have_content('Tool Draft Created Successfully!') + expect(Draft.where(provider_id: 'MMT_2').size).to eq(1) + end + end + end + + context 'when visiting the clone path directly' do + before do + clone_link = page.current_path + '/clone' + visit clone_link + end + + it 'displays warning banner link to change provider' do + expect(page).to have_css('.eui-banner--warn') + expect(page).to have_content('You need to change your current provider to clone this tool') + end + + context 'when clicking the warning banner link' do + before do + click_link('You need to change your current provider to clone this tool') + wait_for_jQuery + end + + it 'switches the provider context' do + expect(User.first.provider_id).to eq('MMT_2') + end + + it 'creates a draft from the tool' do + expect(page).to have_content('Records must have a unique Name and Long Name within a provider. Click here to enter a new Name and Long Name.') + expect(Draft.where(provider_id: 'MMT_2').size).to eq(1) + end + end + end + end + end + + context 'when the tools provider is not in the users available providers' do + before do + @ingested_not_available_provider_tool, _concept_response = publish_tool_draft(provider_id: 'SEDAC') + + visit tool_path(@ingested_not_available_provider_tool['concept-id']) + end + + it 'does not display the action links' do + expect(page).to have_no_link('Edit Tool Record') + expect(page).to have_no_link('Clone Tool Record') +# TODO: Uncomment in MMT-2229 +# expect(page).to have_no_link('Delete Tool Record') + end + + context 'when trying to visit the action paths directly' do + context 'when visiting the edit path directly' do + before do + edit_link = page.current_path + '/edit' + visit edit_link + end + + it 'displays the no permissions banner message' do + expect(page).to have_css('.eui-banner--danger') + expect(page).to have_content("You don't have the appropriate permissions to edit this tool") + end + + it 'displays the Access Denied message' do + expect(page).to have_content('Access Denied') + expect(page).to have_content('It appears you do not have access to edit this content.') + end + end + + context 'when visiting the clone path directly' do + before do + clone_link = page.current_path + '/clone' + visit clone_link + end + + it 'displays the no permissions banner message' do + expect(page).to have_css('.eui-banner--danger') + expect(page).to have_content("You don't have the appropriate permissions to clone this tool") + end + + it 'displays the Access Denied message' do + expect(page).to have_content('Access Denied') + expect(page).to have_content('It appears you do not have access to clone this content.') + end + end + end + end + end +end