Improved rendering of profile pages. Added touch to customer and organization if ticket has changed.
This commit is contained in:
parent
d46196b69e
commit
412f868d42
13 changed files with 655 additions and 122 deletions
|
@ -1,7 +1,4 @@
|
||||||
class App.OrganizationProfile extends App.Controller
|
class App.OrganizationProfile extends App.Controller
|
||||||
events:
|
|
||||||
'focusout [contenteditable]': 'update'
|
|
||||||
|
|
||||||
constructor: (params) ->
|
constructor: (params) ->
|
||||||
super
|
super
|
||||||
|
|
||||||
|
@ -12,11 +9,8 @@ class App.OrganizationProfile extends App.Controller
|
||||||
|
|
||||||
@navupdate '#'
|
@navupdate '#'
|
||||||
|
|
||||||
# subscribe and reload data / fetch new data if triggered
|
# fetch new data if needed
|
||||||
@subscribeId = App.Organization.full( @organization_id, @render, false, true )
|
App.Organization.full( @organization_id, @render )
|
||||||
|
|
||||||
release: =>
|
|
||||||
App.Organization.unsubscribe(@subscribeId)
|
|
||||||
|
|
||||||
meta: =>
|
meta: =>
|
||||||
meta =
|
meta =
|
||||||
|
@ -48,6 +42,39 @@ class App.OrganizationProfile extends App.Controller
|
||||||
@doNotLog = 1
|
@doNotLog = 1
|
||||||
@recentView( 'Organization', @organization_id )
|
@recentView( 'Organization', @organization_id )
|
||||||
|
|
||||||
|
@html App.view('organization_profile/index')(
|
||||||
|
organization: organization
|
||||||
|
)
|
||||||
|
|
||||||
|
new Object(
|
||||||
|
el: @$('.js-object-container')
|
||||||
|
organization: organization
|
||||||
|
)
|
||||||
|
|
||||||
|
new App.TicketStats(
|
||||||
|
el: @$('.js-ticket-stats')
|
||||||
|
organization: organization
|
||||||
|
)
|
||||||
|
|
||||||
|
new App.UpdateTastbar(
|
||||||
|
genericObject: organization
|
||||||
|
)
|
||||||
|
|
||||||
|
class Object extends App.Controller
|
||||||
|
events:
|
||||||
|
'focusout [contenteditable]': 'update'
|
||||||
|
|
||||||
|
constructor: (params) ->
|
||||||
|
super
|
||||||
|
|
||||||
|
# subscribe and reload data / fetch new data if triggered
|
||||||
|
@subscribeId = App.Organization.full( @organization.id, @render, false, true )
|
||||||
|
|
||||||
|
release: =>
|
||||||
|
App.Organization.unsubscribe(@subscribeId)
|
||||||
|
|
||||||
|
render: (organization) =>
|
||||||
|
|
||||||
# get display data
|
# get display data
|
||||||
organizationData = []
|
organizationData = []
|
||||||
for attributeName, attributeConfig of App.Organization.attributesGet('view')
|
for attributeName, attributeConfig of App.Organization.attributesGet('view')
|
||||||
|
@ -65,7 +92,7 @@ class App.OrganizationProfile extends App.Controller
|
||||||
if name isnt 'name'
|
if name isnt 'name'
|
||||||
organizationData.push attributeConfig
|
organizationData.push attributeConfig
|
||||||
|
|
||||||
@html App.view('organization_profile')(
|
@html App.view('organization_profile/object')(
|
||||||
organization: organization
|
organization: organization
|
||||||
organizationData: organizationData
|
organizationData: organizationData
|
||||||
)
|
)
|
||||||
|
@ -76,15 +103,6 @@ class App.OrganizationProfile extends App.Controller
|
||||||
maxlength: 250
|
maxlength: 250
|
||||||
})
|
})
|
||||||
|
|
||||||
new App.TicketStats(
|
|
||||||
el: @$('.js-ticket-stats')
|
|
||||||
organization: organization
|
|
||||||
)
|
|
||||||
|
|
||||||
new App.UpdateTastbar(
|
|
||||||
genericObject: organization
|
|
||||||
)
|
|
||||||
|
|
||||||
# start action controller
|
# start action controller
|
||||||
showHistory = =>
|
showHistory = =>
|
||||||
new App.OrganizationHistory( organization_id: organization.id )
|
new App.OrganizationHistory( organization_id: organization.id )
|
||||||
|
@ -97,6 +115,7 @@ class App.OrganizationProfile extends App.Controller
|
||||||
title: 'Organizations'
|
title: 'Organizations'
|
||||||
object: 'Organization'
|
object: 'Organization'
|
||||||
objects: 'Organizations'
|
objects: 'Organizations'
|
||||||
|
container: @el.closest('.content')
|
||||||
)
|
)
|
||||||
|
|
||||||
actions = [
|
actions = [
|
||||||
|
@ -120,13 +139,14 @@ class App.OrganizationProfile extends App.Controller
|
||||||
update: (e) =>
|
update: (e) =>
|
||||||
name = $(e.target).attr('data-name')
|
name = $(e.target).attr('data-name')
|
||||||
value = $(e.target).html()
|
value = $(e.target).html()
|
||||||
org = App.Organization.find( @organization_id )
|
org = App.Organization.find( @organization.id )
|
||||||
if org[name] isnt value
|
if org[name] isnt value
|
||||||
data = {}
|
data = {}
|
||||||
data[name] = value
|
data[name] = value
|
||||||
org.updateAttributes( data )
|
org.updateAttributes( data )
|
||||||
@log 'notice', 'update', name, value, org
|
@log 'notice', 'update', name, value, org
|
||||||
|
|
||||||
|
|
||||||
class Router extends App.ControllerPermanent
|
class Router extends App.ControllerPermanent
|
||||||
constructor: (params) ->
|
constructor: (params) ->
|
||||||
super
|
super
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
class App.UserProfile extends App.Controller
|
class App.UserProfile extends App.Controller
|
||||||
events:
|
|
||||||
'focusout [contenteditable]': 'update'
|
|
||||||
|
|
||||||
constructor: (params) ->
|
constructor: (params) ->
|
||||||
super
|
super
|
||||||
|
|
||||||
|
@ -12,8 +9,8 @@ class App.UserProfile extends App.Controller
|
||||||
|
|
||||||
@navupdate '#'
|
@navupdate '#'
|
||||||
|
|
||||||
# subscribe and reload data / fetch new data if triggered
|
# fetch new data if needed
|
||||||
@subscribeId = App.User.full( @user_id, @render, false, true )
|
@subscribeId = App.User.full( @user_id, @render )
|
||||||
|
|
||||||
release: =>
|
release: =>
|
||||||
App.User.unsubscribe(@subscribeId)
|
App.User.unsubscribe(@subscribeId)
|
||||||
|
@ -47,6 +44,40 @@ class App.UserProfile extends App.Controller
|
||||||
@doNotLog = 1
|
@doNotLog = 1
|
||||||
@recentView( 'User', @user_id )
|
@recentView( 'User', @user_id )
|
||||||
|
|
||||||
|
@html App.view('user_profile/index')(
|
||||||
|
user: user
|
||||||
|
)
|
||||||
|
|
||||||
|
new Object(
|
||||||
|
el: @$('.js-object-container')
|
||||||
|
user: user
|
||||||
|
)
|
||||||
|
|
||||||
|
new App.TicketStats(
|
||||||
|
el: @$('.js-ticket-stats')
|
||||||
|
user: user
|
||||||
|
)
|
||||||
|
|
||||||
|
new App.UpdateTastbar(
|
||||||
|
genericObject: user
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Object extends App.Controller
|
||||||
|
events:
|
||||||
|
'focusout [contenteditable]': 'update'
|
||||||
|
|
||||||
|
constructor: (params) ->
|
||||||
|
super
|
||||||
|
|
||||||
|
# subscribe and reload data / fetch new data if triggered
|
||||||
|
@subscribeId = App.User.full( @user.id, @render, false, true )
|
||||||
|
|
||||||
|
release: =>
|
||||||
|
App.User.unsubscribe(@subscribeId)
|
||||||
|
|
||||||
|
render: (user) =>
|
||||||
|
|
||||||
# get display data
|
# get display data
|
||||||
userData = []
|
userData = []
|
||||||
for attributeName, attributeConfig of App.User.attributesGet('view')
|
for attributeName, attributeConfig of App.User.attributesGet('view')
|
||||||
|
@ -64,7 +95,7 @@ class App.UserProfile extends App.Controller
|
||||||
if name isnt 'firstname' && name isnt 'lastname' && name isnt 'organization'
|
if name isnt 'firstname' && name isnt 'lastname' && name isnt 'organization'
|
||||||
userData.push attributeConfig
|
userData.push attributeConfig
|
||||||
|
|
||||||
@html App.view('user_profile')(
|
@html App.view('user_profile/object')(
|
||||||
user: user
|
user: user
|
||||||
userData: userData
|
userData: userData
|
||||||
)
|
)
|
||||||
|
@ -75,15 +106,6 @@ class App.UserProfile extends App.Controller
|
||||||
maxlength: 250
|
maxlength: 250
|
||||||
})
|
})
|
||||||
|
|
||||||
new App.TicketStats(
|
|
||||||
el: @$('.js-ticket-stats')
|
|
||||||
user: user
|
|
||||||
)
|
|
||||||
|
|
||||||
new App.UpdateTastbar(
|
|
||||||
genericObject: user
|
|
||||||
)
|
|
||||||
|
|
||||||
# start action controller
|
# start action controller
|
||||||
showHistory = =>
|
showHistory = =>
|
||||||
new App.UserHistory( user_id: user.id )
|
new App.UserHistory( user_id: user.id )
|
||||||
|
@ -97,6 +119,7 @@ class App.UserProfile extends App.Controller
|
||||||
title: 'Users'
|
title: 'Users'
|
||||||
object: 'User'
|
object: 'User'
|
||||||
objects: 'Users'
|
objects: 'Users'
|
||||||
|
container: @el.closest('.content')
|
||||||
)
|
)
|
||||||
|
|
||||||
actions = [
|
actions = [
|
||||||
|
@ -120,7 +143,7 @@ class App.UserProfile extends App.Controller
|
||||||
update: (e) =>
|
update: (e) =>
|
||||||
name = $(e.target).attr('data-name')
|
name = $(e.target).attr('data-name')
|
||||||
value = $(e.target).html()
|
value = $(e.target).html()
|
||||||
user = App.User.find( @user_id )
|
user = App.User.find( @user.id )
|
||||||
if user[name] isnt value
|
if user[name] isnt value
|
||||||
data = {}
|
data = {}
|
||||||
data[name] = value
|
data[name] = value
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
<div class="flex profile">
|
|
||||||
|
|
||||||
<div class="profile-window">
|
|
||||||
<div class="profile-section vertical centered">
|
|
||||||
<div class="align-right profile-action js-action"></div>
|
|
||||||
<div class="profile-organizationIcon">
|
|
||||||
<div class="organization icon"></div>
|
|
||||||
</div>
|
|
||||||
<h1><%= @organization.displayName() %></h1>
|
|
||||||
</div>
|
|
||||||
<div class="profile-section">
|
|
||||||
<div class="profile-details horizontal wrap">
|
|
||||||
<% for row in @organizationData: %>
|
|
||||||
<% if @organization[row.name]: %>
|
|
||||||
<% if row.tag is 'richtext': %>
|
|
||||||
<div class="profile-detailsEntry" style="width: 100%;">
|
|
||||||
<label><%- @Ti( row.display ) %></label>
|
|
||||||
<div contenteditable="true" data-name="<%= row.name %>" data-type="update" data-placeholder="<%- @T('Add a Note') %>"><%- @organization[row.name] %></div>
|
|
||||||
</div>
|
|
||||||
<% else: %>
|
|
||||||
<div class="profile-detailsEntry">
|
|
||||||
<label><%- @Ti( row.display ) %></label>
|
|
||||||
<%- @L( @P( @organization[row.name] ) ) %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
<% end %>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<% if @organization.members: %>
|
|
||||||
<div class="profile-section profile-memberSection">
|
|
||||||
<label><%- @T('Members') %></label>
|
|
||||||
<div class="profile-details horizontal wrap">
|
|
||||||
|
|
||||||
<% for user in @organization.members: %>
|
|
||||||
<div class="profile-organizationMember">
|
|
||||||
<%- user.avatar("40") %>
|
|
||||||
<a href="<%- user.uiUrl() %>" class="user-popover" data-id="<%- user.id %>"><%= user.displayName() %></a>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<div class="profile-section js-ticket-stats"></div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
<div class="flex profile">
|
||||||
|
<div class="profile-window">
|
||||||
|
<div class="js-object-container"></div>
|
||||||
|
<div class="profile-section js-ticket-stats"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,39 @@
|
||||||
|
<div class="profile-section vertical centered">
|
||||||
|
<div class="align-right profile-action js-action"></div>
|
||||||
|
<div class="profile-organizationIcon">
|
||||||
|
<div class="organization icon"></div>
|
||||||
|
</div>
|
||||||
|
<h1><%= @organization.displayName() %></h1>
|
||||||
|
</div>
|
||||||
|
<div class="profile-section">
|
||||||
|
<div class="profile-details horizontal wrap">
|
||||||
|
<% for row in @organizationData: %>
|
||||||
|
<% if row.tag is 'richtext': %>
|
||||||
|
<div class="profile-detailsEntry" style="width: 100%;">
|
||||||
|
<label><%- @Ti( row.display ) %></label>
|
||||||
|
<div contenteditable="true" data-name="<%= row.name %>" data-type="update" data-placeholder="<%- @T('Add a Note') %>"><%- @organization[row.name] %></div>
|
||||||
|
</div>
|
||||||
|
<% else: %>
|
||||||
|
<% if @organization[row.name]: %>
|
||||||
|
<div class="profile-detailsEntry">
|
||||||
|
<label><%- @Ti( row.display ) %></label>
|
||||||
|
<%- @L( @P( @organization[row.name] ) ) %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% if @organization.members: %>
|
||||||
|
<div class="profile-section profile-memberSection">
|
||||||
|
<label><%- @T('Members') %></label>
|
||||||
|
<div class="profile-details horizontal wrap">
|
||||||
|
<% for user in @organization.members: %>
|
||||||
|
<div class="profile-organizationMember">
|
||||||
|
<%- user.avatar("40") %>
|
||||||
|
<a href="<%- user.uiUrl() %>" class="user-popover" data-id="<%- user.id %>"><%= user.displayName() %></a>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
|
@ -1,37 +0,0 @@
|
||||||
<div class="flex profile">
|
|
||||||
|
|
||||||
<div class="profile-window">
|
|
||||||
<div class="profile-section vertical centered">
|
|
||||||
<div class="align-right profile-action js-action"></div>
|
|
||||||
<%- @user.avatar("80") %>
|
|
||||||
<h1><%= @user.displayName() %></h1>
|
|
||||||
<% if @user.organization: %>
|
|
||||||
<div class="profile-organization"><a href="<%- @user.organization.uiUrl() %>"><%= @user.organization.displayName() %></a></div>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="profile-section">
|
|
||||||
<div class="profile-details horizontal wrap">
|
|
||||||
<% for row in @userData: %>
|
|
||||||
<% if @user[row.name]: %>
|
|
||||||
<% if row.tag is 'richtext': %>
|
|
||||||
<div class="profile-detailsEntry" style="width: 100%;">
|
|
||||||
<label><%- @Ti( row.display ) %></label>
|
|
||||||
<div contenteditable="true" data-name="<%= row.name %>" data-type="update" data-placeholder="<%- @T('Add a Note') %>"><%- @user[row.name] %></div>
|
|
||||||
</div>
|
|
||||||
<% else: %>
|
|
||||||
<div class="profile-detailsEntry">
|
|
||||||
<label><%- @Ti( row.display ) %></label>
|
|
||||||
<%- @L( @P( @user[row.name] ) ) %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
<% end %>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="profile-section js-ticket-stats"></div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
<div class="flex profile">
|
||||||
|
<div class="profile-window">
|
||||||
|
<div class="js-object-container"></div>
|
||||||
|
<div class="profile-section js-ticket-stats"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
27
app/assets/javascripts/app/views/user_profile/object.jst.eco
Normal file
27
app/assets/javascripts/app/views/user_profile/object.jst.eco
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<div class="profile-section vertical centered">
|
||||||
|
<div class="align-right profile-action js-action"></div>
|
||||||
|
<%- @user.avatar("80") %>
|
||||||
|
<h1><%= @user.displayName() %></h1>
|
||||||
|
<% if @user.organization: %>
|
||||||
|
<div class="profile-organization"><a href="<%- @user.organization.uiUrl() %>"><%= @user.organization.displayName() %></a></div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<div class="profile-section">
|
||||||
|
<div class="profile-details horizontal wrap">
|
||||||
|
<% for row in @userData: %>
|
||||||
|
<% if @user[row.name]: %>
|
||||||
|
<% if row.tag is 'richtext': %>
|
||||||
|
<div class="profile-detailsEntry" style="width: 100%;">
|
||||||
|
<label><%- @Ti( row.display ) %></label>
|
||||||
|
<div contenteditable="true" data-name="<%= row.name %>" data-type="update" data-placeholder="<%- @T('Add a Note') %>"><%- @user[row.name] %></div>
|
||||||
|
</div>
|
||||||
|
<% else: %>
|
||||||
|
<div class="profile-detailsEntry">
|
||||||
|
<label><%- @Ti( row.display ) %></label>
|
||||||
|
<%- @L( @P( @user[row.name] ) ) %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
30
app/models/observer/ticket/ref_object_touch.rb
Normal file
30
app/models/observer/ticket/ref_object_touch.rb
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
||||||
|
|
||||||
|
class Observer::Ticket::RefObjectTouch < ActiveRecord::Observer
|
||||||
|
observe 'ticket'
|
||||||
|
|
||||||
|
def after_create(record)
|
||||||
|
ref_object_touch(record)
|
||||||
|
end
|
||||||
|
def after_update(record)
|
||||||
|
ref_object_touch(record)
|
||||||
|
end
|
||||||
|
def after_touch(record)
|
||||||
|
ref_object_touch(record)
|
||||||
|
end
|
||||||
|
def after_destroy(record)
|
||||||
|
ref_object_touch(record)
|
||||||
|
end
|
||||||
|
|
||||||
|
def ref_object_touch(record)
|
||||||
|
|
||||||
|
# return if we run import mode
|
||||||
|
return if Setting.get('import_mode')
|
||||||
|
if record.customer
|
||||||
|
record.customer.touch
|
||||||
|
end
|
||||||
|
if record.organization
|
||||||
|
record.organization.touch
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -40,6 +40,7 @@ module Zammad
|
||||||
'observer::_ticket::_notification',
|
'observer::_ticket::_notification',
|
||||||
'observer::_ticket::_reset_new_state',
|
'observer::_ticket::_reset_new_state',
|
||||||
'observer::_ticket::_escalation_calculation',
|
'observer::_ticket::_escalation_calculation',
|
||||||
|
'observer::_ticket::_ref_object_touch',
|
||||||
'observer::_tag::_ticket_history',
|
'observer::_tag::_ticket_history',
|
||||||
'observer::_user::_geo'
|
'observer::_user::_geo'
|
||||||
|
|
||||||
|
|
188
test/browser/agent_organization_profile_test.rb
Normal file
188
test/browser/agent_organization_profile_test.rb
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
require 'browser_test_helper'
|
||||||
|
|
||||||
|
class AgentOrganizationProfileTest < TestCase
|
||||||
|
def test_search_and_edit_verify_in_second
|
||||||
|
message = 'comment 1 ' + rand(99999999999999999).to_s
|
||||||
|
tests = [
|
||||||
|
{
|
||||||
|
:name => 'start',
|
||||||
|
:instance1 => browser_instance,
|
||||||
|
:instance2 => browser_instance,
|
||||||
|
:instance1_username => 'master@example.com',
|
||||||
|
:instance1_password => 'test',
|
||||||
|
:instance2_username => 'agent1@example.com',
|
||||||
|
:instance2_password => 'test',
|
||||||
|
:url => browser_url,
|
||||||
|
:action => [
|
||||||
|
{
|
||||||
|
:where => :instance1,
|
||||||
|
:execute => 'close_all_tasks',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:where => :instance2,
|
||||||
|
:execute => 'close_all_tasks',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:where => :instance1,
|
||||||
|
:execute => 'search_organization',
|
||||||
|
:term => 'Zammad',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:where => :instance2,
|
||||||
|
:execute => 'search_organization',
|
||||||
|
:term => 'Zammad',
|
||||||
|
},
|
||||||
|
|
||||||
|
# update note
|
||||||
|
{
|
||||||
|
:where => :instance1,
|
||||||
|
:execute => 'set',
|
||||||
|
:css => '.active [data-name="note"]',
|
||||||
|
:value => message,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:where => :instance1,
|
||||||
|
:execute => 'click',
|
||||||
|
:css => '.active .profile',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:where => :instance1,
|
||||||
|
:execute => 'wait',
|
||||||
|
:value => 3,
|
||||||
|
},
|
||||||
|
|
||||||
|
# verify
|
||||||
|
{
|
||||||
|
:where => :instance2,
|
||||||
|
:execute => 'match',
|
||||||
|
:css => '.active .profile-window',
|
||||||
|
:value => message,
|
||||||
|
:match_result => true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
browser_double_test(tests)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_search_and_edit_in_one
|
||||||
|
message = '1 ' + rand(99999999).to_s
|
||||||
|
tests = [
|
||||||
|
{
|
||||||
|
:name => 'search and edit',
|
||||||
|
:action => [
|
||||||
|
{
|
||||||
|
:execute => 'close_all_tasks',
|
||||||
|
},
|
||||||
|
|
||||||
|
# search and open org
|
||||||
|
{
|
||||||
|
:execute => 'search_organization',
|
||||||
|
:term => 'Zammad',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'match',
|
||||||
|
:css => '.active .profile-window',
|
||||||
|
:value => 'note',
|
||||||
|
:match_result => true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'match',
|
||||||
|
:css => '.active .profile-window',
|
||||||
|
:value => 'member',
|
||||||
|
:match_result => true,
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
# update note
|
||||||
|
{
|
||||||
|
:execute => 'set',
|
||||||
|
:css => '.active [data-name="note"]',
|
||||||
|
:value => 'some note 123'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'click',
|
||||||
|
:css => '.active .profile',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'wait',
|
||||||
|
:value => 1,
|
||||||
|
},
|
||||||
|
|
||||||
|
# check and change note again in edit screen
|
||||||
|
{
|
||||||
|
:execute => 'click',
|
||||||
|
:css => '.active .js-action .select-arrow',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'click',
|
||||||
|
:css => '.active .js-action a[data-type="edit"]',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'wait',
|
||||||
|
:value => 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'match',
|
||||||
|
:css => '.active .modal',
|
||||||
|
:value => 'note',
|
||||||
|
:match_result => true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'match',
|
||||||
|
:css => '.active .modal',
|
||||||
|
:value => 'some note 123',
|
||||||
|
:match_result => true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'set',
|
||||||
|
:css => '.active .modal [data-name="note"]',
|
||||||
|
:value => 'some note abc'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'click',
|
||||||
|
:css => '.active .modal button.js-submit',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'wait',
|
||||||
|
:value => 4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'match',
|
||||||
|
:css => '.active .profile-window',
|
||||||
|
:value => 'some note abc',
|
||||||
|
:match_result => true,
|
||||||
|
},
|
||||||
|
|
||||||
|
# create new ticket
|
||||||
|
{
|
||||||
|
:execute => 'create_ticket',
|
||||||
|
:group => 'Users',
|
||||||
|
:subject => 'org profile check ' + message,
|
||||||
|
:body => 'org profile check ' + message,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'wait',
|
||||||
|
:value => 4,
|
||||||
|
},
|
||||||
|
|
||||||
|
# switch to org tab, verify if ticket is shown
|
||||||
|
{
|
||||||
|
:execute => 'search_organization',
|
||||||
|
:term => 'Zammad',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
:execute => 'match',
|
||||||
|
:css => '.active .profile-window',
|
||||||
|
:value => 'org profile check ' + message,
|
||||||
|
:match_result => true,
|
||||||
|
},
|
||||||
|
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
browser_signle_test_with_login(tests, { :username => 'master@example.com' })
|
||||||
|
end
|
||||||
|
end
|
188
test/browser/agent_user_profile_test.rb
Normal file
188
test/browser/agent_user_profile_test.rb
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
require 'browser_test_helper'
|
||||||
|
|
||||||
|
class AgentUserProfileTest < TestCase
|
||||||
|
def test_search_and_edit_verify_in_second
|
||||||
|
message = 'comment 1 ' + rand(99999999999999999).to_s
|
||||||
|
tests = [
|
||||||
|
{
|
||||||
|
:name => 'start',
|
||||||
|
:instance1 => browser_instance,
|
||||||
|
:instance2 => browser_instance,
|
||||||
|
:instance1_username => 'master@example.com',
|
||||||
|
:instance1_password => 'test',
|
||||||
|
:instance2_username => 'agent1@example.com',
|
||||||
|
:instance2_password => 'test',
|
||||||
|
:url => browser_url,
|
||||||
|
:action => [
|
||||||
|
{
|
||||||
|
:where => :instance1,
|
||||||
|
:execute => 'close_all_tasks',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:where => :instance2,
|
||||||
|
:execute => 'close_all_tasks',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:where => :instance1,
|
||||||
|
:execute => 'search_user',
|
||||||
|
:term => 'Braun',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:where => :instance2,
|
||||||
|
:execute => 'search_user',
|
||||||
|
:term => 'Braun',
|
||||||
|
},
|
||||||
|
|
||||||
|
# update note
|
||||||
|
{
|
||||||
|
:where => :instance1,
|
||||||
|
:execute => 'set',
|
||||||
|
:css => '.active [data-name="note"]',
|
||||||
|
:value => message,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:where => :instance1,
|
||||||
|
:execute => 'click',
|
||||||
|
:css => '.active .profile',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:where => :instance1,
|
||||||
|
:execute => 'wait',
|
||||||
|
:value => 3,
|
||||||
|
},
|
||||||
|
|
||||||
|
# verify
|
||||||
|
{
|
||||||
|
:where => :instance2,
|
||||||
|
:execute => 'match',
|
||||||
|
:css => '.active .profile-window',
|
||||||
|
:value => message,
|
||||||
|
:match_result => true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
browser_double_test(tests)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_search_and_edit_in_one
|
||||||
|
message = '1 ' + rand(99999999).to_s
|
||||||
|
tests = [
|
||||||
|
{
|
||||||
|
:name => 'search and edit',
|
||||||
|
:action => [
|
||||||
|
{
|
||||||
|
:execute => 'close_all_tasks',
|
||||||
|
},
|
||||||
|
|
||||||
|
# search and open user
|
||||||
|
{
|
||||||
|
:execute => 'search_user',
|
||||||
|
:term => 'Braun',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'match',
|
||||||
|
:css => '.active .profile-window',
|
||||||
|
:value => 'note',
|
||||||
|
:match_result => true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'match',
|
||||||
|
:css => '.active .profile-window',
|
||||||
|
:value => 'email',
|
||||||
|
:match_result => true,
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
# update note
|
||||||
|
{
|
||||||
|
:execute => 'set',
|
||||||
|
:css => '.active [data-name="note"]',
|
||||||
|
:value => 'some note 123'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'click',
|
||||||
|
:css => '.active .profile',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'wait',
|
||||||
|
:value => 1,
|
||||||
|
},
|
||||||
|
|
||||||
|
# check and change note again in edit screen
|
||||||
|
{
|
||||||
|
:execute => 'click',
|
||||||
|
:css => '.active .js-action .select-arrow',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'click',
|
||||||
|
:css => '.active .js-action a[data-type="edit"]',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'wait',
|
||||||
|
:value => 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'match',
|
||||||
|
:css => '.active .modal',
|
||||||
|
:value => 'note',
|
||||||
|
:match_result => true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'match',
|
||||||
|
:css => '.active .modal',
|
||||||
|
:value => 'some note 123',
|
||||||
|
:match_result => true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'set',
|
||||||
|
:css => '.active .modal [data-name="note"]',
|
||||||
|
:value => 'some note abc'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'click',
|
||||||
|
:css => '.active .modal button.js-submit',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'wait',
|
||||||
|
:value => 4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'match',
|
||||||
|
:css => '.active .profile-window',
|
||||||
|
:value => 'some note abc',
|
||||||
|
:match_result => true,
|
||||||
|
},
|
||||||
|
|
||||||
|
# create new ticket
|
||||||
|
{
|
||||||
|
:execute => 'create_ticket',
|
||||||
|
:group => 'Users',
|
||||||
|
:subject => 'user profile check ' + message,
|
||||||
|
:body => 'user profile check ' + message,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:execute => 'wait',
|
||||||
|
:value => 4,
|
||||||
|
},
|
||||||
|
|
||||||
|
# switch to org tab, verify if ticket is shown
|
||||||
|
{
|
||||||
|
:execute => 'search_user',
|
||||||
|
:term => 'Braun',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
:execute => 'match',
|
||||||
|
:css => '.active .profile-window',
|
||||||
|
:value => 'user profile check ' + message,
|
||||||
|
:match_result => true,
|
||||||
|
},
|
||||||
|
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
browser_signle_test_with_login(tests, { :username => 'master@example.com' })
|
||||||
|
end
|
||||||
|
end
|
92
test/unit/ticket_ref_object_update_test.rb
Normal file
92
test/unit/ticket_ref_object_update_test.rb
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class TicketRefObjectTouchTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
|
# create base
|
||||||
|
groups = Group.where( :name => 'Users' )
|
||||||
|
roles = Role.where( :name => 'Agent' )
|
||||||
|
agent1 = User.create_or_update(
|
||||||
|
:login => 'ticket-ref-object-update-agent1@example.com',
|
||||||
|
:firstname => 'Notification',
|
||||||
|
:lastname => 'Agent1',
|
||||||
|
:email => 'ticket-ref-object-update-agent1@example.com',
|
||||||
|
:password => 'agentpw',
|
||||||
|
:active => true,
|
||||||
|
:roles => roles,
|
||||||
|
:groups => groups,
|
||||||
|
:updated_at => '2015-02-05 16:37:00',
|
||||||
|
:updated_by_id => 1,
|
||||||
|
:created_by_id => 1,
|
||||||
|
)
|
||||||
|
roles = Role.where( :name => 'Customer' )
|
||||||
|
customer1 = User.create_or_update(
|
||||||
|
:login => 'ticket-ref-object-update-customer1@example.com',
|
||||||
|
:firstname => 'Notification',
|
||||||
|
:lastname => 'Agent1',
|
||||||
|
:email => 'ticket-ref-object-update-customer1@example.com',
|
||||||
|
:password => 'customerpw',
|
||||||
|
:active => true,
|
||||||
|
:roles => roles,
|
||||||
|
:updated_at => '2015-02-05 16:37:00',
|
||||||
|
:updated_by_id => 1,
|
||||||
|
:created_by_id => 1,
|
||||||
|
)
|
||||||
|
organization1 = Organization.create_if_not_exists(
|
||||||
|
:name => 'Ref Object Update Org',
|
||||||
|
:updated_at => '2015-02-05 16:37:00',
|
||||||
|
:updated_by_id => 1,
|
||||||
|
:created_by_id => 1,
|
||||||
|
)
|
||||||
|
|
||||||
|
test 'check if customer and organization has been updated' do
|
||||||
|
|
||||||
|
ticket = Ticket.create(
|
||||||
|
:title => "some title\n äöüß",
|
||||||
|
:group => Group.lookup( :name => 'Users'),
|
||||||
|
:customer_id => customer1.id,
|
||||||
|
:owner_id => agent1.id,
|
||||||
|
:state => Ticket::State.lookup( :name => 'new' ),
|
||||||
|
:priority => Ticket::Priority.lookup( :name => '2 normal' ),
|
||||||
|
:updated_by_id => 1,
|
||||||
|
:created_by_id => 1,
|
||||||
|
)
|
||||||
|
assert( ticket, "ticket created" )
|
||||||
|
|
||||||
|
# check if customer and organization has been touched
|
||||||
|
customer1 = User.find(customer1.id)
|
||||||
|
if customer1.updated_at > 2.second.ago
|
||||||
|
assert( true, "customer1.updated_at has been updated" )
|
||||||
|
else
|
||||||
|
assert( false, "customer1.updated_at has not been updated" )
|
||||||
|
end
|
||||||
|
|
||||||
|
organization1 = Organization.find(organization1.id)
|
||||||
|
if organization1.updated_at > 2.second.ago
|
||||||
|
assert( true, "organization1.updated_at has been updated" )
|
||||||
|
else
|
||||||
|
assert( false, "organization1.updated_at has not been updated" )
|
||||||
|
end
|
||||||
|
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
delete = ticket.destroy
|
||||||
|
assert( delete, "ticket destroy" )
|
||||||
|
|
||||||
|
# check if customer and organization has been touched
|
||||||
|
customer1 = User.find(customer1.id)
|
||||||
|
if customer1.updated_at > 2.second.ago
|
||||||
|
assert( true, "customer1.updated_at has been updated" )
|
||||||
|
else
|
||||||
|
assert( false, "customer1.updated_at has not been updated" )
|
||||||
|
end
|
||||||
|
|
||||||
|
organization1 = Organization.find(organization1.id)
|
||||||
|
if organization1.updated_at > 2.second.ago
|
||||||
|
assert( true, "organization1.updated_at has been updated" )
|
||||||
|
else
|
||||||
|
assert( false, "organization1.updated_at has not been updated" )
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue