<%- @T('Selector') %>
+<%- @T('Enable time accounting for following matching tickets.') %>
+ +<%- @T('Overviews') %>
+<%- @T('Ticket') %>
+ ++
<%- @T('Customer') %>
+ ++
diff --git a/app/assets/javascripts/app/controllers/ticket_zoom.coffee b/app/assets/javascripts/app/controllers/ticket_zoom.coffee index 9890278d2..72c909783 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom.coffee @@ -428,6 +428,8 @@ class App.TicketZoom extends App.Controller callback: @submit task_key: @task_key ) + #if @shown + # @attributeBar.start() @form_id = App.ControllerForm.formId() @@ -660,7 +662,7 @@ class App.TicketZoom extends App.Controller taskAction = @$('.js-secondaryActionButtonLabel').data('type') - ticketParams = @formParam( @$('.edit') ) + ticketParams = @formParam(@$('.edit')) # validate ticket ticket = App.Ticket.find(@ticket_id) @@ -745,6 +747,35 @@ class App.TicketZoom extends App.Controller ticket.article = article + if !ticket.article + @submitPost(e, ticket) + return + + # verify if time accounting is enabled + if @Config.get('time_accounting') isnt true + @submitPost(e, ticket) + return + + + # verify if time accounting is active for ticket + if false + @submitPost(e, ticket) + return + + # time tracking + new App.TicketZoomTimeAccounting( + container: @el.closest('.content') + ticket: ticket + cancelCallback: => + @formEnable(e) + submitCallback: (params) => + if params.time_unit + ticket.article.time_unit = params.time_unit + @submitPost(e, ticket) + ) + + submitPost: (e, ticket) => + # submit changes @ajax( id: "ticket_update_#{ticket.id}" diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/sidebar.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/sidebar.coffee index 7c6d58e6d..2dd77dcb2 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom/sidebar.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom/sidebar.coffee @@ -42,7 +42,7 @@ class App.TicketZoomSidebar extends App.ObserverController render: (ticket) => editTicket = (el) => - el.append('
') + el.append(App.view('ticket_zoom/sidebar_ticket')()) @edit = new Edit( object_id: ticket.id @@ -52,7 +52,7 @@ class App.TicketZoomSidebar extends App.ObserverController markForm: @markForm ) - if !@permissionCheck('ticket.customer') + if @permissionCheck('ticket.agent') @tagWidget = new App.WidgetTag( el: @el.find('.tags') object_type: 'Ticket' @@ -66,6 +66,11 @@ class App.TicketZoomSidebar extends App.ObserverController links: @links ) + @timeUnitWidget = new App.TicketZoomTimeUnit( + el: @el.find('.js-timeUnit') + object_id: ticket.id + ) + showTicketHistory = => new App.TicketHistory( ticket_id: ticket.id diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/time_accounting.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/time_accounting.coffee new file mode 100644 index 000000000..ae7df3cda --- /dev/null +++ b/app/assets/javascripts/app/controllers/ticket_zoom/time_accounting.coffee @@ -0,0 +1,20 @@ +class App.TicketZoomTimeAccounting extends App.ControllerModal + buttonClose: true + buttonCancel: 'skip' + buttonSubmit: 'Account Time' + buttonClass: 'btn--success' + head: 'Time Accounting' + small: true + + content: -> + App.view('ticket_zoom/time_accounting')() + + onCancel: => + if @cancelCallback + @cancelCallback() + + onSubmit: => + @close() + if @submitCallback + params = @formParams() + @submitCallback(params) diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/time_unit.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/time_unit.coffee new file mode 100644 index 000000000..b5ecd023c --- /dev/null +++ b/app/assets/javascripts/app/controllers/ticket_zoom/time_unit.coffee @@ -0,0 +1,11 @@ +class App.TicketZoomTimeUnit extends App.ObserverController + model: 'Ticket' + observe: + time_unit: true + + render: (ticket) => + return if !@permissionCheck('ticket.agent') + return if !ticket.time_unit + @html App.view('ticket_zoom/time_unit')( + ticket: ticket + ) diff --git a/app/assets/javascripts/app/controllers/time_accounting.coffee b/app/assets/javascripts/app/controllers/time_accounting.coffee new file mode 100644 index 000000000..e81fa2c48 --- /dev/null +++ b/app/assets/javascripts/app/controllers/time_accounting.coffee @@ -0,0 +1,205 @@ +class Index extends App.ControllerSubContent + requiredPermission: 'admin.time_accounting' + header: 'Time Accounting' + events: + 'change .js-timeAccountingSetting input': 'setTimeAccounting' + 'click .js-timePickerYear': 'setYear' + 'click .js-timePickerMonth': 'setMonth' + + elements: + '.js-timeAccountingSetting input': 'timeAccountingSetting' + + constructor: -> + super + + current = new Date() + currentDay = current.getDate() + currentMonth = current.getMonth() + 1 + currentYear = current.getFullYear() + currentWeek = current.getWeek() + if !@month + @month = currentMonth + if !@year + @year = currentYear + + @subscribeId = App.Setting.subscribe(@render, initFetch: true, clear: false) + + release: => + App.Setting.unsubscribe(@subscribeId) + + render: => + currentNewTagSetting = @Config.get('time_accounting') || false + #return if currentNewTagSetting is @lastNewTagSetting + @lastNewTagSetting = currentNewTagSetting + + timeRangeYear = [] + year = new Date().getFullYear() + for item in [year-2..year] + record = { + display: item + value: item + } + timeRangeYear.push record + + timeRangeMonth = [ + { + display: 'Jan' + value: 1 + }, + { + display: 'Feb' + value: 2 + }, + { + display: 'Mar' + value: 3 + }, + { + display: 'Apr' + value: 4, + }, + { + display: 'Mai' + value: 5, + }, + { + display: 'Jun' + value: 6, + }, + { + display: 'Jul' + value: 7, + }, + { + display: 'Aug' + value: 8, + }, + { + display: 'Sep' + value: 9, + }, + { + display: 'Oct' + value: 10, + }, + { + display: 'Nov' + value: 11, + }, + { + display: 'Dec' + value: 12, + }, + ] + + @html App.view('time_accounting/index')( + timeRangeYear: timeRangeYear + timeRangeMonth: timeRangeMonth + year: @year + month: @month + ) + + configure_attributes = [ + { name: 'condition', display: 'Conditions for effected objects', tag: 'ticket_selector', null: false, preview: false, action: false, hasChanged: false }, + ] + + new App.ControllerForm( + el: @$('.js-selector') + model: + configure_attributes: configure_attributes, + autofocus: true + ) + + new ByTicket( + el: @$('.js-tableTicket') + year: @year + month: @month + ) + + new ByCustomer( + el: @$('.js-tableCustomer') + year: @year + month: @month + ) + + new ByOrganization( + el: @$('.js-tableOrganization') + year: @year + month: @month + ) + + setTimeAccounting: (e) => + value = @timeAccountingSetting.prop('checked') + App.Setting.set('time_accounting', value) + + setYear: (e) => + e.preventDefault() + @year = $(e.target).data('type') + @render() + + setMonth: (e) => + e.preventDefault() + @month = $(e.target).data('type') + @render() + +class ByTicket extends App.Controller + constructor: -> + super + @load() + + load: => + @ajax( + id: 'by_ticket' + type: 'GET' + url: "#{@apiPath}/time_accounting/log/by_ticket/#{@year}/#{@month}" + processData: true + success: (data, status, xhr) => + @render(data) + ) + + render: (rows) => + @html App.view('time_accounting/by_ticket')( + rows: rows + ) + +class ByCustomer extends App.Controller + constructor: -> + super + @load() + + load: => + @ajax( + id: 'by_customer' + type: 'GET' + url: "#{@apiPath}/time_accounting/log/by_customer/#{@year}/#{@month}" + processData: true + success: (data, status, xhr) => + @render(data) + ) + + render: (rows) => + @html App.view('time_accounting/by_customer')( + rows: rows + ) + +class ByOrganization extends App.Controller + constructor: -> + super + @load() + + load: => + @ajax( + id: 'by_organization' + type: 'GET' + url: "#{@apiPath}/time_accounting/log/by_organization/#{@year}/#{@month}" + processData: true + success: (data, status, xhr) => + @render(data) + ) + + render: (rows) => + @html App.view('time_accounting/by_organization')( + rows: rows + ) + +App.Config.set('TimeAccounting', { prio: 8500, name: 'Time Accounting', parent: '#manage', target: '#manage/time_accounting', controller: Index, permission: ['admin.time_accounting'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/models/ticket_article.coffee b/app/assets/javascripts/app/models/ticket_article.coffee index 1eb27461f..dc98d58d8 100644 --- a/app/assets/javascripts/app/models/ticket_article.coffee +++ b/app/assets/javascripts/app/models/ticket_article.coffee @@ -1,5 +1,5 @@ class App.TicketArticle extends App.Model - @configure 'TicketArticle', 'from', 'to', 'cc', 'subject', 'body', 'content_type', 'ticket_id', 'type_id', 'sender_id', 'internal', 'in_reply_to', 'form_id', 'preferences', 'updated_at' + @configure 'TicketArticle', 'from', 'to', 'cc', 'subject', 'body', 'content_type', 'ticket_id', 'type_id', 'sender_id', 'internal', 'in_reply_to', 'form_id', 'time_unit', 'preferences', 'updated_at' @extend Spine.Model.Ajax @url: @apiPath + '/ticket_articles' @configure_attributes = [ diff --git a/app/assets/javascripts/app/views/ticket_zoom/sidebar_ticket.jst.eco b/app/assets/javascripts/app/views/ticket_zoom/sidebar_ticket.jst.eco new file mode 100644 index 000000000..9bd538e05 --- /dev/null +++ b/app/assets/javascripts/app/views/ticket_zoom/sidebar_ticket.jst.eco @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/app/assets/javascripts/app/views/ticket_zoom/time_accounting.jst.eco b/app/assets/javascripts/app/views/ticket_zoom/time_accounting.jst.eco new file mode 100644 index 000000000..242e7f409 --- /dev/null +++ b/app/assets/javascripts/app/views/ticket_zoom/time_accounting.jst.eco @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/app/assets/javascripts/app/views/ticket_zoom/time_unit.jst.eco b/app/assets/javascripts/app/views/ticket_zoom/time_unit.jst.eco new file mode 100644 index 000000000..25c122b58 --- /dev/null +++ b/app/assets/javascripts/app/views/ticket_zoom/time_unit.jst.eco @@ -0,0 +1,4 @@ +<%- @T('No Entries') %> + |
---|
<%- @T('Customer') %> + | <%- @T('Organization') %> + | <%- @T('Time Units') %> + |
---|---|---|
<%= row.customer.email %> + | <% if row.organization: %><%= row.organization.name %><% end %> + | <%= row.time_unit %> + <% end %> + |
<%- @T('No Entries') %> + |
---|
<%- @T('Organization') %> + | <%- @T('Time Units') %> + |
---|---|
<%= row.organization.name %> + | <%= row.time_unit %> + <% end %> + |
<%- @T('No Entries') %> + |
---|
<%- @T('Ticket#') %> + | <%- @T('Title') %> + | <%- @T('Customer') %> + | <%- @T('Organization') %> + | <%- @T('Agent') %> + | <%- @T('Time Units') %> + | <%- @T('Time Units Total') %> + |
---|---|---|---|---|---|---|
<%= row.ticket.number %> + | <%= row.ticket.title %> + | <%= row.customer %> + | <%= row.organization %> + | <%= row.agent %> + | <%= row.time_unit %> + | <%= row.ticket.time_unit %> + <% end %> + |
<%- @T('Enable time accounting for following matching tickets.') %>
+ +