Improved modal and added generic actions.

This commit is contained in:
Martin Edenhofer 2014-09-21 21:58:07 +02:00
parent 5b3cae547c
commit 3ed77d985e
20 changed files with 297 additions and 222 deletions

View file

@ -456,7 +456,6 @@ class App.ControllerModal extends App.Controller
@show()
show: ->
console.log('M', @message, @el.length)
if @button is true
@button = 'Submit'

View file

@ -359,41 +359,21 @@ class App.GenericHistory extends App.ControllerModal
@head = 'History'
@close = true
render: ( items, orderClass = '' ) ->
render: ->
for item in items
item.link = ''
item.title = '???'
if item.object is 'Ticket::Article'
item.object = 'Article'
article = App.TicketArticle.find( item.o_id )
ticket = App.Ticket.find( article.ticket_id )
item.title = article.subject || ticket.title
item.link = article.uiUrl()
if App[item.object]
object = App[item.object].find( item.o_id )
item.link = object.uiUrl()
item.title = object.displayName()
item.created_by = App.User.find( item.created_by_id )
# set cache
@historyListCache = items
localItem = @reworkItems( @items )
@html App.view('generic/history')(
items: items
orderClass: orderClass
@historyListCache
items: localItem
)
@onShow()
@el.find('a[data-type="sortorder"]').bind(
'click',
(e) =>
e.preventDefault()
@sortorder(e)
@sortorder()
)
if !@isShown
@isShown = true
@ -404,16 +384,95 @@ class App.GenericHistory extends App.ControllerModal
@userPopups()
# show frontend times
@delay( @frontendTimeUpdate, 100, 'ui-time-update' )
@delay( @frontendTimeUpdate, 800, 'ui-time-update' )
sortorder: (e) ->
e.preventDefault()
isDown = @el.find('[data-type="sortorder"]').hasClass('down')
sortorder: =>
@items = @items.reverse()
if isDown
@render( @historyListCache, 'up' )
@render()
T: (name) ->
App.i18n.translateInline(name)
reworkItems: (items) ->
newItems = []
newItem = {}
lastUserId = undefined
lastTime = undefined
items = clone(items)
for item in items
if item.object is 'Ticket::Article'
item.object = 'Article'
data = item
data.created_by = App.User.find( item.created_by_id )
currentItemTime = new Date( item.created_at )
lastItemTime = new Date( new Date( lastTime ).getTime() + (15 * 1000) )
# start new section if user or time has changed
if lastUserId isnt item.created_by_id || currentItemTime > lastItemTime
lastTime = item.created_at
lastUserId = item.created_by_id
if !_.isEmpty(newItem)
newItems.push newItem
newItem =
created_at: item.created_at
created_by: App.User.find( item.created_by_id )
records: []
# build content
content = ''
if item.type is 'notification' || item.type is 'email'
content = "#{ @T( item.type ) } #{ @T( 'sent to' ) } #{ item.value_to }"
else
@render( @historyListCache.reverse(), 'down' )
content = "#{ @T( item.type ) } #{ @T(item.object) } "
if item.attribute
content += "#{ @T(item.attribute) }"
# convert time stamps
if item.object is 'User' && item.attribute is 'last_login'
if item.value_from
item.value_from = App.i18n.translateTimestamp( item.value_from )
if item.value_to
item.value_to = App.i18n.translateTimestamp( item.value_to )
if item.value_from
if item.value_to
content += " #{ @T( 'from' ) }"
content += " '#{ item.value_from }'"
if item.value_to
if item.value_from
content += " #{ @T( 'to' ) }"
content += " '#{ item.value_to }'"
newItem.records.push content
if !_.isEmpty(newItem)
newItems.push newItem
newItems
class App.ActionRow extends App.Controller
constructor: ->
super
@render()
render: ->
@html App.view('generic/actions')(
items: @items
)
for item in @items
do (item) =>
@el.find('[data-type="' + item.name + '"]').on(
'click',
(e) =>
e.preventDefault()
item.callback()
)
class App.Sidebar extends App.Controller
events:

View file

@ -1,15 +1,18 @@
class App.TicketMerge extends App.ControllerModal
constructor: ->
super
@head = 'Merge'
@button = true
@cancel = true
@fetch()
fetch: ->
# merge tickets
@ajax(
id: 'ticket_merge_list'
id: 'ticket_related'
type: 'GET'
url: @apiPath + '/ticket_merge_list/' + @ticket.id
url: @apiPath + '/ticket_related/' + @ticket.id
processData: true,
success: (data, status, xhr) =>
@ -18,7 +21,6 @@ class App.TicketMerge extends App.ControllerModal
@ticket_ids_by_customer = data.ticket_ids_by_customer
@ticket_ids_recent_viewed = data.ticket_ids_recent_viewed
@render()
)

View file

@ -15,6 +15,8 @@ class App.OrganizationHistory extends App.GenericHistory
# load assets
App.Collection.loadAssets( data.assets )
@items = data.history
# render page
@render(data.history)
@render()
)

View file

@ -64,10 +64,19 @@ class App.OrganizationZoom extends App.Controller
)
# start action controller
new ActionRow(
showHistory = =>
new App.OrganizationHistory( organization_id: organization.id )
actions = [
{
name: 'history'
title: 'History'
callback: showHistory
}
]
new App.ActionRow(
el: @el.find('.action')
organization: organization
ui: @
items: actions
)
new Sidebar(
@ -168,21 +177,6 @@ class Sidebar extends App.Controller
items: items
)
class ActionRow extends App.Controller
events:
'click [data-type=history]': 'history_dialog'
constructor: ->
super
@render()
render: ->
@html App.view('user_zoom/actions')()
history_dialog: (e) ->
e.preventDefault()
new App.OrganizationHistory( organization_id: @organization.id )
class Router extends App.ControllerPermanent
constructor: (params) ->
super

View file

@ -9,12 +9,14 @@ class App.TicketHistory extends App.GenericHistory
@ajax(
id: 'ticket_history',
type: 'GET',
url: @apiPath + '/ticket_history/' + @ticket.id,
url: @apiPath + '/ticket_history/' + @ticket_id,
success: (data, status, xhr) =>
# load assets
App.Collection.loadAssets( data.assets )
@items = data.history
# render page
@render(data.history)
@render()
)

View file

@ -162,6 +162,28 @@ class App.TicketZoom extends App.Controller
object_type: 'Ticket'
object: @ticket
)
el.append('<div class="action"></div>')
showHistory = =>
new App.TicketHistory( ticket_id: @ticket.id )
showMerge = =>
new App.TicketMerge( ticket: @ticket, task_key: @task_key )
actions = [
{
name: 'history'
title: 'History'
callback: showHistory
},
{
name: 'merge'
title: 'Merge'
callback: showMerge
},
]
new App.ActionRow(
el: @el.find('.action')
items: actions
)
items = [
{
head: 'Ticket Settings'
@ -275,7 +297,6 @@ class App.TicketZoom extends App.Controller
)
###
@TicketAction()
@ArticleView()
if force || !@editDone
@ -323,18 +344,6 @@ class App.TicketZoom extends App.Controller
ui: @
)
TicketAction: =>
# start action controller
if !@isRole('Customer')
new ActionRow(
el: @el.find('.action')
ticket: @ticket
ui: @
)
# enable user popups
@userPopups()
class TicketTitle extends App.Controller
events:
'blur .ticket-title-update': 'update'
@ -1212,26 +1221,6 @@ class Article extends App.Controller
for attachment in @article.attachments
attachment.size = @humanFileSize(attachment.size)
class ActionRow extends App.Controller
events:
'click [data-type=history]': 'history_dialog'
'click [data-type=merge]': 'merge_dialog'
constructor: ->
super
@render()
render: ->
@html App.view('ticket_zoom/actions')()
history_dialog: (e) ->
e.preventDefault()
new App.TicketHistory( ticket: @ticket )
merge_dialog: (e) ->
e.preventDefault()
new App.TicketMerge( ticket: @ticket, task_key: @ui.task_key )
class TicketZoomRouter extends App.ControllerPermanent
constructor: (params) ->
super

