Browse Source

Added switch to user feature.

Martin Edenhofer 11 years ago
parent
commit
53ae52a96c

+ 2 - 2
app/assets/javascripts/app/controllers/_application_controller.js.coffee

@@ -143,8 +143,8 @@ class App.Controller extends Spine.Controller
 
   ticketTableAttributes: (attributes) =>
     all_attributes = [
-      { name: 'number',                 link: true, title: 'title' },
-      { name: 'title',                  link: true, title: 'title' },
+      { name: 'number',                 type: 'link', title: 'title', dataType: 'edit' },
+      { name: 'title',                  type: 'link', title: 'title', dataType: 'edit' },
       { name: 'customer',               class: 'user-popover', data: { id: true } },
       { name: 'ticket_state',           translate: true, title: true },
       { name: 'ticket_priority',        translate: true, title: true },

+ 51 - 23
app/assets/javascripts/app/controllers/_application_controller_generic.js.coffee

@@ -60,11 +60,11 @@ class App.ControllerGenericEdit extends App.ControllerModal
 
     @html App.view('generic/admin/edit')( head: @pageData.object )
     new App.ControllerForm(
-      el:         @el.find('#object_edit'),
-      model:      App[ @genericObject ],
-      params:     @item,
-      required:   @required,
-      autofocus:  true,
+      el:         @el.find('#object_edit')
+      model:      App[ @genericObject ]
+      params:     @item
+      required:   @required
+      autofocus:  true
     )
     @modalShow()
 
@@ -96,7 +96,7 @@ class App.ControllerGenericEdit extends App.ControllerModal
         ui.modalHide()
     )
 
-class App.ControllerGenericIndex extends App.ControllerContent
+class App.ControllerGenericIndex extends App.Controller
   events:
     'click [data-type=edit]':    'edit'
     'click [data-type=destroy]': 'destroy'
@@ -143,25 +143,53 @@ class App.ControllerGenericIndex extends App.ControllerContent
       )
 
     @html App.view('generic/admin/index')(
-      head:    @pageData.objects,
-      notes:   @pageData.notes,
-      buttons: @pageData.buttons,
-      menus:   @pageData.menus,
+      head:    @pageData.objects
+      notes:   @pageData.notes
+      buttons: @pageData.buttons
+      menus:   @pageData.menus
     )
 
+    # append additional col. link switch to
+    overview = _.clone( App[ @genericObject ].configure_overview )
+    attributes = _.clone( App[ @genericObject ].configure_attributes )
+    if @pageData.addCol
+      for item in @pageData.addCol.overview
+        overview.push item
+      for item in @pageData.addCol.attributes
+        attributes.push item
+
     # append content table
     new App.ControllerTable(
-      el:      @el.find('.table-overview'),
-      model:   App[ @genericObject ],
-      objects: objects,
+      el:         @el.find('.table-overview')
+      model:      App[ @genericObject ]
+      objects:    objects
+      overview:   overview
+      attributes: attributes
+    )
+
+    binds = {}
+    for item in attributes
+      if item.dataType
+        if !binds[item.dataType]
+          callback = item.callback || @edit
+          @el.on( 'click', "[data-type=#{item.dataType}]", callback )
+          binds[item.dataType] = true
+
+  custom: (e) =>
+    e.preventDefault()
+    item = $(e.target).item( App[ @genericObject ] )
+    new App.ControllerGenericEdit(
+      id:            item.id
+      pageData:      @pageData
+      genericObject: @genericObject
     )
 
   edit: (e) =>
     e.preventDefault()
     item = $(e.target).item( App[ @genericObject ] )
     new App.ControllerGenericEdit(
-      id:            item.id,
-      pageData:      @pageData,
+      id:            item.id
+      pageData:      @pageData
       genericObject: @genericObject
     )
 
@@ -174,7 +202,7 @@ class App.ControllerGenericIndex extends App.ControllerContent
   new: (e) ->
     e.preventDefault()
     new App.ControllerGenericNew(
-      pageData:      @pageData,
+      pageData:      @pageData
       genericObject: @genericObject
     )
 
