Browse Source

Implemented issue #373 - Feature "Time recording”.

Martin Edenhofer 8 years ago
parent
commit
ad53128091

+ 32 - 1
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}"

+ 7 - 2
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('<form><fieldset class="edit"></fieldset></form><div class="tags"></div><div class="links"></div>')
+      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

+ 20 - 0
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)

+ 11 - 0
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
+    )

+ 205 - 0
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')

+ 1 - 1
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 = [

+ 6 - 0
app/assets/javascripts/app/views/ticket_zoom/sidebar_ticket.jst.eco

@@ -0,0 +1,6 @@
+<form>
+  <fieldset class="edit"></fieldset>
+</form>
+<div class="tags"></div>
+<div class="links"></div>
+<div class="js-timeUnit"></div>

+ 3 - 0
app/assets/javascripts/app/views/ticket_zoom/time_accounting.jst.eco

@@ -0,0 +1,3 @@
+<form>
+  <input type="text" name="time_unit" placeholder="<%- @T('Please enter your time which you want to account.') %>"/>
+</form>

+ 4 - 0
app/assets/javascripts/app/views/ticket_zoom/time_unit.jst.eco

@@ -0,0 +1,4 @@
+<div>
+  <label><%- @T('Accounted Time') %></label>
+  <div><%= @ticket.time_unit %></div>
+</div>

+ 23 - 0
app/assets/javascripts/app/views/time_accounting/by_customer.jst.eco

@@ -0,0 +1,23 @@
+<% if !@rows.length: %>
+  <table class="settings-list settings-list--stretch settings-list--placeholder">
+    <thead><tr><th><%- @T('No Entries') %>
+  </table>
+<% else: %>
+<table class="table table-striped table-hover">
+  <thead>
+  <tr>
+    <th><%- @T('Customer') %>
+    <th><%- @T('Organization') %>
+    <th><%- @T('Time Units') %>
+  </thead>
+  <tbody>
+  <% for row in @rows: %>
+  <tr>
+    <td><a href="#user/profile/<%- row.customer.id %>"><%= row.customer.email %></a>
+    <td><% if row.organization: %><%= row.organization.name %><% end %>
+    <td><%= row.time_unit %>
+  <% end %>
+  </tbody>
+</table>
+</div>
+<% end %>

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