From 4c824992ee715638565bfa3856041beb15c2a4ff Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Tue, 4 Sep 2012 23:28:49 +0200 Subject: [PATCH] Init version of customer panel. --- .../controllers/agent_ticket_view.js.coffee | 19 +- .../controllers/customer_tickets.js.coffee | 186 +----------------- .../app/controllers/dashboard.js.coffee | 5 + .../app/controllers/organizations.js.coffee | 2 +- .../javascripts/app/models/group.js.coffee | 11 +- .../app/models/organization.js.coffee | 10 +- .../javascripts/app/models/role.js.coffee | 8 +- .../javascripts/app/models/user.js.coffee | 34 ++-- .../app/views/agent_ticket_view.jst.eco | 2 +- app/controllers/application_controller.rb | 14 +- .../ticket_overviews_controller.rb | 38 +++- app/controllers/tickets_controller.rb | 10 + app/models/ticket.rb | 59 ++++-- app/models/user.rb | 7 + db/migrate/20120101000001_create_base.rb | 22 ++- db/migrate/20120101000010_create_ticket.rb | 1 + db/migrate/20120825005823_group_update.rb | 22 +++ db/migrate/20120904192450_overview_update.rb | 8 + db/seeds.rb | 61 +++++- lib/web_socket.rb | 14 +- 20 files changed, 276 insertions(+), 257 deletions(-) create mode 100644 db/migrate/20120825005823_group_update.rb create mode 100644 db/migrate/20120904192450_overview_update.rb diff --git a/app/assets/javascripts/app/controllers/agent_ticket_view.js.coffee b/app/assets/javascripts/app/controllers/agent_ticket_view.js.coffee index 7dd743702..74e7d96d0 100644 --- a/app/assets/javascripts/app/controllers/agent_ticket_view.js.coffee +++ b/app/assets/javascripts/app/controllers/agent_ticket_view.js.coffee @@ -20,8 +20,8 @@ class Index extends App.Controller @title '' @navupdate '#ticket_view/' + @view - @meta = {} - @bulk = {} + @meta = {} + @bulk = {} # set controller to active Config['ActiveController'] = '#ticket_overview_' + @view @@ -126,19 +126,24 @@ class Index extends App.Controller @html html # create table/overview + checkbox = true + edit = true + if @isRole('Customer') + checkbox = false + edit = false table = '' if @view_mode is 'm' table = App.view('agent_ticket_view/detail')( overview: @overview, objects: @ticket_list_show, - checkbox: true + checkbox: checkbox, ) table = $(table) table.delegate('[name="bulk_all"]', 'click', (e) -> if $(e.target).attr('checked') - $(e.target).parents().find('[name="bulk"]').attr('checked', true); + $(e.target).parents().find('[name="bulk"]').attr('checked', true) else - $(e.target).parents().find('[name="bulk"]').attr('checked', false); + $(e.target).parents().find('[name="bulk"]').attr('checked', false) ) else shown_all_attributes = @ticketTableAttributes( App.Overview.find(@overview.id).view.s.overview ) @@ -146,7 +151,8 @@ class Index extends App.Controller overview_extended: shown_all_attributes, model: App.Ticket, objects: @ticket_list_show, - checkbox: true, + checkbox: checkbox, + edit: edit, ) # append content table @@ -209,7 +215,6 @@ class Index extends App.Controller # render init page html = App.view('agent_ticket_view/bulk')( meta: @overview.meta, - checkbox: true form_ticket: form_ticket, # form_article: form_article, ) diff --git a/app/assets/javascripts/app/controllers/customer_tickets.js.coffee b/app/assets/javascripts/app/controllers/customer_tickets.js.coffee index a5dc9e28a..273cf7d45 100644 --- a/app/assets/javascripts/app/controllers/customer_tickets.js.coffee +++ b/app/assets/javascripts/app/controllers/customer_tickets.js.coffee @@ -1,10 +1,10 @@ $ = jQuery.sub() class Index extends App.Controller - events: - 'submit form': 'submit', - 'click .submit': 'submit', - 'click .cancel': 'cancel', +# events: +# 'submit form': 'submit', +# 'click .submit': 'submit', +# 'click .cancel': 'cancel', constructor: (params) -> super @@ -14,186 +14,18 @@ class Index extends App.Controller # set title @title 'My Tickets' - @fetch(params) +# @fetch(params) @navupdate '#customer_tickets' - @edit_form = undefined + @render() - # lisen if view need to be rerendert - Spine.bind 'ticket_create_rerender', (defaults) => - @log 'rerender', defaults - @render(defaults) + render: -> - # get data / in case also ticket data for split - fetch: (params) -> - - # use cache - cache = App.Store.get( 'ticket_create_attributes' ) - - if cache && !params.ticket_id && !params.article_id - - # get edit form attributes - @edit_form = cache.edit_form - - # load user collection - @loadCollection( type: 'User', data: cache.users ) - - @render() - else - App.Com.ajax( - id: 'ticket_create', - type: 'GET', - url: '/ticket_create', - data: { - ticket_id: params.ticket_id, - article_id: params.article_id, - }, - processData: true, - success: (data, status, xhr) => - - # cache request - App.Store.write( 'ticket_create_attributes', data ) - - # get edit form attributes - @edit_form = data.edit_form - - # load user collection - @loadCollection( type: 'User', data: data.users ) - - # load ticket collection - if data.ticket && data.articles - @loadCollection( type: 'Ticket', data: [data.ticket] ) - - # load article collections - @loadCollection( type: 'TicketArticle', data: data.articles || [] ) - - # render page - t = App.Ticket.find(params.ticket_id).attributes() - a = App.TicketArticle.find(params.article_id) - - # reset owner - t.owner_id = 0 - t.customer_id_autocompletion = a.from - t.subject = a.subject || t.title - t.body = a.body - @log '11111', t - @render( options: t ) - ) - - render: (template = {}) -> - - # set defaults - defaults = template['options'] || {} - if !( 'ticket_state_id' of defaults ) - defaults['ticket_state_id'] = App.TicketState.findByAttribute( 'name', 'new' ) - if !( 'ticket_priority_id' of defaults ) - defaults['ticket_priority_id'] = App.TicketPriority.findByAttribute( 'name', '2 normal' ) - - # remember customers - if $('#create_customer_id').val() - defaults['customer_id'] = $('#create_customer_id').val() - defaults['customer_id_autocompletion'] = $('#create_customer_id_autocompletion').val() - else -# defaults['customer_id'] = '2' -# defaults['customer_id_autocompletion'] = '12312313' - - # generate form - configure_attributes = [ -# { name: 'customer_id', display: 'Customer', tag: 'autocompletion', type: 'text', limit: 100, null: false, relation: 'User', class: 'span7', autocapitalize: false, help: 'Select the customer of the Ticket or create one.', link: '»', callback: @userInfo }, - { name: 'group_id', display: 'Group', tag: 'select', multiple: false, null: false, filter: @edit_form, nulloption: true, relation: 'Group', default: defaults['group_id'], class: 'span7', }, -# { name: 'owner_id', display: 'Owner', tag: 'select', multiple: false, null: true, filter: @edit_form, nulloption: true, relation: 'User', default: defaults['owner_id'], class: 'span7', }, - { name: 'subject', display: 'Subject', tag: 'input', type: 'text', limit: 100, null: false, default: defaults['subject'], class: 'span7', }, - { name: 'body', display: 'Text', tag: 'textarea', rows: 10, null: false, default: defaults['body'], class: 'span7', }, -# { name: 'ticket_state_id', display: 'State', tag: 'select', multiple: false, null: false, filter: @edit_form, relation: 'TicketState', default: defaults['ticket_state_id'], translate: true, class: 'medium' }, -# { name: 'ticket_priority_id', display: 'Priority', tag: 'select', multiple: false, null: false, filter: @edit_form, relation: 'TicketPriority', default: defaults['ticket_priority_id'], translate: true, class: 'medium' }, - ] - @html App.view('agent_ticket_create')( + @html App.view('agent_ticket_view')( head: 'My Ticket', - form: @formGen( model: { configure_attributes: configure_attributes, className: 'create' } ), +# form: @formGen( model: { configure_attributes: configure_attributes, className: 'create' } ), ) - # add elastic to textarea - @el.find('textarea').elastic() - # update textarea size - @el.find('textarea').trigger('change') - - # start customer info controller - if defaults['customer_id'] - $('#create_customer_id').val( defaults['customer_id'] ) - $('#create_customer_id_autocompletion').val( defaults['customer_id_autocompletion'] ) - @userInfo( user_id: defaults['customer_id'] ) - - cancel: -> - @render() - - submit: (e) -> - e.preventDefault() - - # get params - params = @formParam(e.target) - - # fillup params - if !params.title - params.title = params.subject - - # create ticket - object = new App.Ticket - @log 'updateAttributes', params - - # find sender_id - sender = App.TicketArticleSender.findByAttribute( 'name', 'Customer' ) - type = App.TicketArticleType.findByAttribute( 'name', 'phone' ) - if params.group_id - group = App.Group.find(params.group_id) - - # create article - params['article'] = { - from: params.customer_id_autocompletion, - to: (group && group.name) || '', - subject: params.subject, - body: params.body, - ticket_article_type_id: type.id, - ticket_article_sender_id: sender.id, - created_by_id: params.customer_id, - } -# console.log('params', params) - - object.load(params) - - # validate form - errors = object.validate() - - # show errors in form - if errors - @log 'error new', errors - @validateForm( form: e.target, errors: errors ) - - # save ticket, create article - else - - # disable form - @formDisable(e) - ui = @ - object.save( - success: -> - - # notify UI - ui.notify - type: 'success', - msg: T('Ticket %s created!', @.number), - link: "#ticket/zoom/#{@.id}" - timeout: 12000, - - # create new create screen - ui.render() - - # scroll to top - ui.scrollTo() - - error: -> - ui.log 'save failed!' - ui.formEnable(e) - ) Config.Routes['customer_tickets'] = Index diff --git a/app/assets/javascripts/app/controllers/dashboard.js.coffee b/app/assets/javascripts/app/controllers/dashboard.js.coffee index 0a5df9129..ccbd4b51d 100644 --- a/app/assets/javascripts/app/controllers/dashboard.js.coffee +++ b/app/assets/javascripts/app/controllers/dashboard.js.coffee @@ -8,6 +8,11 @@ class Index extends App.Controller # check authentication return if !@authenticate() + # check role + if @isRole('Customer') + @navigate '#ticket_view/my_tickets' + return + # set title @title 'Dashboard' @navupdate '#/' diff --git a/app/assets/javascripts/app/controllers/organizations.js.coffee b/app/assets/javascripts/app/controllers/organizations.js.coffee index 397d0ea6c..adcacb251 100644 --- a/app/assets/javascripts/app/controllers/organizations.js.coffee +++ b/app/assets/javascripts/app/controllers/organizations.js.coffee @@ -58,7 +58,7 @@ Config.NavBar['TicketOverview'] = { prio: 1000, parent: '', name: 'Overviews', t #Config.NavBar[''] = { prio: 1600, parent: '', name: 'anybody+agent', target: '#aa', role: ['Anybody', 'Agent'] } #Config.NavBar[''] = { prio: 1600, parent: '', name: 'Anybody', target: '#anybody', role: ['Anybody'] } Config.NavBar['CustomerTicketNew'] = { prio: 1600, parent: '', name: 'New Ticket', target: '#customer_ticket_new', role: ['Customer'] } -Config.NavBar['CustomerTickets'] = { prio: 1700, parent: '', name: 'My Tickets', target: '#customer_tickets', role: ['Customer'] } +Config.NavBar['CustomerTickets'] = { prio: 1700, parent: '', name: 'My Tickets', target: '#ticket_view/my_tickets', role: ['Customer'] } Config.NavBarRight['TicketNew'] = { prio: 8000, parent: '', name: 'New', target: '#ticket_create', role: ['Agent'] } Config.NavBarRight['User'] = { diff --git a/app/assets/javascripts/app/models/group.js.coffee b/app/assets/javascripts/app/models/group.js.coffee index 5f5864740..71c9d8b71 100644 --- a/app/assets/javascripts/app/models/group.js.coffee +++ b/app/assets/javascripts/app/models/group.js.coffee @@ -2,10 +2,13 @@ class App.Group extends App.Model @configure 'Group', 'name', 'note', 'active' @extend Spine.Model.Ajax @configure_attributes = [ - { name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, 'null': false, 'class': 'xlarge' }, - { name: 'note', display: 'Note', note: 'Notes are visible to agents only, never to customers.', tag: 'textarea', limit: 250, 'null': true, 'class': 'xlarge' }, - { name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 }, - { name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', 'default': true, 'null': false, 'class': 'xlarge' }, + { name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, 'null': false, 'class': 'span4' }, + { name: 'assignment_timeout', display: 'Assignment Timout', tag: 'input', note: 'Assignment timout in minutes if assigned agent is not working on it. Ticket will be shown as unassigend.', type: 'text', limit: 100, 'null': false, 'class': 'span4' }, + { name: 'follow_up_possible', display: 'Follow possible', tag: 'select', default: 'yes', options: { yes: 'yes', reject: 'reject follow up/do not reopen Ticket', 'new_ticket': 'do not reopen Ticket but create new Ticket' }, 'null': false, note: 'Follow up for closed ticket possible or not.', 'class': 'span4' }, + { name: 'follow_up_assignment', display: 'Assign Follow Ups', tag: 'select', default: 'yes', options: { yes: 'yes', no: 'no' }, 'null': false, note: 'Assign follow up to latest agent again.', 'class': 'span4' }, + { name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, 'null': true, 'class': 'span4' }, + { name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 }, + { name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', 'default': true, 'null': false, 'class': 'span4' }, ] @configure_overview = [ 'name', diff --git a/app/assets/javascripts/app/models/organization.js.coffee b/app/assets/javascripts/app/models/organization.js.coffee index 6fd469baa..12369b54d 100644 --- a/app/assets/javascripts/app/models/organization.js.coffee +++ b/app/assets/javascripts/app/models/organization.js.coffee @@ -2,11 +2,11 @@ class App.Organization extends App.Model @configure 'Organization', 'name', 'shared', 'note', 'active' @extend Spine.Model.Ajax @configure_attributes = [ - { name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, 'null': false, 'class': 'xlarge' }, - { name: 'note', display: 'Note', note: 'Notes are visible to agents only, never to customers.', tag: 'textarea', limit: 250, 'null': true, 'class': 'xlarge' }, - { name: 'shared', display: 'Shared organiztion', note: 'Customers in the organiztion can view each other items.', tag: 'boolean', type: 'boolean', 'default': true, 'null': false, 'class': 'xlarge' }, - { name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 }, - { name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', 'default': true, 'null': false, 'class': 'xlarge' }, + { name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, 'null': false, 'class': 'span4' }, + { name: 'shared', display: 'Shared organiztion', tag: 'boolean', note: 'Customers in the organiztion can view each other items.', type: 'boolean', 'default': true, 'null': false, 'class': 'span4' }, + { name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, 'null': true, 'class': 'span4' }, + { name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 }, + { name: 'active', display: 'Active', tag: 'boolean', note: 'boolean', 'default': true, 'null': false, 'class': 'span4' }, ] @configure_overview = [ 'name', 'shared', diff --git a/app/assets/javascripts/app/models/role.js.coffee b/app/assets/javascripts/app/models/role.js.coffee index d4e11e85c..ff9931459 100644 --- a/app/assets/javascripts/app/models/role.js.coffee +++ b/app/assets/javascripts/app/models/role.js.coffee @@ -2,10 +2,10 @@ class App.Role extends App.Model @configure 'Role', 'name', 'note', 'active' @extend Spine.Model.Ajax @configure_attributes = [ - { name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, 'null': false, 'class': 'xlarge' }, - { name: 'note', display: 'Note', note: 'Notes are visible to agents only, never to customers.', tag: 'textarea', limit: 250, 'null': true, 'class': 'xlarge' }, - { name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 }, - { name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', 'default': true, 'null': false, 'class': 'xlarge' }, + { name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, 'null': false, 'class': 'span4' }, + { name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, 'null': true, 'class': 'span4' }, + { name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 }, + { name: 'active', display: 'Active', tag: 'boolean', type: 'boolean', 'default': true, 'null': false, 'class': 'span4' }, ] @configure_overview = [ 'name', diff --git a/app/assets/javascripts/app/models/user.js.coffee b/app/assets/javascripts/app/models/user.js.coffee index 8d4c8f524..22d07bed6 100644 --- a/app/assets/javascripts/app/models/user.js.coffee +++ b/app/assets/javascripts/app/models/user.js.coffee @@ -3,23 +3,23 @@ class App.User extends App.Model @extend Spine.Model.Ajax # @hasMany 'roles', 'App.Role' @configure_attributes = [ - { name: 'login', display: 'Login', tag: 'input', type: 'text', limit: 100, null: false, class: 'xlarge', autocapitalize: false, signup: false, quick: false }, - { name: 'firstname', display: 'Firstname', tag: 'input', type: 'text', limit: 100, null: false, class: 'xlarge', signup: true, quick: true, info: true, invite_agent: true }, - { name: 'lastname', display: 'Lastname', tag: 'input', type: 'text', limit: 100, null: false, class: 'xlarge', signup: true, quick: true, info: true, invite_agent: true }, - { name: 'email', display: 'Email', tag: 'input', type: 'email', limit: 100, null: false, class: 'xlarge', signup: true, quick: true, info: true, invite_agent: true }, - { name: 'web', display: 'Web', tag: 'input', type: 'url', limit: 100, null: true, class: 'xlarge', signup: false, quick: true, info: true }, - { name: 'phone', display: 'Phone', tag: 'input', type: 'phone', limit: 100, null: true, class: 'xlarge', signup: false, quick: true, info: true }, - { name: 'mobile', display: 'Mobile', tag: 'input', type: 'phone', limit: 100, null: true, class: 'xlarge', signup: false, quick: true, info: true }, - { name: 'fax', display: 'Fax', tag: 'input', type: 'phone', limit: 100, null: true, class: 'xlarge', signup: false, quick: true, info: true }, - { name: 'street', display: 'Street', tag: 'input', type: 'text', limit: 100, null: true, class: 'xlarge', signup: false, quick: true, info: true }, - { name: 'zip', display: 'Zip', tag: 'input', type: 'text', limit: 100, null: true, class: 'xlarge', signup: false, quick: true, info: true }, - { name: 'city', display: 'City', tag: 'input', type: 'text', limit: 100, null: true, class: 'xlarge', signup: false, quick: true, info: true }, - { name: 'password', display: 'Password', tag: 'input', type: 'password', limit: 50, null: true, autocomplete: 'off', class: 'xlarge', signup: true, quick: false, }, - { name: 'organization_id', display: 'Organization', tag: 'select', multiple: false, nulloption: true, null: true, relation: 'Organization', class: 'xlarge' }, - { name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, null: true, class: 'xlarge', quick: true, info: true }, - { name: 'role_ids', display: 'Roles', tag: 'checkbox', multiple: true, null: false, relation: 'Role', class: 'xlarge' }, - { name: 'group_ids', display: 'Groups', tag: 'checkbox', multiple: true, null: true, relation: 'Group', class: 'xlarge', invite_agent: true }, - { name: 'active', display: 'Active', tag: 'boolean', default: true, null: true, class: 'xlarge' }, + { name: 'login', display: 'Login', tag: 'input', type: 'text', limit: 100, null: false, class: 'span4', autocapitalize: false, signup: false, quick: false }, + { name: 'firstname', display: 'Firstname', tag: 'input', type: 'text', limit: 100, null: false, class: 'span4', signup: true, quick: true, info: true, invite_agent: true }, + { name: 'lastname', display: 'Lastname', tag: 'input', type: 'text', limit: 100, null: false, class: 'span4', signup: true, quick: true, info: true, invite_agent: true }, + { name: 'email', display: 'Email', tag: 'input', type: 'email', limit: 100, null: false, class: 'span4', signup: true, quick: true, info: true, invite_agent: true }, + { name: 'web', display: 'Web', tag: 'input', type: 'url', limit: 100, null: true, class: 'span4', signup: false, quick: true, info: true }, + { name: 'phone', display: 'Phone', tag: 'input', type: 'phone', limit: 100, null: true, class: 'span4', signup: false, quick: true, info: true }, + { name: 'mobile', display: 'Mobile', tag: 'input', type: 'phone', limit: 100, null: true, class: 'span4', signup: false, quick: true, info: true }, + { name: 'fax', display: 'Fax', tag: 'input', type: 'phone', limit: 100, null: true, class: 'span4', signup: false, quick: true, info: true }, + { name: 'street', display: 'Street', tag: 'input', type: 'text', limit: 100, null: true, class: 'span4', signup: false, quick: true, info: true }, + { name: 'zip', display: 'Zip', tag: 'input', type: 'text', limit: 100, null: true, class: 'span4', signup: false, quick: true, info: true }, + { name: 'city', display: 'City', tag: 'input', type: 'text', limit: 100, null: true, class: 'span4', signup: false, quick: true, info: true }, + { name: 'password', display: 'Password', tag: 'input', type: 'password', limit: 50, null: true, autocomplete: 'off', class: 'span4', signup: true, quick: false, }, + { name: 'organization_id', display: 'Organization', tag: 'select', multiple: false, nulloption: true, null: true, relation: 'Organization', class: 'span4' }, + { name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, null: true, class: 'span4', quick: true, info: true }, + { name: 'role_ids', display: 'Roles', tag: 'checkbox', multiple: true, null: false, relation: 'Role', class: 'span4' }, + { name: 'group_ids', display: 'Groups', tag: 'checkbox', multiple: true, null: true, relation: 'Group', class: 'span4', invite_agent: true }, + { name: 'active', display: 'Active', tag: 'boolean', default: true, null: true, class: 'span4' }, { name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 }, ] @configure_overview = [ diff --git a/app/assets/javascripts/app/views/agent_ticket_view.jst.eco b/app/assets/javascripts/app/views/agent_ticket_view.jst.eco index ca7675093..f416db90f 100644 --- a/app/assets/javascripts/app/views/agent_ticket_view.jst.eco +++ b/app/assets/javascripts/app/views/agent_ticket_view.jst.eco @@ -1,7 +1,7 @@