@@ -191,8 +219,8 @@ class DestroyConfirm extends App.ControllerModal
       button:  'Yes'
     )
     @modalShow(
-      backdrop: true,
-      keyboard: true,
+      backdrop: true
+      keyboard: true
     )
 
   submit: (e) =>
@@ -233,10 +261,10 @@ class App.ControllerLevel2 extends App.ControllerContent
     @navupdate @page.nav
 
     @html App.view('generic/admin_level2/index')(
-      page:     @page,
-      menus:    @menu,
-      type:     @type,
-      target:   @target,
+      page:     @page
+      menus:    @menu
+      type:     @type
+      target:   @target
     )
 
     if !@target
@@ -269,7 +297,7 @@ class App.ControllerTabs extends App.Controller
 
   render: ->
     @html App.view('generic/tabs')(
-      tabs: @tabs,
+      tabs: @tabs
     )
     @el.find('.nav-tabs li:first').addClass('active')
 

+ 46 - 28
app/assets/javascripts/app/controllers/_application_controller_table.js.coffee

@@ -10,34 +10,34 @@ class App.ControllerTable extends App.Controller
   ###
 
     new App.ControllerTable(
-      header:   ['Host', 'User', 'Adapter', 'Active'],
-      overview: ['host', 'user', 'adapter', 'active'],
-      model:    App.Channel,
-      objects:  data,
-      checkbox: false,
-      radio:    false,
+      header:   ['Host', 'User', 'Adapter', 'Active']
+      overview: ['host', 'user', 'adapter', 'active']
+      model:    App.Channel
+      objects:  data
+      checkbox: false
+      radio:    false
     )
 
     new App.ControllerTable(
       overview_extended: [
-        { name: 'number',                 link: true },
-        { name: 'title',                  link: true },
-        { name: 'customer',               class: 'user-popover', data: { id: true } },
-        { name: 'ticket_state',           translate: true },
-        { name: 'ticket_priority',        translate: true },
+        { name: 'number',                 link: true }
+        { name: 'title',                  link: true }
+        { name: 'customer',               class: 'user-popover', data: { id: true } }
+        { name: 'ticket_state',           translate: true }
+        { name: 'ticket_priority',        translate: true }
         { name: 'group' },
-        { name: 'owner',                  class: 'user-popover', data: { id: true } },
-        { name: 'created_at',             callback: @frontendTime },
-        { name: 'last_contact',           callback: @frontendTime },
-        { name: 'last_contact_agent',     callback: @frontendTime },
-        { name: 'last_contact_customer',  callback: @frontendTime },
-        { name: 'first_response',         callback: @frontendTime },
-        { name: 'close_time',             callback: @frontendTime },
+        { name: 'owner',                  class: 'user-popover', data: { id: true } }
+        { name: 'created_at',             callback: @frontendTime }
+        { name: 'last_contact',           callback: @frontendTime }
+        { name: 'last_contact_agent',     callback: @frontendTime }
+        { name: 'last_contact_customer',  callback: @frontendTime }
+        { name: 'first_response',         callback: @frontendTime }
+        { name: 'close_time',             callback: @frontendTime }
       ],
-      model:    App.Ticket,
-      objects:  tickets,
-      checkbox: false,
-      radio:    false,
+      model:    App.Ticket
+      objects:  tickets
+      checkbox: false
+      radio:    false
     )
 
   ###
@@ -53,7 +53,7 @@ class App.ControllerTable extends App.Controller
       table = '<p>-' + App.i18n.translateContent( 'none' ) + '-</p>'
       return $(table)
 
-    # define normal header
+    # define table header
     if header
       header_new = []
       for key in header
@@ -64,21 +64,39 @@ class App.ControllerTable extends App.Controller
     else if !data.overview_extended
       header = []
       for row in overview
+        found = false
         if attributes
           for attribute in attributes
             if row is attribute.name
+              found = true
               header.push attribute
             else
               rowWithoutId = row + '_id'
               if rowWithoutId is attribute.name
-                header.push  attribute
+                found = true
+                header.push attribute
+        if !found
+          header.push {
+            name:    row
+            display: row
+          }     
 
+    # collect data of col. types
     dataTypesForCols = []
     for row in overview
