Browse Source

Fixes #864 - Added relative pending_time to Macro/Trigger/Scheduler functionality. Based on the Pull Request #2862 by @fleverest – huge thanks ❤️

Mantas Masalskis 4 years ago
parent
commit
22fe0a2a97

+ 18 - 4
app/assets/javascripts/app/controllers/_ui_element/ticket_perform_action.coffee

@@ -35,8 +35,13 @@ class App.UiElement.ticket_perform_action
             # ignore readonly attributes
             if !row.readonly
               config = _.clone(row)
-              if config.tag is 'tag'
-                config.operator = ['add', 'remove']
+
+              switch config.tag
+                when 'datetime'
+                  config.operator = ['static', 'relative']
+                when 'tag'
+                  config.operator = ['add', 'remove']
+
               elements["#{groupKey}.#{config.name}"] = config
 
     # add ticket deletion action
@@ -318,13 +323,22 @@ class App.UiElement.ticket_perform_action
         item = App.UiElement[tagSearch].render(config, {})
       else
         item = App.UiElement[config.tag].render(config, {})
-    if meta.operator is 'before (relative)' || meta.operator is 'within next (relative)' || meta.operator is 'within last (relative)' || meta.operator is 'after (relative)'
+
+    relative_operators = [
+      'before (relative)',
+      'within next (relative)',
+      'within last (relative)',
+      'after (relative)',
+      'relative'
+    ]
+
+    if _.include(relative_operators, meta.operator)
       config['name'] = "#{attribute.name}::#{groupAndAttribute}"
       if attribute.value && attribute.value[groupAndAttribute]
         config['value'] = _.clone(attribute.value[groupAndAttribute])
       item = App.UiElement['time_range'].render(config, {})
 
-    elementRow.find('.js-value').removeClass('hide').html(item)
+    elementRow.find('.js-setAttribute > .flex > .js-value').removeClass('hide').html(item)
 
   @buildNotificationArea: (notificationType, elementFull, elementRow, groupAndAttribute, elements, meta, attribute) ->
 

+ 19 - 0
app/assets/javascripts/app/models/ticket.coffee

@@ -133,6 +133,25 @@ class App.Ticket extends App.Model
               else
                 @tagAdd(params.ticket.id, tag)
 
+        # apply pending date changes
+        else if attributes[1] is 'pending_time' && content.operator is 'relative'
+          pendtil = new Date
+          diff    = parseInt(content.value, 10)
+
+          switch content.range
+            when 'day'
+              pendtil.setDate(pendtil.getDate() + diff)
+            when 'minute'
+              pendtil.setMinutes(pendtil.getMinutes() + diff)
+            when 'hour'
+              pendtil.setHours(pendtil.getHours() + diff)
+            when 'month'
+              pendtil.setMonth(pendtil.getMonth() + diff)
+            when 'year'
+              pendtil.setYear(pendtil.getYear() + diff)
+
+          params.ticket[attributes[1]] = pendtil.toISOString()
+
         # apply user changes
         else if attributes[1] is 'owner_id'
           if content.pre_condition is 'current_user.id'

+ 2 - 2
app/assets/javascripts/app/views/generic/ticket_perform_action/attribute_selector.jst.eco

@@ -11,5 +11,5 @@
       <%- @Icon('arrow-down', 'dropdown-arrow') %>
     </div>
   </div>
-  <div class="controls js-value"></div>
-</div>
+  <div class="controls js-value horizontal"></div>
+</div>

+ 22 - 0
app/models/observer/ticket/pending_time.rb

@@ -0,0 +1,22 @@
+# Ensures pending time is always zero-seconds
+class Observer::Ticket::PendingTime < ActiveRecord::Observer
+  observe 'ticket'
+
+  def before_create(record)
+    _check(record)
+  end
+
+  def before_update(record)
+    _check(record)
+  end
+
+  private
+
+  def _check(record)
+    return true if record.pending_time.blank?
+    return true if !record.pending_time_changed?
+    return true if record.pending_time.sec.zero?
+
+    record.pending_time = record.pending_time.change sec: 0
+  end
+end

