Merge branch 'develop' of github.com:martini/zammad into develop
This commit is contained in:
commit
9c27582068
22 changed files with 438 additions and 15 deletions
|
@ -528,6 +528,9 @@ class App.Controller extends Spine.Controller
|
|||
# replace new option list
|
||||
form.find('[name="' + fieldNameToChange + '"]').closest('.form-group').replaceWith( newElement )
|
||||
|
||||
stopPropagation: (e) ->
|
||||
e.stopPropagation()
|
||||
|
||||
class App.ControllerPermanent extends App.Controller
|
||||
constructor: ->
|
||||
super
|
||||
|
|
|
@ -8,6 +8,9 @@ class App.UiElement.ticket_perform_action
|
|||
name: 'Ticket'
|
||||
model: 'Ticket'
|
||||
|
||||
operators =
|
||||
'ticket.tags': ['add', 'remove']
|
||||
|
||||
# megre config
|
||||
elements = {}
|
||||
for groupKey, groupMeta of groups
|
||||
|
@ -21,11 +24,11 @@ class App.UiElement.ticket_perform_action
|
|||
config = _.clone(row)
|
||||
elements["#{groupKey}.#{config.name}"] = config
|
||||
|
||||
[defaults, groups, elements]
|
||||
[defaults, groups, operators, elements]
|
||||
|
||||
@render: (attribute, params = {}) ->
|
||||
|
||||
[defaults, groups, elements] = @defaults()
|
||||
[defaults, groups, operators, elements] = @defaults()
|
||||
|
||||
selector = @buildAttributeSelector(groups, elements)
|
||||
|
||||
|
@ -53,6 +56,7 @@ class App.UiElement.ticket_perform_action
|
|||
elementRow = $(e.target).closest('.js-filterElement')
|
||||
|
||||
@rebuildAttributeSelectors(item, elementRow, groupAndAttribute)
|
||||
@buildOperator(item, elementRow, groupAndAttribute, elements, undefined, attribute, operators)
|
||||
@buildValue(item, elementRow, groupAndAttribute, elements, undefined, attribute)
|
||||
)
|
||||
|
||||
|
@ -63,6 +67,7 @@ class App.UiElement.ticket_perform_action
|
|||
for groupAndAttribute, meta of params[attribute.name]
|
||||
selectorExists = true
|
||||
value = meta.value
|
||||
operator = meta.operator
|
||||
|
||||
# get selector rows
|
||||
elementFirst = item.find('.js-filterElement').first()
|
||||
|
@ -71,6 +76,7 @@ class App.UiElement.ticket_perform_action
|
|||
# clone, rebuild and append
|
||||
elementClone = elementFirst.clone(true)
|
||||
@rebuildAttributeSelectors(item, elementClone, groupAndAttribute)
|
||||
@buildOperator(item, elementClone, groupAndAttribute, elements, value, attribute, operators, operator)
|
||||
@buildValue(item, elementClone, groupAndAttribute, elements, value, attribute)
|
||||
elementLast.after(elementClone)
|
||||
|
||||
|
@ -93,6 +99,26 @@ class App.UiElement.ticket_perform_action
|
|||
|
||||
item
|
||||
|
||||
@buildOperator: (elementFull, elementRow, groupAndAttribute, elements, value, attribute, operators, operator) ->
|
||||
name = "#{attribute.name}::#{groupAndAttribute}::operator"
|
||||
if !operators[groupAndAttribute]
|
||||
elementRow.find('.js-operator').html('')
|
||||
return
|
||||
|
||||
# get current operator
|
||||
if !operator
|
||||
operator = elementRow.find('.js-operator select').val()
|
||||
|
||||
# build new operator
|
||||
selection = $("<select class=\"form-control\" name=\"#{name}\"></select>")
|
||||
for operatorKey in operators[groupAndAttribute]
|
||||
operatorKeyName = App.i18n.translateInline(operatorKey)
|
||||
selected = ''
|
||||
if operatorKey is operator
|
||||
selected = 'selected'
|
||||
selection.append("<option value=\"#{operatorKey}\" #{selected}>#{operatorKeyName}</option>")
|
||||
elementRow.find('.js-operator').html(selection)
|
||||
|
||||
@buildValue: (elementFull, elementRow, groupAndAttribute, elements, value, attribute) ->
|
||||
|
||||
# do nothing if item already exists
|
||||
|
@ -163,7 +189,7 @@ class App.UiElement.ticket_perform_action
|
|||
@humanText: (condition) ->
|
||||
none = App.i18n.translateContent('No filter.')
|
||||
return [none] if _.isEmpty(condition)
|
||||
[defaults, groups, elements] = @defaults()
|
||||
[defaults, groups, operators, elements] = @defaults()
|
||||
rules = []
|
||||
for attribute, value of condition
|
||||
|
||||
|
|
27
app/assets/javascripts/app/controllers/macro.coffee
Normal file
27
app/assets/javascripts/app/controllers/macro.coffee
Normal file
|
@ -0,0 +1,27 @@
|
|||
class Index extends App.ControllerContent
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
# check authentication
|
||||
return if !@authenticate()
|
||||
|
||||
new App.ControllerGenericIndex(
|
||||
el: @el
|
||||
id: @id
|
||||
genericObject: 'Macro'
|
||||
pageData:
|
||||
title: 'Macros'
|
||||
home: 'macros'
|
||||
object: 'Macro'
|
||||
objects: 'Macros'
|
||||
navupdate: '#macros'
|
||||
notes: [
|
||||
'TextModules are ...'
|
||||
]
|
||||
buttons: [
|
||||
{ name: 'New Macro', 'data-type': 'new', class: 'btn--success' }
|
||||
]
|
||||
container: @el.closest('.content')
|
||||
)
|
||||
|
||||
App.Config.set( 'Macros', { prio: 2310, name: 'Macros', parent: '#manage', target: '#manage/macros', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )
|
|
@ -308,6 +308,12 @@ class App.TicketZoom extends App.Controller
|
|||
el: @el.find('.ticket-meta')
|
||||
)
|
||||
|
||||
new App.TicketZoomAttributeBar(
|
||||
ticket: @ticket
|
||||
el: @el.find('.js-attributeBar')
|
||||
callback: @submit
|
||||
)
|
||||
|
||||
@form_id = App.ControllerForm.formId()
|
||||
|
||||
new App.TicketZoomArticleNew(
|
||||
|
@ -338,7 +344,7 @@ class App.TicketZoom extends App.Controller
|
|||
user_id: @ticket.customer_id
|
||||
size: 50
|
||||
)
|
||||
new App.TicketZoomSidebar(
|
||||
@sidebar = new App.TicketZoomSidebar(
|
||||
el: @el.find('.tabsSidebar')
|
||||
sidebarState: @sidebarState
|
||||
ticket: @ticket
|
||||
|
@ -462,7 +468,7 @@ class App.TicketZoom extends App.Controller
|
|||
|
||||
resetButton.removeClass('hide')
|
||||
|
||||
submit: (e) =>
|
||||
submit: (e, macro = {}) =>
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
ticketParams = @formParam( @$('.edit') )
|
||||
|
@ -477,6 +483,25 @@ class App.TicketZoom extends App.Controller
|
|||
for key, value of ticketParams
|
||||
ticket[key] = value
|
||||
|
||||
# apply macro
|
||||
for key, content of macro
|
||||
attributes = key.split('.')
|
||||
if attributes[0] is 'ticket'
|
||||
|
||||
# apply tag changes
|
||||
if attributes[1] is 'tags'
|
||||
if @sidebar && @sidebar.tagWidget
|
||||
tags = content.value.split(',')
|
||||
for tag in tags
|
||||
if content.operator is 'remove'
|
||||
@sidebar.tagWidget.remove(tag)
|
||||
else
|
||||
@sidebar.tagWidget.add(tag)
|
||||
|
||||
# apply direct value changes
|
||||
else
|
||||
ticket[attributes[1]] = content.value
|
||||
|
||||
# set defaults
|
||||
if !@isRole('Customer')
|
||||
if !ticket['owner_id']
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
class App.TicketZoomAttributeBar extends App.Controller
|
||||
elements:
|
||||
'.buttonDropdown': 'buttonDropdown'
|
||||
|
||||
events:
|
||||
'mousedown .js-openDropdownMacro': 'toggleDropdownMacro'
|
||||
'click .js-openDropdownMacro': 'stopPropagation'
|
||||
'mouseup .js-dropdownActionMacro': 'performTicketMacro'
|
||||
'mouseenter .js-dropdownActionMacro': 'onActionMacroMouseEnter'
|
||||
'mouseleave .js-dropdownActionMacro': 'onActionMacroMouseLeave'
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
@subscribeId = App.Macro.subscribe(@render)
|
||||
@render()
|
||||
|
||||
release: =>
|
||||
App.Macro.unsubscribe(@subscribeId)
|
||||
|
||||
render: =>
|
||||
macros = App.Macro.all()
|
||||
if _.isEmpty(macros) || !@isRole('Agent')
|
||||
macroDisabled = true
|
||||
@html App.view('ticket_zoom/attribute_bar')(
|
||||
macros: macros
|
||||
macroDisabled: macroDisabled
|
||||
)
|
||||
|
||||
toggleDropdownMacro: =>
|
||||
if @buttonDropdown.hasClass 'is-open'
|
||||
@closeMacroDropdown()
|
||||
else
|
||||
@buttonDropdown.addClass 'is-open'
|
||||
$(document).bind 'click.buttonDropdown', @closeMacroDropdown
|
||||
|
||||
closeMacroDropdown: =>
|
||||
@buttonDropdown.removeClass 'is-open'
|
||||
$(document).unbind 'click.buttonDropdown'
|
||||
|
||||
performTicketMacro: (e) =>
|
||||
macroId = $(e.target).data('id')
|
||||
console.log "perform action", @$(e.currentTarget).text(), macroId
|
||||
macro = App.Macro.find(macroId)
|
||||
|
||||
@callback(e, macro.perform)
|
||||
@closeMacroDropdown()
|
||||
|
||||
onActionMacroMouseEnter: (e) =>
|
||||
@$(e.currentTarget).addClass('is-active')
|
||||
|
||||
onActionMacroMouseLeave: (e) =>
|
||||
@$(e.currentTarget).removeClass('is-active')
|
|
@ -50,14 +50,14 @@ class App.TicketZoomSidebar extends App.Controller
|
|||
|
||||
if !@isRole('Customer')
|
||||
el.append('<div class="tags"></div>')
|
||||
new App.WidgetTag(
|
||||
@tagWidget = new App.WidgetTag(
|
||||
el: el.find('.tags')
|
||||
object_type: 'Ticket'
|
||||
object: ticket
|
||||
tags: @tags
|
||||
)
|
||||
el.append('<div class="links"></div>')
|
||||
new App.WidgetLink(
|
||||
@linkWidget = new App.WidgetLink(
|
||||
el: el.find('.links')
|
||||
object_type: 'Ticket'
|
||||
object: ticket
|
||||
|
|
|
@ -65,8 +65,10 @@ class App.WidgetTag extends App.Controller
|
|||
e.preventDefault()
|
||||
item = @$('[name="new_tag"]').val()
|
||||
return if !item
|
||||
@add(item)
|
||||
|
||||
if _.contains(@tagList, item)
|
||||
add: (item) =>
|
||||
if _.contains(@tags, item)
|
||||
@render()
|
||||
return
|
||||
|
||||
|
@ -90,6 +92,10 @@ class App.WidgetTag extends App.Controller
|
|||
item = $(e.target).parents('li').find('.js-tag').text()
|
||||
return if !item
|
||||
|
||||
@remove(item)
|
||||
|
||||
remove: (item) =>
|
||||
|
||||
@tags = _.filter(@tags, (tagItem) -> return tagItem if tagItem isnt item )
|
||||
@render()
|
||||
|
||||
|
|
|
@ -26,6 +26,9 @@ class App.PrettyDate
|
|||
diff = diff.toString().replace('-', '')
|
||||
diff = parseFloat(diff)
|
||||
|
||||
if diff < 60
|
||||
return App.i18n.translateInline('just now')
|
||||
|
||||
if direction is 'past' && !escalation && diff > ( 60 * 60 * 24 * 14 )
|
||||
return App.i18n.translateDate(time)
|
||||
|
||||
|
|
20
app/assets/javascripts/app/models/macro.coffee
Normal file
20
app/assets/javascripts/app/models/macro.coffee
Normal file
|
@ -0,0 +1,20 @@
|
|||
class App.Macro extends App.Model
|
||||
@configure 'Macro', 'name', 'perform', 'active'
|
||||
@extend Spine.Model.Ajax
|
||||
@url: @apiPath + '/macros'
|
||||
@configure_attributes = [
|
||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false },
|
||||
{ name: 'perform', display: 'Execute changes on objects.', tag: 'ticket_perform_action', null: true },
|
||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
||||
{ name: 'note', display: 'Note', tag: 'textarea', limit: 250, null: true },
|
||||
{ name: 'active', display: 'Active', tag: 'active', default: true },
|
||||
]
|
||||
@configure_delete = true
|
||||
@configure_overview = [
|
||||
'name',
|
||||
]
|
||||
|
||||
@description = '''
|
||||
Macros are....
|
||||
|
||||
'''
|
|
@ -6,6 +6,7 @@
|
|||
<%- @Icon('arrow-down', 'dropdown-arrow') %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="controls js-operator"></div>
|
||||
<div class="controls js-value"></div>
|
||||
</div>
|
||||
<div class="filter-controls">
|
||||
|
|
|
@ -634,7 +634,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="attributeBar">
|
||||
<div class="btn js-reset hide">Discard your unsaved changes.</div>
|
||||
<div class="btn js-reset">Discard your unsaved changes.</div>
|
||||
<div class="buttonDropdown dropdown dropup">
|
||||
<div class="btn btn--primary btn--split--first js-submit">Update</div>
|
||||
<div class="btn btn--primary btn--slim btn--split--last js-openDropdown"><%- @Icon('arrow-up') %></div>
|
||||
|
|
|
@ -25,8 +25,5 @@
|
|||
|
||||
<div class="tabsSidebar tabsSidebar--attributeBarSpacer vertical"></div>
|
||||
|
||||
<div class="attributeBar">
|
||||
<div class="btn js-reset hide"><%- @T('Discard your unsaved changes.') %></div>
|
||||
<div class="btn btn--primary js-submit"><%- @T('Update') %></div>
|
||||
</div>
|
||||
<div class="attributeBar js-attributeBar"></div>
|
||||
</div>
|
|
@ -0,0 +1,14 @@
|
|||
<div class="btn js-reset hide"><%- @T('Discard your unsaved changes.') %></div>
|
||||
<% if @macroDisabled: %>
|
||||
<div class="btn btn--primary js-submit"><%- @T('Update') %></div>
|
||||
<% else: %>
|
||||
<div class="buttonDropdown dropdown dropup">
|
||||
<div class="btn btn--primary btn--split--first js-submit"><%- @T('Update') %></div>
|
||||
<div class="btn btn--primary btn--slim btn--split--last js-openDropdownMacro"><%- @Icon('arrow-up') %></div>
|
||||
<ul class="dropdown-menu dropdown-menu-right" role="menu" aria-labelledby="userAction">
|
||||
<% for macro in @macros: %>
|
||||
<li class="js-dropdownActionMacro" role="menuitem" data-id="<%= macro.id %>"><%- @T(macro.displayName()) %>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
<% end %>
|
155
app/controllers/macros_controller.rb
Normal file
155
app/controllers/macros_controller.rb
Normal file
|
@ -0,0 +1,155 @@
|
|||
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
class MacrosController < ApplicationController
|
||||
before_action :authentication_check
|
||||
|
||||
=begin
|
||||
|
||||
Format:
|
||||
JSON
|
||||
|
||||
Example:
|
||||
{
|
||||
"id":1,
|
||||
"name":"some text_module",
|
||||
"perform":{
|
||||
"ticket.priority_id": 5,
|
||||
"ticket.state_id": 2,
|
||||
},
|
||||
"active":true,
|
||||
"updated_at":"2012-09-14T17:51:53Z",
|
||||
"created_at":"2012-09-14T17:51:53Z",
|
||||
"updated_by_id":2,
|
||||
"created_by_id":2,
|
||||
}
|
||||
|
||||
=end
|
||||
|
||||
=begin
|
||||
|
||||
Resource:
|
||||
GET /api/v1/macros.json
|
||||
|
||||
Response:
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"name": "some_name1",
|
||||
...
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "some_name2",
|
||||
...
|
||||
}
|
||||
]
|
||||
|
||||
Test:
|
||||
curl http://localhost/api/v1/macros.json -v -u #{login}:#{password}
|
||||
|
||||
=end
|
||||
|
||||
def index
|
||||
model_index_render(Macro, params)
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
Resource:
|
||||
GET /api/v1/macros/#{id}.json
|
||||
|
||||
Response:
|
||||
{
|
||||
"id": 1,
|
||||
"name": "name_1",
|
||||
...
|
||||
}
|
||||
|
||||
Test:
|
||||
curl http://localhost/api/v1/macros/#{id}.json -v -u #{login}:#{password}
|
||||
|
||||
=end
|
||||
|
||||
def show
|
||||
model_show_render(Macro, params)
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
Resource:
|
||||
POST /api/v1/macros.json
|
||||
|
||||
Payload:
|
||||
{
|
||||
"name": "some name",
|
||||
"perform":{
|
||||
"ticket.priority_id": 5,
|
||||
"ticket.state_id": 2,
|
||||
},
|
||||
"active":true,
|
||||
}
|
||||
|
||||
Response:
|
||||
{
|
||||
"id": 1,
|
||||
"name": "some_name",
|
||||
...
|
||||
}
|
||||
|
||||
Test:
|
||||
curl http://localhost/api/v1/macros.json -v -u #{login}:#{password} -H "Content-Type: application/json" -X POST -d '{"name": "some_name","active": true, "note": "some note"}'
|
||||
|
||||
=end
|
||||
|
||||
def create
|
||||
model_create_render(Macro, params)
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
Resource:
|
||||
PUT /api/v1/macros/{id}.json
|
||||
|
||||
Payload:
|
||||
{
|
||||
"name": "some name",
|
||||
"perform":{
|
||||
"ticket.priority_id": 5,
|
||||
"ticket.state_id": 2,
|
||||
},
|
||||
"active":true,
|
||||
}
|
||||
|
||||
Response:
|
||||
{
|
||||
"id": 1,
|
||||
"name": "some_name",
|
||||
...
|
||||
}
|
||||
|
||||
Test:
|
||||
curl http://localhost/api/v1/macros.json -v -u #{login}:#{password} -H "Content-Type: application/json" -X PUT -d '{"name": "some_name","active": true, "note": "some note"}'
|
||||
|
||||
=end
|
||||
|
||||
def update
|
||||
model_update_render(Macro, params)
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
Resource:
|
||||
DELETE /api/v1/macros/{id}.json
|
||||
|
||||
Response:
|
||||
{}
|
||||
|
||||
Test:
|
||||
curl http://localhost/api/v1/macros.json -v -u #{login}:#{password} -H "Content-Type: application/json" -X DELETE
|
||||
|
||||
=end
|
||||
|
||||
def destroy
|
||||
model_destory_render(Macro, params)
|
||||
end
|
||||
end
|
|
@ -4,6 +4,10 @@ module ExtraCollection
|
|||
def session( collections, assets, user )
|
||||
|
||||
# all ticket stuff
|
||||
collections[ Macro.to_app_model ] = []
|
||||
Macro.all.each {|item|
|
||||
assets = item.assets(assets)
|
||||
}
|
||||
collections[ Ticket::StateType.to_app_model ] = []
|
||||
Ticket::StateType.all.each {|item|
|
||||
assets = item.assets(assets)
|
||||
|
|
7
app/models/macro.rb
Normal file
7
app/models/macro.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
class Macro < ApplicationModel
|
||||
store :perform
|
||||
validates :name, presence: true
|
||||
|
||||
end
|
11
config/routes/macro.rb
Normal file
11
config/routes/macro.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
Zammad::Application.routes.draw do
|
||||
api_path = Rails.configuration.api_path
|
||||
|
||||
# macros
|
||||
match api_path + '/macros', to: 'macros#index', via: :get
|
||||
match api_path + '/macros/:id', to: 'macros#show', via: :get
|
||||
match api_path + '/macros', to: 'macros#create', via: :post
|
||||
match api_path + '/macros/:id', to: 'macros#update', via: :put
|
||||
match api_path + '/macros/:id', to: 'macros#destroy', via: :delete
|
||||
|
||||
end
|
34
db/migrate/20151015000001_create_macro.rb
Normal file
34
db/migrate/20151015000001_create_macro.rb
Normal file
|
@ -0,0 +1,34 @@
|
|||
class CreateMacro < ActiveRecord::Migration
|
||||
def up
|
||||
create_table :macros do |t|
|
||||
t.string :name, limit: 250, null: true
|
||||
t.string :perform, limit: 5000, null: false
|
||||
t.boolean :active, null: false, default: true
|
||||
t.string :note, limit: 250, null: true
|
||||
t.integer :updated_by_id, null: false
|
||||
t.integer :created_by_id, null: false
|
||||
t.timestamps null: false
|
||||
end
|
||||
add_index :macros, [:name], unique: true
|
||||
|
||||
UserInfo.current_user_id = 1
|
||||
Macro.create_or_update(
|
||||
name: 'Close & Tag as Spam',
|
||||
perform: {
|
||||
'ticket.state_id': {
|
||||
value: Ticket::State.find_by(name: 'closed').id,
|
||||
},
|
||||
'ticket.tags': {
|
||||
operator: 'add',
|
||||
value: 'spam',
|
||||
},
|
||||
},
|
||||
note: 'example macro',
|
||||
active: true,
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
drop_table :macros
|
||||
end
|
||||
end
|
15
db/seeds.rb
15
db/seeds.rb
|
@ -1572,6 +1572,21 @@ Ticket::Article::Sender.create_if_not_exists( id: 1, name: 'Agent' )
|
|||
Ticket::Article::Sender.create_if_not_exists( id: 2, name: 'Customer' )
|
||||
Ticket::Article::Sender.create_if_not_exists( id: 3, name: 'System' )
|
||||
|
||||
Macro.create_if_not_exists(
|
||||
name: 'Close & Tag as Spam',
|
||||
perform: {
|
||||
'ticket.state_id': {
|
||||
value: Ticket::State.find_by(name: 'closed').id,
|
||||
},
|
||||
'ticket.tags': {
|
||||
operator: 'add',
|
||||
value: 'spam',
|
||||
},
|
||||
},
|
||||
note: 'example macro',
|
||||
active: true,
|
||||
)
|
||||
|
||||
UserInfo.current_user_id = user_community.id
|
||||
ticket = Ticket.create(
|
||||
group_id: Group.where( name: 'Users' ).first.id,
|
||||
|
|
4
lib/sessions/backend/collections/macro.rb
Normal file
4
lib/sessions/backend/collections/macro.rb
Normal file
|
@ -0,0 +1,4 @@
|
|||
class Sessions::Backend::Collections::Macors < Sessions::Backend::Collections::Base
|
||||
model_set 'Macro'
|
||||
add_if_not_role 'Customer'
|
||||
end
|
|
@ -137,6 +137,10 @@ test( 'form checks', function() {
|
|||
'ticket.priority_id': {
|
||||
value: 3,
|
||||
},
|
||||
'ticket.tags': {
|
||||
operator: 'remove',
|
||||
value: 'tag1, tag2',
|
||||
},
|
||||
},
|
||||
}
|
||||
new App.ControllerForm({
|
||||
|
@ -193,6 +197,10 @@ test( 'form checks', function() {
|
|||
'ticket.priority_id': {
|
||||
value: '3',
|
||||
},
|
||||
'ticket.tags': {
|
||||
operator: 'remove',
|
||||
value: 'tag1, tag2',
|
||||
},
|
||||
},
|
||||
working_hours: {
|
||||
mon: {
|
||||
|
@ -328,6 +336,10 @@ test( 'form checks', function() {
|
|||
'ticket.priority_id': {
|
||||
value: '3',
|
||||
},
|
||||
'ticket.tags': {
|
||||
operator: 'remove',
|
||||
value: 'tag1, tag2',
|
||||
},
|
||||
},
|
||||
}
|
||||
deepEqual( params, test_params, 'form param check' );
|
||||
|
|
|
@ -5,7 +5,10 @@ test( "check pretty date", function() {
|
|||
|
||||
// past
|
||||
var result = App.PrettyDate.humanTime( current );
|
||||
equal( result, '0 minutes ago', 'right now')
|
||||
equal( result, 'just now', 'just now')
|
||||
|
||||
result = App.PrettyDate.humanTime( current - 15000 );
|
||||
equal( result, 'just now', 'just now')
|
||||
|
||||
result = App.PrettyDate.humanTime( current - 60000 );
|
||||
equal( result, '1 minute ago', '1 min ago')
|
||||
|
@ -60,7 +63,10 @@ test( "check pretty date", function() {
|
|||
// future
|
||||
current = new Date()
|
||||
result = App.PrettyDate.humanTime( current );
|
||||
equal( result, '0 minutes ago', 'right now')
|
||||
equal( result, 'just now', 'just now')
|
||||
|
||||
result = App.PrettyDate.humanTime( current.getTime() + 55000 );
|
||||
equal( result, 'just now', 'just now')
|
||||
|
||||
result = App.PrettyDate.humanTime( current.getTime() + 65000 );
|
||||
equal( result, 'in 1 minute', 'in 1 min')
|
||||
|
|
Loading…
Reference in a new issue