Improved permanent task highlighting in nav bar.
This commit is contained in:
parent
e6540720a3
commit
81e27f8901
24 changed files with 256 additions and 174 deletions
|
@ -130,6 +130,11 @@ class App.Controller extends Spine.Controller
|
|||
return if !$('#navigation').is(':visible')
|
||||
$('#navigation').addClass('hide')
|
||||
|
||||
updateNavMenu: =>
|
||||
delay = ->
|
||||
App.Event.trigger('menu:render')
|
||||
@delay(delay, 200)
|
||||
|
||||
scrollTo: (x = 0, y = 0, delay = 0) ->
|
||||
a = ->
|
||||
window.scrollTo(x, y)
|
||||
|
|
|
@ -6,7 +6,7 @@ class App.ChannelChat extends App.Controller
|
|||
'click .js-selectBrowserWidth': 'selectBrowserWidth'
|
||||
'click .js-swatch': 'usePaletteColor'
|
||||
'click .js-toggle-chat': 'toggleChat'
|
||||
'click .js-chatSetting': 'toggleChatSetting'
|
||||
'change .js-chatSetting input': 'toggleChatSetting'
|
||||
'click .js-eyedropper': 'pickColor'
|
||||
|
||||
elements:
|
||||
|
@ -307,12 +307,7 @@ class App.ChannelChat extends App.Controller
|
|||
|
||||
toggleChatSetting: =>
|
||||
value = @chatSetting.prop('checked')
|
||||
setting = App.Setting.findByAttribute('name', 'chat')
|
||||
setting.state_current = { value: value }
|
||||
setting.save()
|
||||
@Config.set('chat', value)
|
||||
delay = -> App.Event.trigger('ui:rerender')
|
||||
@delay(delay, 200)
|
||||
App.Setting.set('chat', value)
|
||||
|
||||
updateParams: =>
|
||||
quote = (value) ->
|
||||
|
|
|
@ -3,7 +3,7 @@ class App.ChannelForm extends App.Controller
|
|||
events:
|
||||
'change form.js-params': 'updateParams'
|
||||
'keyup form.js-params': 'updateParams'
|
||||
'click .js-formSetting': 'toggleFormSetting'
|
||||
'change .js-formSetting input': 'toggleFormSetting'
|
||||
|
||||
elements:
|
||||
'.js-paramsBlock': 'paramsBlock'
|
||||
|
@ -16,10 +16,11 @@ class App.ChannelForm extends App.Controller
|
|||
|
||||
render: =>
|
||||
App.Setting.unsubscribe(@subscribeId)
|
||||
setting = App.Setting.findByAttribute('name', 'form_ticket_create')
|
||||
|
||||
setting = App.Setting.get('form_ticket_create')
|
||||
@html App.view('channel/form')(
|
||||
baseurl: window.location.origin
|
||||
formSetting: setting.state_current.value
|
||||
formSetting: setting
|
||||
)
|
||||
|
||||
@paramsBlock.each (i, block) ->
|
||||
|
@ -49,8 +50,6 @@ class App.ChannelForm extends App.Controller
|
|||
|
||||
toggleFormSetting: =>
|
||||
value = @formSetting.prop('checked')
|
||||
setting = App.Setting.findByAttribute('name', 'form_ticket_create')
|
||||
setting.state_current = { value: value }
|
||||
setting.save()
|
||||
App.Setting.set('form_ticket_create', value)
|
||||
|
||||
App.Config.set( 'Form', { prio: 2000, name: 'Form', parent: '#channels', target: '#channels/form', controller: App.ChannelForm, role: ['Admin'] }, 'NavBarAdmin' )
|
||||
|
|
|
@ -55,12 +55,7 @@ class App.ControllerIntegrationBase extends App.Controller
|
|||
msg: App.i18n.translateContent('Update successful!')
|
||||
timeout: 2000
|
||||
}
|
||||
if @preferences
|
||||
if @preferences.render
|
||||
App.Event.trigger( 'ui:rerender' )
|
||||
|
||||
if @preferences.session_check
|
||||
App.Auth.loginCheck()
|
||||
App.Setting.preferencesPost(@)
|
||||
|
||||
fail: (settings, details) ->
|
||||
App.Event.trigger 'notify', {
|
||||
|
@ -73,25 +68,4 @@ class App.ControllerIntegrationBase extends App.Controller
|
|||
|
||||
value =
|
||||
items: [params]
|
||||
App.Setting.set(
|
||||
@featureConfig,
|
||||
value,
|
||||
done: ->
|
||||
App.Event.trigger 'notify', {
|
||||
type: 'success'
|
||||
msg: App.i18n.translateContent('Update successful!')
|
||||
timeout: 2000
|
||||
}
|
||||
if @preferences
|
||||
if @preferences.render
|
||||
App.Event.trigger( 'ui:rerender' )
|
||||
|
||||
if @preferences.session_check
|
||||
App.Auth.loginCheck()
|
||||
fail: (settings, details) ->
|
||||
App.Event.trigger 'notify', {
|
||||
type: 'error'
|
||||
msg: App.i18n.translateContent(details.error_human || details.error || 'Unable to update object!')
|
||||
timeout: 2000
|
||||
}
|
||||
)
|
||||
App.Setting.set(@featureConfig, value)
|
||||
|
|
|
@ -108,13 +108,8 @@ class App.SettingsAreaItem extends App.Controller
|
|||
}
|
||||
|
||||
# rerender ui || get new collections and session data
|
||||
if @setting.preferences
|
||||
if @setting.preferences.render
|
||||
ui.render()
|
||||
App.Event.trigger( 'ui:rerender' )
|
||||
App.Setting.preferencesPost(@setting)
|
||||
|
||||
if @setting.preferences.session_check
|
||||
App.Auth.loginCheck()
|
||||
fail: (settings, details) ->
|
||||
ui.formEnable(e)
|
||||
App.Event.trigger 'notify', {
|
||||
|
@ -158,10 +153,10 @@ class App.SettingsAreaLogo extends App.Controller
|
|||
if file.size && file.size > 1024 * 1024 * maxSiteInMb
|
||||
App.Event.trigger 'notify', {
|
||||
type: 'error'
|
||||
msg: App.i18n.translateContent('File too big, max. %s MB allowed.', maxSiteInMb )
|
||||
msg: App.i18n.translateContent('File too big, max. %s MB allowed.', maxSiteInMb)
|
||||
timeout: 2000
|
||||
}
|
||||
@logoPreview.attr( 'src', '' )
|
||||
@logoPreview.attr('src', '')
|
||||
return
|
||||
|
||||
reader.readAsDataURL(file)
|
||||
|
@ -209,4 +204,4 @@ class App.SettingsAreaLogo extends App.Controller
|
|||
)
|
||||
|
||||
# add resized image
|
||||
App.ImageService.resizeForApp( @params.logo, @logoPreview.width(), @logoPreview.height(), store )
|
||||
App.ImageService.resizeForApp(@params.logo, @logoPreview.width(), @logoPreview.height(), store)
|
||||
|
|
|
@ -72,13 +72,8 @@ class App.SettingsForm extends App.Controller
|
|||
timeout: 2000
|
||||
}
|
||||
|
||||
# rerender ui || get new collections and session data
|
||||
if @preferences
|
||||
if @preferences.render
|
||||
App.Event.trigger( 'ui:rerender' )
|
||||
|
||||
if @preferences.session_check
|
||||
App.Auth.loginCheck()
|
||||
# rerender ui || get new collections and session data
|
||||
App.Setting.preferencesPost(@)
|
||||
|
||||
fail: (settings, details) ->
|
||||
App.Event.trigger 'notify', {
|
||||
|
|
|
@ -86,8 +86,7 @@ class App.CustomerChat extends App.Controller
|
|||
)
|
||||
|
||||
featureActive: =>
|
||||
if @Config.get('chat')
|
||||
return true
|
||||
return true if @Config.get('chat')
|
||||
false
|
||||
|
||||
render: ->
|
||||
|
@ -164,6 +163,10 @@ class App.CustomerChat extends App.Controller
|
|||
@title 'Customer Chat', true
|
||||
@navupdate '#customer_chat'
|
||||
|
||||
active: (state) =>
|
||||
return @shown if state is undefined
|
||||
@shown = state
|
||||
|
||||
counter: =>
|
||||
counter = 0
|
||||
|
||||
|
@ -239,11 +242,6 @@ class App.CustomerChat extends App.Controller
|
|||
@stopPushState()
|
||||
@pushState()
|
||||
|
||||
updateNavMenu: =>
|
||||
delay = ->
|
||||
App.Event.trigger('menu:render')
|
||||
@delay(delay, 200, 'updateNavMenu')
|
||||
|
||||
updateMeta: =>
|
||||
if @meta.waiting_chat_count && @maxChatWindows > @windowCount()
|
||||
@acceptChatElement.addClass('is-clickable is-blinking')
|
||||
|
|
|
@ -8,6 +8,7 @@ class App.CTI extends App.Controller
|
|||
return if !@isRole('CTI')
|
||||
|
||||
@list = []
|
||||
@backends = []
|
||||
@meta =
|
||||
active: false
|
||||
counter: 0
|
||||
|
@ -18,40 +19,39 @@ class App.CTI extends App.Controller
|
|||
|
||||
@load()
|
||||
|
||||
App.Event.bind(
|
||||
@bind('cti_event', (data) =>
|
||||
if data.direction is 'in'
|
||||
if data.state is 'newCall'
|
||||
if @switch()
|
||||
@notify(data)
|
||||
return if @meta.state[data.id]
|
||||
@meta.state[data.id] = true
|
||||
@meta.counter += 1
|
||||
@updateNavMenu()
|
||||
if data.state is 'answer' || data.state is 'hangup'
|
||||
return if !@meta.state[data.id]
|
||||
delete @meta.state[data.id]
|
||||
@meta.counter -= 1
|
||||
@updateNavMenu()
|
||||
'cti_event'
|
||||
(data) =>
|
||||
console.log('cti_event', data)
|
||||
if data.direction is 'in'
|
||||
if data.state is 'newCall'
|
||||
if @switch()
|
||||
@notify(data)
|
||||
return if @meta.state[data.id]
|
||||
@meta.state[data.id] = true
|
||||
@meta.counter += 1
|
||||
@updateNavMenu()
|
||||
if data.state is 'answer' || data.state is 'hangup'
|
||||
return if !@meta.state[data.id]
|
||||
delete @meta.state[data.id]
|
||||
@meta.counter -= 1
|
||||
@updateNavMenu()
|
||||
)
|
||||
@bind('cti_list_push', (data) =>
|
||||
if data.assets
|
||||
App.Collection.loadAssets(data.assets)
|
||||
if data.backends
|
||||
@backends = data.backends
|
||||
if data.list
|
||||
@list = data.list
|
||||
@render()
|
||||
'cti_list_push'
|
||||
)
|
||||
@bind('auth', (data) =>
|
||||
@meta.counter = 0
|
||||
)
|
||||
|
||||
'cti_event'
|
||||
)
|
||||
App.Event.bind(
|
||||
'cti_list_push'
|
||||
(data) =>
|
||||
if data.assets
|
||||
App.Collection.loadAssets(data.assets)
|
||||
if data.list
|
||||
@list = data.list
|
||||
@render()
|
||||
'cti_list_push'
|
||||
)
|
||||
App.Event.bind(
|
||||
'auth'
|
||||
(data) =>
|
||||
@meta.counter = 0
|
||||
@bind('cti:reload', =>
|
||||
@load()
|
||||
'cti_reload'
|
||||
)
|
||||
|
||||
# rerender view, e. g. on langauge change
|
||||
|
@ -69,6 +69,8 @@ class App.CTI extends App.Controller
|
|||
success: (data) =>
|
||||
if data.assets
|
||||
App.Collection.loadAssets(data.assets)
|
||||
if data.backends
|
||||
@backends = data.backends
|
||||
if data.list
|
||||
@list = data.list
|
||||
@render()
|
||||
|
@ -82,16 +84,27 @@ class App.CTI extends App.Controller
|
|||
title: title
|
||||
)
|
||||
|
||||
featureActive: =>
|
||||
return true
|
||||
return true if @Config.get('sipgate_integration')
|
||||
false
|
||||
featureActive: ->
|
||||
true
|
||||
|
||||
render: ->
|
||||
if !@isRole('CTI')
|
||||
@renderScreenUnauthorized(objectName: 'CTI')
|
||||
return
|
||||
|
||||
# check if min one backend is enabled
|
||||
backendEnabled = false
|
||||
for backend in @backends
|
||||
if backend.enabled
|
||||
backendEnabled = true
|
||||
if !backendEnabled
|
||||
@html App.view('cti/not_configured')(
|
||||
backends: @backends
|
||||
isAdmin: @isRole('Admin')
|
||||
)
|
||||
@updateNavMenu()
|
||||
return
|
||||
|
||||
format = (time) ->
|
||||
# Minutes and seconds
|
||||
mins = ~~(time / 60)
|
||||
|
@ -158,6 +171,10 @@ class App.CTI extends App.Controller
|
|||
@title 'CTI', true
|
||||
@navupdate '#cti'
|
||||
|
||||
active: (state) =>
|
||||
return @shown if state is undefined
|
||||
@shown = state
|
||||
|
||||
counter: =>
|
||||
count = 0
|
||||
for item in @list
|
||||
|
@ -182,11 +199,6 @@ class App.CTI extends App.Controller
|
|||
processData: true
|
||||
)
|
||||
|
||||
updateNavMenu: =>
|
||||
delay = ->
|
||||
App.Event.trigger('menu:render')
|
||||
@delay(delay, 200, 'updateNavMenu')
|
||||
|
||||
class CTIRouter extends App.ControllerPermanent
|
||||
constructor: (params) ->
|
||||
super
|
||||
|
|
|
@ -59,13 +59,11 @@ class App.Dashboard extends App.Controller
|
|||
@navigate '#clues'
|
||||
|
||||
active: (state) =>
|
||||
@activeState = state
|
||||
return @shown if state is undefined
|
||||
@shown = state
|
||||
if state
|
||||
@mayBeClues()
|
||||
|
||||
isActive: =>
|
||||
@activeState
|
||||
|
||||
url: ->
|
||||
'#dashboard'
|
||||
|
||||
|
@ -81,9 +79,6 @@ class App.Dashboard extends App.Controller
|
|||
# highlight navbar
|
||||
@navupdate '#dashboard'
|
||||
|
||||
hide: ->
|
||||
# no
|
||||
|
||||
changed: ->
|
||||
false
|
||||
|
||||
|
@ -112,6 +107,6 @@ class DashboardRouter extends App.ControllerPermanent
|
|||
persistent: true
|
||||
)
|
||||
|
||||
App.Config.set( 'dashboard', DashboardRouter, 'Routes' )
|
||||
App.Config.set( 'Dashboard', { prio: 100, parent: '', name: 'Dashboard', target: '#dashboard', role: ['Agent'], class: 'dashboard' }, 'NavBar' )
|
||||
App.Config.set( 'Dashboard', { controller: 'Dashboard', authentication: true }, 'permanentTask' )
|
||||
App.Config.set('dashboard', DashboardRouter, 'Routes')
|
||||
App.Config.set('Dashboard', { prio: 100, parent: '', name: 'Dashboard', target: '#dashboard', key: 'Dashboard', role: ['Agent'], class: 'dashboard' }, 'NavBar')
|
||||
App.Config.set('Dashboard', { controller: 'Dashboard', authentication: true }, 'permanentTask')
|
||||
|
|
|
@ -1801,11 +1801,6 @@ class CustomerChatRef extends App.Controller
|
|||
# write state
|
||||
App.SessionStorage.set('chat_layout_ref', state)
|
||||
|
||||
updateNavMenu: =>
|
||||
delay = ->
|
||||
App.Event.trigger('menu:render')
|
||||
@delay(delay, 200)
|
||||
|
||||
testChat: (chat, count) ->
|
||||
for i in [0..count]
|
||||
text = @questions[Math.floor(Math.random() * @questions.length)].question
|
||||
|
|
|
@ -55,9 +55,10 @@ class App.Navigation extends App.ControllerWidgetPermanent
|
|||
@notificationWidget = undefined
|
||||
|
||||
renderMenu: =>
|
||||
items = @getItems( navbar: @Config.get( 'NavBar' ) )
|
||||
items = @getItems( navbar: @Config.get('NavBar') )
|
||||
|
||||
# apply counter and switch info from persistant controllers (if exists)
|
||||
activeTab = {}
|
||||
itemsNew = []
|
||||
for item in items
|
||||
shown = true
|
||||
|
@ -70,6 +71,8 @@ class App.Navigation extends App.ControllerWidgetPermanent
|
|||
item.counter = worker.counter()
|
||||
if worker.switch
|
||||
item.switch = worker.switch()
|
||||
if worker.active && worker.active()
|
||||
activeTab[item.target] = true
|
||||
if worker.featureActive
|
||||
if worker.featureActive()
|
||||
shown = true
|
||||
|
@ -80,16 +83,17 @@ class App.Navigation extends App.ControllerWidgetPermanent
|
|||
items = itemsNew
|
||||
|
||||
# get open tabs to repopen on rerender
|
||||
open_tab = {}
|
||||
openTab = {}
|
||||
@$('.open').children('a').each( (i,d) ->
|
||||
href = $(d).attr('href')
|
||||
open_tab[href] = true
|
||||
openTab[href] = true
|
||||
)
|
||||
|
||||
# render menu
|
||||
@$('.js-menu').html App.view('navigation/menu')(
|
||||
items: items
|
||||
open_tab: open_tab
|
||||
items: items
|
||||
openTab: openTab
|
||||
activeTab: activeTab
|
||||
)
|
||||
|
||||
# bind on switch changes and execute it on controller
|
||||
|
|
|
@ -26,7 +26,6 @@ class App.OrganizationProfile extends App.Controller
|
|||
meta.head = organization.displayName()
|
||||
meta.title = organization.displayName()
|
||||
meta.iconClass = organization.icon()
|
||||
|
||||
meta
|
||||
|
||||
url: =>
|
||||
|
@ -41,9 +40,6 @@ class App.OrganizationProfile extends App.Controller
|
|||
|
||||
render: (organization) =>
|
||||
|
||||
# update taskbar with new meta data
|
||||
App.TaskManager.touch(@task_key)
|
||||
|
||||
if !@doNotLog
|
||||
@doNotLog = 1
|
||||
@recentView('Organization', @organization_id)
|
||||
|
@ -55,6 +51,7 @@ class App.OrganizationProfile extends App.Controller
|
|||
new Object(
|
||||
el: elLocal.find('.js-object-container')
|
||||
organization: organization
|
||||
task_key: @task_key
|
||||
)
|
||||
|
||||
new App.TicketStats(
|
||||
|
@ -83,6 +80,9 @@ class Object extends App.Controller
|
|||
|
||||
render: (organization) =>
|
||||
|
||||
# update taskbar with new meta data
|
||||
App.TaskManager.touch(@task_key)
|
||||
|
||||
# get display data
|
||||
organizationData = []
|
||||
for attributeName, attributeConfig of App.Organization.attributesGet('view')
|
||||
|
@ -117,6 +117,7 @@ class Object extends App.Controller
|
|||
organization_id: organization.id
|
||||
container: @el.closest('.content')
|
||||
)
|
||||
|
||||
editOrganization = =>
|
||||
new App.ControllerGenericEdit(
|
||||
id: organization.id
|
||||
|
|
|
@ -29,10 +29,8 @@ class App.TicketOverview extends App.Controller
|
|||
@delay(update, 2800, 'overview:fetch')
|
||||
|
||||
active: (state) =>
|
||||
@activeState = state
|
||||
|
||||
isActive: =>
|
||||
@activeState
|
||||
return @shown if state is undefined
|
||||
@shown = state
|
||||
|
||||
url: =>
|
||||
"#ticket/view/#{@view}"
|
||||
|
@ -399,7 +397,7 @@ class Table extends App.Controller
|
|||
view: @view
|
||||
|
||||
# start bulk action observ
|
||||
@el.append( @bulkForm.el )
|
||||
@el.append(@bulkForm.el)
|
||||
if @$('.table-overview').find('input[name="bulk"]:checked').length isnt 0
|
||||
@bulkForm.show()
|
||||
|
||||
|
@ -431,7 +429,7 @@ class Table extends App.Controller
|
|||
ticket_id = $(element).val()
|
||||
for ticket_id_selected in ticketIDs
|
||||
if ticket_id_selected is ticket_id
|
||||
$(element).attr( 'checked', true )
|
||||
$(element).attr('checked', true)
|
||||
)
|
||||
|
||||
viewmode: (e) =>
|
||||
|
@ -591,8 +589,8 @@ class BulkForm extends App.Controller
|
|||
params.ticket_id = ticket.id
|
||||
params.form_id = @form_id
|
||||
|
||||
sender = App.TicketArticleSender.findByAttribute( 'name', 'Agent' )
|
||||
type = App.TicketArticleType.find( params['type_id'] )
|
||||
sender = App.TicketArticleSender.findByAttribute('name', 'Agent')
|
||||
type = App.TicketArticleType.find(params['type_id'])
|
||||
params.sender_id = sender.id
|
||||
|
||||
if !params['internal']
|
||||
|
@ -789,7 +787,7 @@ class TicketOverviewRouter extends App.ControllerPermanent
|
|||
persistent: true
|
||||
)
|
||||
|
||||
App.Config.set( 'ticket/view', TicketOverviewRouter, 'Routes' )
|
||||
App.Config.set( 'ticket/view/:view', TicketOverviewRouter, 'Routes' )
|
||||
App.Config.set( 'TicketOverview', { controller: 'TicketOverview', authentication: true }, 'permanentTask' )
|
||||
App.Config.set( 'TicketOverview', { prio: 1000, parent: '', name: 'Overviews', target: '#ticket/view', role: ['Agent', 'Customer'], class: 'overviews' }, 'NavBar' )
|
||||
App.Config.set('ticket/view', TicketOverviewRouter, 'Routes')
|
||||
App.Config.set('ticket/view/:view', TicketOverviewRouter, 'Routes')
|
||||
App.Config.set('TicketOverview', { controller: 'TicketOverview', authentication: true }, 'permanentTask')
|
||||
App.Config.set('TicketOverview', { prio: 1000, parent: '', name: 'Overviews', target: '#ticket/view', key: 'TicketOverview', role: ['Agent', 'Customer'], class: 'overviews' }, 'NavBar')
|
||||
|
|
|
@ -8,16 +8,13 @@ class App.UserProfile extends App.Controller
|
|||
return
|
||||
|
||||
# fetch new data if needed
|
||||
@subscribeId = App.User.full(@user_id, @render)
|
||||
App.User.full(@user_id, @render)
|
||||
|
||||
# rerender view, e. g. on langauge change
|
||||
@bind 'ui:rerender', =>
|
||||
return if !@authenticate(true)
|
||||
@render(App.User.fullLocal(@user_id))
|
||||
|
||||
release: =>
|
||||
App.User.unsubscribe(@subscribeId)
|
||||
|
||||
meta: =>
|
||||
meta =
|
||||
url: @url()
|
||||
|
@ -43,9 +40,6 @@ class App.UserProfile extends App.Controller
|
|||
|
||||
render: (user) =>
|
||||
|
||||
# update taskbar with new meta data
|
||||
App.TaskManager.touch(@task_key)
|
||||
|
||||
if !@doNotLog
|
||||
@doNotLog = 1
|
||||
@recentView('User', @user_id)
|
||||
|
@ -55,8 +49,9 @@ class App.UserProfile extends App.Controller
|
|||
))
|
||||
|
||||
new Object(
|
||||
el: elLocal.find('.js-object-container')
|
||||
user: user
|
||||
el: elLocal.find('.js-object-container')
|
||||
user: user
|
||||
task_key: @task_key
|
||||
)
|
||||
|
||||
new App.TicketStats(
|
||||
|
@ -70,7 +65,6 @@ class App.UserProfile extends App.Controller
|
|||
genericObject: user
|
||||
)
|
||||
|
||||
|
||||
class Object extends App.Controller
|
||||
events:
|
||||
'focusout [contenteditable]': 'update'
|
||||
|
@ -86,6 +80,9 @@ class Object extends App.Controller
|
|||
|
||||
render: (user) =>
|
||||
|
||||
# update taskbar with new meta data
|
||||
App.TaskManager.touch(@task_key)
|
||||
|
||||
# get display data
|
||||
userData = []
|
||||
for attributeName, attributeConfig of App.User.attributesGet('view')
|
||||
|
|
|
@ -10,5 +10,29 @@ class App.Setting extends App.Model
|
|||
@set: (name, value, options = {}) ->
|
||||
setting = App.Setting.findByAttribute('name', name)
|
||||
setting.state_current.value = value
|
||||
if !options.done
|
||||
options.done = ->
|
||||
App.Setting.preferencesPost(@)
|
||||
|
||||
if !options.fail
|
||||
options.fail = (settings, details) ->
|
||||
App.Event.trigger 'notify', {
|
||||
type: 'error'
|
||||
msg: App.i18n.translateContent(details.error_human || details.error || 'Unable to update object!')
|
||||
timeout: 2000
|
||||
}
|
||||
setting.save(options)
|
||||
App.Config.set(name, value)
|
||||
|
||||
@preferencesPost: (setting) ->
|
||||
return if !setting.preferences
|
||||
if setting.preferences.render
|
||||
App.Event.trigger('ui:rerender')
|
||||
|
||||
if setting.preferences.trigger
|
||||
trigger = setting.preferences.trigger
|
||||
delay = -> App.Event.trigger(trigger)
|
||||
App.Delay.set(delay, 20)
|
||||
|
||||
if setting.preferences.session_check
|
||||
App.Auth.loginCheck()
|
||||
|
|
10
app/assets/javascripts/app/views/cti/not_configured.jst.eco
Normal file
10
app/assets/javascripts/app/views/cti/not_configured.jst.eco
Normal file
|
@ -0,0 +1,10 @@
|
|||
<div class="main flex">
|
||||
<h1><%- @T('Caller log') %></h1>
|
||||
<p><%- @T('Sorry, currently is no CTI backend enabled!') %></p>
|
||||
<p><%- @T('We support') %>:</p>
|
||||
<ul>
|
||||
<% for backend in @backends: %>
|
||||
<li><% if @isAdmin: %><a href="<%- backend.url %>"><% end %><%= backend.name %><% if @isAdmin: %></a><% end %>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
|
@ -1,6 +1,6 @@
|
|||
<% for item in @items: %>
|
||||
<% if item.child: %>
|
||||
<div class="dropdown<%- ' open' if @open_tab[item.target] %>">
|
||||
<div class="dropdown<%- ' open' if @openTab[item.target] %>">
|
||||
<a href="<%= item.target %>" class="menu-item js-<%- item.class %>MenuItem dropdown-toggle" data-toggle="dropdown">
|
||||
<%- @Icon(item.class, 'menu-item-icon') %>
|
||||
<span class="menu-item-name flex">
|
||||
|
@ -21,7 +21,7 @@
|
|||
</ul>
|
||||
</div>
|
||||
<% else: %>
|
||||
<a class="menu-item js-<%- item.class %>MenuItem" href="<%= item.target %>" data-key="<%- item.key %>">
|
||||
<a class="menu-item js-<%- item.class %>MenuItem <% if @activeTab[item.target]: %>is-active<% end %>" href="<%= item.target %>" data-key="<%- item.key %>">
|
||||
<%- @Icon(item.class, 'menu-item-icon') %>
|
||||
<span class="menu-item-name">
|
||||
<%- @T(item.name) %>
|
||||
|
|
32
app/controllers/cti_controller.rb
Normal file
32
app/controllers/cti_controller.rb
Normal file
|
@ -0,0 +1,32 @@
|
|||
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
class CtiController < ApplicationController
|
||||
before_action :authentication_check
|
||||
|
||||
# list current caller log
|
||||
def index
|
||||
return if deny_if_not_role('CTI')
|
||||
|
||||
backends = [
|
||||
{
|
||||
name: 'sipgate.io',
|
||||
enabled: Setting.get('sipgate_integration'),
|
||||
url: '#system/integration/sipgate',
|
||||
}
|
||||
]
|
||||
|
||||
result = Cti::Log.log
|
||||
result[:backends] = backends
|
||||
render json: result
|
||||
end
|
||||
|
||||
# set caller log to done
|
||||
def done
|
||||
return if deny_if_not_role('CTI')
|
||||
log = Cti::Log.find(params['id'])
|
||||
log.done = params['done']
|
||||
log.save
|
||||
render json: {}
|
||||
end
|
||||
|
||||
end
|
|
@ -4,23 +4,6 @@ require 'builder'
|
|||
|
||||
class Integration::SipgateController < ApplicationController
|
||||
|
||||
# list current caller log
|
||||
def index
|
||||
return if !authentication_check
|
||||
return if deny_if_not_role('CTI')
|
||||
render json: Cti::Log.log
|
||||
end
|
||||
|
||||
# set caller log to done
|
||||
def done
|
||||
return if !authentication_check
|
||||
return if deny_if_not_role('CTI')
|
||||
log = Cti::Log.find(params['id'])
|
||||
log.done = params['done']
|
||||
log.save
|
||||
render json: {}
|
||||
end
|
||||
|
||||
# notify about inbound call / block inbound call
|
||||
def in
|
||||
http_log_config facility: 'sipgate.io'
|
||||
|
|
51
app/models/transaction/cti_caller_id_detection.rb
Normal file
51
app/models/transaction/cti_caller_id_detection.rb
Normal file
|
@ -0,0 +1,51 @@
|
|||
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
||||
require 'signature_detection'
|
||||
|
||||
class Transaction::CtiCallerIdDetection
|
||||
|
||||
=begin
|
||||
{
|
||||
object: 'Ticket',
|
||||
type: 'create',
|
||||
object_id: 123,
|
||||
via_web: true,
|
||||
user_id: 123,
|
||||
},
|
||||
{
|
||||
object: 'User',
|
||||
type: 'update',
|
||||
object_id: 123,
|
||||
via_web: true,
|
||||
changes: {
|
||||
'attribute1' => [before, now],
|
||||
'attribute2' => [before, now],
|
||||
}
|
||||
user_id: 123,
|
||||
},
|
||||
=end
|
||||
|
||||
def initialize(item, params = {})
|
||||
@item = item
|
||||
@params = params
|
||||
end
|
||||
|
||||
def perform
|
||||
|
||||
# return if we run import mode
|
||||
return if Setting.get('import_mode')
|
||||
|
||||
if @item[:object] == 'Ticket' && @item[:type] == 'create'
|
||||
ticket = Ticket.lookup(id: @item[:object_id])
|
||||
return if !ticket
|
||||
Cti::CallerId.build(ticket)
|
||||
end
|
||||
|
||||
if @item[:object] == 'User'
|
||||
user = User.lookup(id: @item[:object_id])
|
||||
return if !user
|
||||
Cti::CallerId.build(user)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
6
config/routes/cti.rb
Normal file
6
config/routes/cti.rb
Normal file
|
@ -0,0 +1,6 @@
|
|||
Zammad::Application.routes.draw do
|
||||
|
||||
match '/api/v1/cti/log', to: 'cti#index', via: :get
|
||||
match '/api/v1/cti/done/:id', to: 'cti#done', via: :post
|
||||
|
||||
end
|
|
@ -1,7 +1,5 @@
|
|||
Zammad::Application.routes.draw do
|
||||
|
||||
match '/api/v1/cti/log', to: 'integration/sipgate#index', via: :get
|
||||
match '/api/v1/cti/done/:id', to: 'integration/sipgate#done', via: :post
|
||||
match '/api/v1/sipgate/in', to: 'integration/sipgate#in', via: :post
|
||||
match '/api/v1/sipgate/out', to: 'integration/sipgate#out', via: :post
|
||||
|
||||
|
|
15
db/migrate/20160429000001_update_cti.rb
Normal file
15
db/migrate/20160429000001_update_cti.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
class UpdateCti < ActiveRecord::Migration
|
||||
def up
|
||||
setting = Setting.find_by(name: 'sipgate_integration')
|
||||
if setting
|
||||
setting.preferences = { prio: 1, trigger: 'cti:reload' }
|
||||
setting.save
|
||||
end
|
||||
|
||||
setting = Setting.find_by(name: 'chat')
|
||||
if setting
|
||||
setting.preferences = { trigger: 'menu:render' }
|
||||
setting.save
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1198,7 +1198,7 @@ Setting.create_if_not_exists(
|
|||
},
|
||||
],
|
||||
},
|
||||
preferences: { render: true },
|
||||
preferences: { trigger: 'menu:render' },
|
||||
state: false,
|
||||
frontend: true
|
||||
)
|
||||
|
@ -1851,7 +1851,7 @@ Setting.create_if_not_exists(
|
|||
],
|
||||
},
|
||||
state: false,
|
||||
preferences: { prio: 1 },
|
||||
preferences: { prio: 1, trigger: 'cti:reload' },
|
||||
frontend: false
|
||||
)
|
||||
Setting.create_if_not_exists(
|
||||
|
|
Loading…
Reference in a new issue