Browse Source

Fixes #5148 - External data source search gets stuck when it is added as a condition or an action

Mantas Masalskis 9 months ago
parent
commit
8d4f763ec8

+ 10 - 9
app/assets/javascripts/app/lib/app_post/z_searchable_ajax_select_external_data_source.coffee

@@ -67,18 +67,19 @@ class App.ExternalDataSourceAjaxSelect extends App.SearchableAjaxSelect
     "#{objectName}+#{attributeName}+#{query}"
 
   ajaxAttributes: =>
-    objectName    = @options.attribute.objectName
-    attributeName = @options.attribute.attributeName or @options.attribute.nameRaw
-    query         = @input.val()
+    objectName     = @options.attribute.objectName
+    attributeName  = @options.attribute.attributeName or @options.attribute.nameRaw
+    query          = @input.val()
+    search_context = {}
 
-    params = if @delegate.params?.id then @delegate.params else App.ControllerForm.params(@delegate.form)
+    if @delegate
+      params = if @delegate.params?.id then @delegate.params else App.ControllerForm.params(@delegate.form)
 
-    search_context = {}
-    if params.id
-      search_context["#{@delegate.model.className.toLowerCase()}_id"] = params.id
+      if params.id
+        search_context["#{@delegate.model.className.toLowerCase()}_id"] = params.id
 
-    if params.customer_id
-      search_context.customer_id = params.customer_id
+      if params.customer_id
+        search_context.customer_id = params.customer_id
 
     {
       id:   @options.attribute.id

+ 18 - 11
app/controllers/external_data_source_controller.rb

@@ -36,25 +36,32 @@ class ExternalDataSourceController < ApplicationController
   end
 
   def render_context
-    {}.tap do |result|
-      search_context = params.fetch(:search_context, {})
-      [::Ticket, ::Group, ::User, ::Organization].each do |model|
-        param_value = search_context["#{model.name.downcase}_id"]
-        result[model.name.downcase.to_sym] = model.find_by(id: param_value) if param_value
-      end
+    search_context = params.fetch(:search_context, {})
 
-      result[:user] ||= current_user
+    result = [::Ticket, ::Group, ::User, ::Organization].each_with_object({}) do |model, memo|
+      param_value = search_context["#{model.name.downcase}_id"]
 
-      # If ticket does not exist yet, fake it with a customer if present.
-      inject_ticket(search_context, result)
+      next if !param_value
+
+      memo[model.name.downcase.to_sym] = model.find_by(id: param_value)
     end
+
+    result[:user] ||= current_user
+
+    # If ticket does not exist yet, fake it with a customer if present.
+    inject_ticket(search_context, result)
+
+    result
   end
 
   def inject_ticket(search_context, result)
     return if result[:ticket]
+    return if !search_context['customer_id']
+
+    customer = ::User.find_by(id: search_context['customer_id'])
 
-    customer = ::User.find_by(id: search_context['customer_id']) if search_context['customer_id']
-    result[:ticket] = ::Ticket.new(customer: customer) if customer
+    return if !customer
 
+    result[:ticket] = ::Ticket.new(customer: customer)
   end
 end

+ 82 - 0
public/assets/tests/qunit/form_ticket_perform_action.js

@@ -781,3 +781,85 @@ QUnit.test( "ticket_perform_action check template attributes", assert => {
   var articleBody = row.find('[data-name="ticket_perform_action8::article.body::value"]')
   assert.equal(articleBody.html(), 'foobar', 'article body text check')
 });
+
+QUnit.test( "ticket_perform_action allows to load data from external data source", assert => {
+  var testOptions = [
+    {
+      value: 1,
+      label: 'A',
+    },
+    {
+      value: 2,
+      label: 'B',
+    },
+    {
+      value: 3,
+      label: 'C',
+    },
+  ]
+
+  App.ExternalDataSourceAjaxSelect.TEST_SEARCH_RESULT_CACHE = {
+    'Ticket+external_data_source1+*': {
+      result: testOptions,
+    },
+    'Ticket+external_data_source1+': {
+      result: testOptions,
+    },
+  }
+
+  $('#forms').append('<hr><h1>ticket_perform_action allows to load data from external data source</h1><form id="form9"></form>')
+
+  var el = $('#form9')
+
+  App.Ticket.configure_attributes.push({
+    name:    'external_data_source1',
+    display: 'ExternalDataSource1',
+    tag:     'autocompletion_ajax_external_data_source',
+    null:    true,
+  })
+
+  new App.ControllerForm({
+    el:        el,
+    model:     {
+      configure_attributes: [
+        {
+          name:    'ticket_perform_action6',
+          display: 'TicketPerformAction6',
+          tag:     'ticket_perform_action',
+          null:    true,
+        },
+      ]
+    },
+    params:    {},
+    autofocus: true
+  })
+
+  $('[data-attribute-name="ticket_perform_action6"] .js-attributeSelector .form-control')
+    .last()
+    .val('ticket.external_data_source1')
+    .trigger('change')
+
+  $('[data-attribute-name="ticket_perform_action6"] .js-input')
+    .trigger('focus')
+    .val('*')
+    .trigger('input')
+
+  var entries = $('[data-attribute-name="ticket_perform_action6"]').find('.js-optionsList li').length
+  assert.equal(entries, 3, 'dropdown count')
+
+  $('[data-attribute-name="ticket_perform_action6"]').find('.js-optionsList li:first').trigger('click')
+
+  var params = App.ControllerForm.params(el)
+  var test_params = {
+    ticket_perform_action6: {
+      'ticket.external_data_source1': {
+        'value': {
+          label: 'A',
+          value: 1
+        }
+      }
+    }
+  }
+
+  assert.deepEqual(params, test_params, 'form param check')
+});

+ 21 - 0
spec/requests/external_data_source_controller_spec.rb

@@ -94,6 +94,27 @@ RSpec.describe 'External Data Source', :aggregate_failures, db_adapter: :postgre
           expect(ExternalDataSource).to have_received(:new).with(include(render_context: { group: group, user: admin }))
         end
       end
+
+      context 'when customer is given' do
+        let(:object_name) { 'Group' }
+        let(:customer)    { create(:customer) }
+        let(:url)         { "/api/v1/external_data_source/#{attribute.object_lookup.name}/#{attribute.name}?query=abc&search_context%5Bcustomer_id%5D=#{customer.id}" }
+
+        it 'responds with an array of ExternalCredential records' do
+          get url, as: :json
+
+          expect(response).to have_http_status(:ok)
+          expect(json_response).to eq('result' => mocked_payload)
+          expect(ExternalDataSource)
+            .to have_received(:new)
+            .with(include(
+                    render_context: {
+                      user:   admin,
+                      ticket: a_kind_of(Ticket).and(have_attributes(customer: customer))
+                    }
+                  ))
+        end
+      end
     end
   end
 end