+ 32 - 0
app/models/ticket.rb

@@ -907,6 +907,38 @@ perform changes on ticket
         next
       end
 
+      # Apply pending_time changes
+      if key == 'ticket.pending_time'
+        new_value = case value['operator']
+                    when 'static'
+                      value['value']
+                    when 'relative'
+                      pendtil = Time.zone.now
+                      val     = value['value'].to_i
+
+                      case value['range']
+                      when 'day'
+                        pendtil += val.days
+                      when 'minute'
+                        pendtil += val.minutes
+                      when 'hour'
+                        pendtil += val.hours
+                      when 'month'
+                        pendtil += val.months
+                      when 'year'
+                        pendtil += val.years
+                      end
+
+                      pendtil
+                    end
+
+        if new_value
+          self[attribute] = new_value
+          changed = true
+          next
+        end
+      end
+
       # update tags
       if key == 'ticket.tags'
         next if value['value'].blank?

+ 14 - 0
app/views/tests/ticket_macro.html.erb

@@ -0,0 +1,14 @@
+
+<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/ticket_macro.js", nonce: true %>
+
+<style type="text/css">
+body {
+  padding-top: 0px;
+}
+</style>
+
+<script type="text/javascript">
+</script>
+
+<div id="qunit" class="u-dontfold"></div>

+ 1 - 0
config/application.rb

@@ -29,6 +29,7 @@ module Zammad
       'observer::_session',
       'observer::_ticket::_close_time',
       'observer::_ticket::_last_owner_update',
+      'observer::_ticket::_pending_time',
       'observer::_ticket::_user_ticket_counter',
       'observer::_ticket::_article_changes',
       'observer::_ticket::_article::_fillup_from_origin_by_id',

+ 1 - 0
config/routes/test.rb

@@ -25,6 +25,7 @@ Zammad::Application.routes.draw do
   match '/tests_table',                       to: 'tests#table',                      via: :get
   match '/tests_table_extended',              to: 'tests#table_extended',             via: :get
   match '/tests_html_utils',                  to: 'tests#html_utils',                 via: :get
+  match '/tests_ticket_macro',                to: 'tests#ticket_macro',               via: :get
   match '/tests_ticket_selector',             to: 'tests#ticket_selector',            via: :get
   match '/tests_taskbar',                     to: 'tests#taskbar',                    via: :get
   match '/tests_text_module',                 to: 'tests#text_module',                via: :get

+ 141 - 0
public/assets/tests/form_ticket_perform_action.js

@@ -237,6 +237,104 @@ test( "ticket_perform_action check", function() {
     }
   }
   deepEqual(params, test_params, 'form param check')
