Added switch to user feature.

This commit is contained in:
Martin Edenhofer 2013-10-07 05:38:07 +02:00
parent 32455cb8af
commit 53ae52a96c
8 changed files with 179 additions and 74 deletions

View file

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

View file

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

View file

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

View file

@ -24,6 +24,22 @@ class Index extends App.Controller
# { name: 'List', 'data-type': '', class: 'active' }, # { name: 'List', 'data-type': '', class: 'active' },
{ name: 'New User', 'data-type': 'new', class: 'primary' } { 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' ) App.Config.set( 'User', { prio: 1000, name: 'Users', parent: '#manage', target: '#manage/users', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )

View file

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

View file

@ -28,7 +28,7 @@ class SessionsController < ApplicationController
current_user_set(user) current_user_set(user)
# log new session # 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 # auto population of default collections
default_collection = SessionHelper::default_collections(user) default_collection = SessionHelper::default_collections(user)
@ -131,7 +131,7 @@ class SessionsController < ApplicationController
current_user_set(authorization.user) current_user_set(authorization.user)
# log new session # 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 # remember last login date
authorization.user.update_last_login authorization.user.update_last_login
@ -150,7 +150,7 @@ class SessionsController < ApplicationController
current_user_set(user) current_user_set(user)
# log new session # log new session
user.activity_stream_log( 'session started', user.id ) user.activity_stream_log( 'session started', user.id, true )
# remember last login date # remember last login date
user.update_last_login user.update_last_login
@ -160,6 +160,37 @@ class SessionsController < ApplicationController
redirect_to '/#' redirect_to '/#'
end 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 def list
return if deny_if_not_role('Admin') return if deny_if_not_role('Admin')
sessions = ActiveRecord::SessionStore::Session.order('updated_at DESC').limit(10000) sessions = ActiveRecord::SessionStore::Session.order('updated_at DESC').limit(10000)

View file

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

View file

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