View file

@ -15,6 +15,8 @@ class App.UserHistory extends App.GenericHistory
# load assets
App.Collection.loadAssets( data.assets )
@items = data.history
# render page
@render(data.history)
@render()
)

View file

@ -63,10 +63,19 @@ class App.UserZoom extends App.Controller
)
# start action controller
new ActionRow(
showHistory = =>
new App.UserHistory( user_id: user.id )
actions = [
{
name: 'history'
title: 'History'
callback: showHistory
}
]
new App.ActionRow(
el: @el.find('.action')
user: user
ui: @
items: actions
)
new Sidebar(
@ -218,22 +227,6 @@ class Sidebar extends App.Controller
items: items
)
class ActionRow extends App.Controller
events:
'click [data-type=history]': 'history_dialog'
constructor: ->
super
@render()
render: ->
@html App.view('user_zoom/actions')()
history_dialog: (e) ->
e.preventDefault()
new App.UserHistory( user_id: @user.id )
class Router extends App.ControllerPermanent
constructor: (params) ->
super

View file

@ -74,10 +74,10 @@ class App.WidgetLink extends App.Controller
add: (e) =>
e.preventDefault()
new App.LinkAdd(
link_object: @object_type,
link_object_id: @object.id,
object: @object,
parent: @,
link_object: @object_type
link_object_id: @object.id
object: @object
parent: @
)
class App.LinkAdd extends App.ControllerModal
@ -87,17 +87,86 @@ class App.LinkAdd extends App.ControllerModal
@button = true
@cancel = true
@ticket = @object
@fetch()
fetch: ->
# merge tickets
@ajax(
id: 'ticket_related'
type: 'GET'
url: @apiPath + '/ticket_related/' + @ticket.id
processData: true,
success: (data, status, xhr) =>
# load assets
App.Collection.loadAssets( data.assets )
@ticket_ids_by_customer = data.ticket_ids_by_customer
@ticket_ids_recent_viewed = data.ticket_ids_recent_viewed
@render()
)
render: ->
@html App.view('link/add')(
link_object: @link_object,
link_object_id: @link_object_id,
object: @object,
)
list = []
for ticket_id in @ticket_ids_by_customer
if ticket_id isnt @ticket.id
ticketItem = App.Ticket.fullLocal( ticket_id )
list.push ticketItem
new App.ControllerTable(
el: @el.find('#ticket-merge-customer-tickets'),
overview: [ 'number', 'title', 'state', 'group', 'created_at' ]
model: App.Ticket,
objects: list,
radio: true,
)
list = []
for ticket_id in @ticket_ids_recent_viewed
if ticket_id isnt @ticket.id
ticketItem = App.Ticket.fullLocal( ticket_id )
list.push ticketItem
new App.ControllerTable(
el: @el.find('#ticket-merge-recent-tickets'),
overview: [ 'number', 'title', 'state', 'group', 'created_at' ]
model: App.Ticket,
objects: list,
radio: true,
)
@el.delegate('[name="ticket_number"]', 'focus', (e) ->
$(e.target).parents().find('[name="radio"]').prop( 'checked', false )
)
@el.delegate('[name="radio"]', 'click', (e) ->
if $(e.target).prop('checked')
ticket_id = $(e.target).val()
ticket = App.Ticket.fullLocal( ticket_id )
$(e.target).parents().find('[name="ticket_number"]').val( ticket.number )
)
@show()
onSubmit: (e) =>
e.preventDefault()
params = @formParam(e.target)
if !params['ticket_number']
alert('Ticket# is needed!')
return
if !params['link_type']
alert('Link type is needed!')
return
# get data
@ajax(
id: 'links_add_' + @object.id + '_' + @object_type,

View file

@ -1,26 +1,10 @@
<form class="form-horizontal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<div class="modal-close js-close">
<div class="close icon"></div>
</div>
<h1 class="modal-title"><%- @T( 'Merge' ) %></h1>
</div>
<div class="modal-body">
<div>
<h4><%- @T( 'Merge to Ticket#' ) %></h4>
<input type="text" name="master_ticket_number" class="form-control" value=""/>
<hr>
<h4><%- @T( 'Recent Customer Tickets' ) %></h4>
<div id="ticket-merge-customer-tickets"></div>
<hr>
<h4><%- @T( 'Recent Views Tickets' ) %></h4>
<h4><%- @T( 'Recent viewed Tickets' ) %></h4>
<div id="ticket-merge-recent-tickets"></div>
</div>
<div class="modal-footer horizontal">
<a class="subtle-link standalone js-cancel" href="#/"><%- @T( 'Cancel & Go Back' ) %></a>
<button type="submit" class="btn btn--create js-submit align-right"><%- @T( 'Submit' ) %></button>
</div>
</div>
</div>
</form>

View file

@ -1,6 +1,8 @@
<div class="dropdown dropup actions">
<button class="btn" data-toggle="dropdown"><%- @T('Action') %> <span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a href="#" data-type="history"><%- @T( 'History' ) %></a></li>
<% for item in @items: %>
<li><a href="#" data-type="<%= item.name %>"><%- @T( item.title ) %></a></li>
<% end %>
</ul>
</div>

View file

@ -1,49 +1,17 @@
<div>
<a href="#" data-type="sortorder" class="<%= @orderClass %>"><%- @T( 'Change order' ) %></a>
<a href="#" data-type="sortorder"><%- @T( 'Change order' ) %></a>
<hr>
<% open = false %>
<% for item in @items: %>
<% if lasttime isnt item['created_at'] || last_user isnt item['created_by_id']: %>
<% if open: %>
</ul>
<hr>
<% end %>
<% open = true %>
<% last_user = item['created_by_id'] %>
<% lasttime = item['created_at'] %>
<span class="user-popover" data-id="<%= item.created_by.id %>"><%= item.created_by.displayName() %></span> -
<span class="humanTimeFromNow" data-time="<%- item.created_at %>">?</span>
<ul>
<% for content in item.records: %>
<li><%- content %></li>
<% end %>
<li>
<% if ( item['type'] is 'notification' || item['type'] is 'email' ): %>
<%- @T( item['type'] ) %>
<% if item['value_from']: %>
"<%= item['value_from'] %>" <%- @T( 'sent to' ) %>
<% end %>
<% if item['value_to']: %>
"<%= item['value_to'] %>"
<% end %>
<% else: %>
<%- @T( item['type'] ) %> <%= item['object'] %> <% if item['attribute']: %>"<%= item['attribute'] %>"<% end %>
<% if item['value_from']: %>
<% if item['value_to']: %>
<%- @T( 'from' ) %>
<% end %>
"<%= item['value_from'] %>"
<% end %>
<% if item['value_to']: %>
<% if item['value_from']: %>
<%- @T( 'to' ) %>
<% end %>
"<%= item['value_to'] %>"
<% end %>
<% end %>
</li>
<% end %>
<% if open: %>
</ul>
<hr>
<% end %>
</div>

View file

@ -12,11 +12,11 @@
<%- @T( 'of' ) %>
Ticket#
<%= @object.number %>.
<!--
<ul>
<li>Ticket#</li>
<li>Recent Views Tickets</li>
<li>Recent Customer Tickets</li>
</ul>
-->
<hr>
<h4><%- @T( 'Recent Customer Tickets' ) %></h4>
<div id="ticket-merge-customer-tickets"></div>
<hr>
<h4><%- @T( 'Recent viewed Tickets' ) %></h4>
<div id="ticket-merge-recent-tickets"></div>
</fieldset>

View file

@ -1,12 +1,18 @@
<div class="main flex tabsSidebarSpace">
<div class="flex vertical">
<div class="flex u-positionOrigin horizontal">
<div class="main flex tabsSidebarSpace">
<div class="organizationZoom">
<div class="page-header">
<h1><%- @T( @head ) %></h1>
</div>
<div class="main-overviews" id="sortable"></div>
</div>
</div>
</div>
<div class="tabsSidebar vertical"></div>
<div class="tabsSidebar vertical"></div>
</div>
<form class="bottom-form form-inline horizontal" role="form">
<div class="action"></div>
</form>
</div>

View file

@ -1,8 +0,0 @@
<div class="btn-group dropup">
<button type="button" class="btn btn-default dropdown-toggle actions" data-toggle="dropdown"><%- @T('Action') %> <span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li><a href="#" data-type="history"><%- @T( 'History' ) %></a></li>
<li><a href="#" data-type="merge"><%- @T( 'Merge' ) %></a></li>
</ul>
</div>

View file

@ -7,7 +7,6 @@
</div>
<div class="main-overviews" id="sortable"></div>
</div>
</div>

View file

@ -137,17 +137,24 @@ class TicketsController < ApplicationController
render :json => history
end
# GET /api/v1/ticket_merge_list/1
def ticket_merge_list
# GET /api/v1/ticket_related/1
def ticket_related
ticket = Ticket.find( params[:ticket_id] )
assets = ticket.assets({})
# open tickets by customer
group_ids = Group.select( 'groups.id' ).joins(:users).
where( 'groups_users.user_id = ?', current_user.id ).
where( 'groups.active = ?', true ).
map( &:id )
access_condition = [ 'group_id IN (?)', group_ids ]
ticket_list = Ticket.where(
:customer_id => ticket.customer_id,
:state_id => Ticket::State.by_category( 'open' )
)
.where(access_condition)
.where( 'id != ?', [ ticket.id ] )
.order('created_at DESC')
.limit(6)
@ -161,9 +168,9 @@ class TicketsController < ApplicationController
ticket_ids_recent_viewed = []
ticket_recent_view = RecentView.list( current_user, 8 )
ticket_recent_view = RecentView.list( current_user, 8, 'Ticket' )
ticket_recent_view.each {|item|
if item['recent_view_object'] == 'Ticket'
if item['object'] == 'Ticket'
ticket_ids_recent_viewed.push item['o_id']
ticket = Ticket.find( item['o_id'] )
assets = ticket.assets(assets)

View file

@ -32,10 +32,16 @@ class RecentView < ApplicationModel
RecentView.where( :created_by_id => user.id ).destroy_all
end
def self.list( user, limit = 10 )
def self.list( user, limit = 10, type = nil )
if !type
recent_views = RecentView.where( :created_by_id => user.id ).
order('created_at DESC, id DESC').
limit(limit)
else
recent_views = RecentView.select('DISTINCT(o_id), recent_view_object_id').where( :created_by_id => user.id, :recent_view_object_id => ObjectLookup.by_name(type) ) .
order('created_at DESC, id DESC').
limit(limit)
end
list = []
recent_views.each { |item|

View file

@ -11,7 +11,7 @@ Zammad::Application.routes.draw do
match api_path + '/ticket_full/:id', :to => 'tickets#ticket_full', :via => :get
match api_path + '/ticket_history/:id', :to => 'tickets#ticket_history', :via => :get
match api_path + '/ticket_customer', :to => 'tickets#ticket_customer', :via => :get
match api_path + '/ticket_merge_list/:ticket_id', :to => 'tickets#ticket_merge_list', :via => :get
match api_path + '/ticket_related/:ticket_id', :to => 'tickets#ticket_related', :via => :get
match api_path + '/ticket_merge/:slave_ticket_id/:master_ticket_number', :to => 'tickets#ticket_merge', :via => :get
# ticket overviews