+
+  // add pending time
+  $('[data-attribute-name="ticket_perform_action3"] .js-add').last().click()
+
+  var row = $('[data-attribute-name="ticket_perform_action3"] .js-filterElement').last()
+
+  var date_string = '2010-07-15T12:00:00.000Z'
+  var date_parsed = new Date(date_string) // make sure it works regardless of browser locale
+
+  row.find('.js-attributeSelector .form-control').last().val('ticket.pending_time').trigger('change')
+  row.find('.js-datepicker').val(date_parsed.toLocaleDateString()).trigger('blur')
+  row.find('.js-datepicker').datepicker('setDate')
+  row.find('.js-timepicker').val(date_parsed.getHours() + ':' + date_parsed.getMinutes()).trigger('blur')
+
+  params = App.ControllerForm.params(el)
+  test_params = {
+    ticket_perform_action1: {
+      'ticket.state_id': {
+        value: '2'
+      }
+    },
+    ticket_perform_action2: {
+      'notification.email': {
+        body: 'some body',
+        internal: 'true',
+        recipient: 'ticket_customer',
+        subject: 'some subject'
+      },
+      'ticket.priority_id': {
+        value: '2'
+      },
+      'ticket.state_id': {
+        value: '1'
+      },
+    },
+    ticket_perform_action3: {
+      'notification.email': {
+        body: 'some body',
+        internal: 'false',
+        recipient: 'ticket_owner',
+        subject: 'some subject'
+      },
+      'ticket.pending_time': {
+        operator: 'static',
+        value: date_string
+      },
+      'ticket.state_id': {
+        value: '3'
+      }
+    }
+  }
+  deepEqual(params, test_params, 'form param check')
+
+  // switch pending time to relative
+
+  row.find('.js-operator select').val('relative').trigger('change')
+  row.find('.js-range').val('day').trigger('change')
+  row.find('.js-value').val('10').trigger('change')
+
+  params = App.ControllerForm.params(el)
+  test_params = {
+    ticket_perform_action1: {
+      'ticket.state_id': {
+        value: '2'
+      }
+    },
+    ticket_perform_action2: {
+      'notification.email': {
+        body: 'some body',
+        internal: 'true',
+        recipient: 'ticket_customer',
+        subject: 'some subject'
+      },
+      'ticket.priority_id': {
+        value: '2'
+      },
+      'ticket.state_id': {
+        value: '1'
+      },
+    },
+    ticket_perform_action3: {
+      'notification.email': {
+        body: 'some body',
+        internal: 'false',
+        recipient: 'ticket_owner',
+        subject: 'some subject'
+      },
+      'ticket.pending_time': {
+        operator: 'relative',
+        range: 'day',
+        value: '10'
+      },
+      'ticket.state_id': {
+        value: '3'
+      }
+    }
+  }
+  deepEqual(params, test_params, 'form param check')
 });
 
 // Test for backwards compatibility after issue is fixed https://github.com/zammad/zammad/issues/2782
@@ -363,3 +461,46 @@ test( "ticket_perform_action rows manipulation", function() {
 
   equal($(selector + ' .js-filterElement').length, 1, 'prevents removing last row')
 });
+
+// Test for backwards compatibility after PR https://github.com/zammad/zammad/pull/2862
+test( "ticket_perform_action backwards check after PR#2862", function() {
+  $('#forms').append('<hr><h1>ticket_perform_action check</h1><form id="form3"></form>')
+
+  var el = $('#form3')
+
+  var defaults = {
+    ticket_perform_action4: {
+      'ticket.pending_time': {
+        value: '2010-07-15T05:00:00.000Z'
+      }
+    }
+  }
+
+  new App.ControllerForm({
+    el:        el,
+    model:     {
+      configure_attributes: [
+        {
+          name:    'ticket_perform_action4',
+          display: 'TicketPerformAction4',
+          tag:     'ticket_perform_action',
+          null:    true,
+        },
+      ]
+    },
+    params: defaults,
+    autofocus: true
+  })
+
+  var params = App.ControllerForm.params(el)
+  var test_params = {
+    ticket_perform_action4: {
+      'ticket.pending_time': {
+        operator: 'static',
+        value: '2010-07-15T05:00:00.000Z'
+      }
+    }
+  }
+
+  deepEqual(params, test_params, 'form param check')
+});

+ 43 - 0
public/assets/tests/ticket_macro.js

@@ -0,0 +1,43 @@
+test( "ticket macro pending time check", function() {
+  var test_relative = function(rules, target, description){
+    var ticket = new App.Ticket()
+
+    App.Ticket.macro({
+      ticket: ticket,
+      macro: {
+        "ticket.pending_time": rules
+      }
+    })
+
+    var compare_against = new Date()
+    var travel = Math.abs( new Date(ticket.pending_time) - compare_against)
+
+    var diff = Math.abs(target - travel)
+
+    ok(diff < 1000, description)
+  }
+
+  var rules = {
+    operator: "relative",
+    range: "day",
+    value: 5
+  }
+
+  test_relative(rules, 60 * 60 * 24 * 5 * 1000, '5 days')
+
+  var rules = {
+    operator: "relative",
+    range: "minute",
+    value: 3
+  }
+
+  test_relative(rules, 60 * 3 * 1000, '5 minutes')
+
+  var rules = {
+    operator: "relative",
+    range: "hour",
+    value: 10
+  }
+
+  test_relative(rules, 60 * 60 * 10 * 1000, '10 hours')
+})

Some files were not shown because too many files changed in this diff