-      dataTypesForCols.push {
-        name: row
-        link: true
-      }
+      if attributes
+        for attribute in attributes
+          if row is attribute.name
+            dataTypesAttribute = _.clone(attribute)
+            dataTypesAttribute['type'] = 'link'
+            if !dataTypesAttribute['dataType']
+              dataTypesAttribute['dataType'] = 'edit'
+            dataTypesForCols.push dataTypesAttribute
+      else
+        dataTypesForCols.push {
+          name: row
+          link: true
+        }
 
     # extended table format
     if data.overview_extended

+ 16 - 0
app/assets/javascripts/app/controllers/users.js.coffee

@@ -24,6 +24,22 @@ class Index extends App.Controller
 #          { name: 'List', 'data-type': '', class: 'active' },
           { name: 'New User', 'data-type': 'new', class: 'primary' }
         ]
+        addCol:
+          overview: ['switch_to']
+          attributes: [
+            {
+              name:     'switch_to'
+              display:  'Switch to'
+              type:     'link'
+              class:    'glyphicon glyphicon-user'
+              readonly: 1
+              dataType: 'switch_to'
+              callback: (e) ->
+                e.preventDefault()
+                user_id = $(e.target).parent().parent().data('id')
+                window.location = App.Config.get('api_path') + '/sessions/switch/' + user_id
+            }
+          ]
     )
 
 App.Config.set( 'User', { prio: 1000, name: 'Users', parent: '#manage', target: '#manage/users', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )

+ 12 - 8
app/assets/javascripts/app/views/generic/table.jst.eco

@@ -32,10 +32,10 @@
   <% position++ %>
   <tr class="item <% if object.active is false: %>not-active<% end %>" data-id="<%= object.id %>" data-position="<%= position %>" >
     <% if @checkbox: %>
-    <td><input type="checkbox" value="<%= object.id %>" name="bulk"/></td>
+      <td><input type="checkbox" value="<%= object.id %>" name="bulk"/></td>
     <% end %>
     <% if @radio: %>
-    <td><input type="radio" value="<%= object.id %>" name="radio"/></td>
+      <td><input type="radio" value="<%= object.id %>" name="radio"/></td>
     <% end %>
     <% for row in @overview: %>
       <% displayName = @P( object[row.name], row ) %>
@@ -46,18 +46,22 @@
           <% displayNameTitle = @P( object[row.title], row ) %>
         <% end %>
       <% end %>
-    <td <% if row.title: %>title="<%= displayNameTitle %>"<% end %>>
-      <% if row.link: %><a href="#" data-type="edit"><% else: %><span <% if row.class: %>class="<%= row.class %>"<% end %> <% if row.data && row.data.id: %>data-id="<%= object[row.name].id %>"<% end %>><% end %>
-      <% if row.translate || row.callback: %><%- displayName %><% else: %><%= displayName %><% end %>
-      <% if row.link: %></a><% else: %></span><% end %>
-    </td>
+      <td <% if row.title: %>title="<%= displayNameTitle %>"<% end %>>
+        <% if row.type is 'link': %>
+          <a href="#" data-type="<%= row.dataType %>" <% if row.class: %>class="<%= row.class %>"<% end %>>
+        <% else: %>
+          <span <% if row.class: %>class="<%= row.class %>"<% end %> <% if row.data && row.data.id: %>data-id="<%= object[row.name].id %>"<% end %>>
+        <% end %>
+        <% if row.translate || row.callback: %><%- displayName %><% else: %><%= displayName %><% end %>
+        <% if row.type is 'link': %></a><% else: %></span><% end %>
+      </td>
   <% end %>
 <!--
     <td><%= object.updated_at %></td>
 -->
 <% if @destroy: %>
     <td>    
-      <a data-type="destroy">x</a>
+      <a class="glyphicon glyphicon-trash" data-type="destroy">x</a>
     </td>
 <% end %>
   </tr>

+ 34 - 3
app/controllers/sessions_controller.rb

@@ -28,7 +28,7 @@ class SessionsController < ApplicationController
     current_user_set(user)
 
     # log new session
-    user.activity_stream_log( 'session started', user.id )
+    user.activity_stream_log( 'session started', user.id, true )
 
     # auto population of default collections
     default_collection = SessionHelper::default_collections(user)
@@ -131,7 +131,7 @@ class SessionsController < ApplicationController
     current_user_set(authorization.user)
 
     # log new session
-    user.activity_stream_log( 'session started', authorization.user.id )
+    user.activity_stream_log( 'session started', authorization.user.id, true )
 
     # remember last login date
     authorization.user.update_last_login
@@ -150,7 +150,7 @@ class SessionsController < ApplicationController
       current_user_set(user)
 
       # log new session
-      user.activity_stream_log( 'session started', user.id )
+      user.activity_stream_log( 'session started', user.id, true )
 
       # remember last login date
       user.update_last_login
@@ -160,6 +160,37 @@ class SessionsController < ApplicationController
     redirect_to '/#'
   end
 
+  # "switch" to user
+  def switch_to_user
+    return if deny_if_not_role('Admin')
+
+    # check user
+    if !params[:id]
+      render(
+        :json   => { :message => 'no user given' },
+        :status => :not_found
+      )
+      return false
+    end
+
+    user = User.lookup( :id => params[:id] )
+    if !user
+      render(
+        :json   => {},
+        :status => :not_found
+      )
+      return false
+    end
+
+    # log new session
+    user.activity_stream_log( 'switch to', current_user.id, true )
+
+    # set session user
+    current_user_set(user)
+
+    redirect_to '/#'
+  end
+
   def list
     return if deny_if_not_role('Admin')
     sessions = ActiveRecord::SessionStore::Session.order('updated_at DESC').limit(10000)

+ 10 - 3
app/models/application_model/activity_stream_base.rb

@@ -9,21 +9,28 @@ log activity for this object
   article = Ticket::Article.find(123)
   result = article.activity_stream_log( 'created', user_id )
 
+  # force log
+  result = article.activity_stream_log( 'created', user_id, true )
+
 returns
 
   result = true # false
 
 =end
 
-  def activity_stream_log (type, user_id)
-    role = self.class.activity_stream_support_config[:role]
+  def activity_stream_log (type, user_id, force = false)
+    role       = self.class.activity_stream_support_config[:role]
+    updated_at = self.updated_at
+    if force
+      updated_at = Time.new
+    end
     ActivityStream.add(
       :o_id           => self['id'],
       :type           => type,
       :object         => self.class.name,
       :group_id       => self['group_id'],
       :role           => role,
-      :created_at     => self.updated_at,
+      :created_at     => updated_at,
       :created_by_id  => user_id,
     )
   end

+ 8 - 7
config/routes/auth.rb

@@ -2,17 +2,18 @@ Zammad::Application.routes.draw do
   api_path = Rails.configuration.api_path
 
   # omniauth
-  match '/auth/:provider/callback',       :to => 'sessions#create_omniauth',:via => [:post, :get, :puts, :delete]
+  match '/auth/:provider/callback',         :to => 'sessions#create_omniauth',:via => [:post, :get, :puts, :delete]
 
   # sso
-  match '/auth/sso',                      :to => 'sessions#create_sso',     :via => [:post, :get]
+  match '/auth/sso',                        :to => 'sessions#create_sso',     :via => [:post, :get]
 
   # sessions
-  match api_path + '/signin',        :to => 'sessions#create',         :via => :post
-  match api_path + '/signshow',      :to => 'sessions#show',           :via => :get
-  match api_path + '/signout',       :to => 'sessions#destroy',        :via => [:get, :delete]
+  match api_path + '/signin',               :to => 'sessions#create',         :via => :post
+  match api_path + '/signshow',             :to => 'sessions#show',           :via => :get
+  match api_path + '/signout',              :to => 'sessions#destroy',        :via => [:get, :delete]
 
-  match api_path + '/sessions',      :to => 'sessions#list',           :via => :get
-  match api_path + '/sessions/:id',  :to => 'sessions#delete',         :via => :delete
+  match api_path + '/sessions/switch/:id',  :to => 'sessions#switch_to_user', :via => :get
+  match api_path + '/sessions',             :to => 'sessions#list',           :via => :get
+  match api_path + '/sessions/:id',         :to => 'sessions#delete',         :via => :delete
 
 end