Refactoring: Bindings and namespaces improves memory usage and resolved ghost bindings.
* Renamed controllers `@bind` and `@unbind` to `@controllerBind` and `@controllerUnbind` to not overwrite spine's methods to take advantage of spine's binding/unbinding and cleanup features. * Cleanup of controller namespaces `App.ObserverController` -> `App.ControllerObserver`, `App.ObserverActionRow` -> `App.ControllerObserverActionRow` and `App.WizardModal` -> `App.ControllerWizardModal` * Moved to named local controller names to have better trace backs/debugging (e. g. `class Index` to `class UserIndex`). * Splited `app/assets/javascripts/app/controllers/_application_controller.coffee` into separate files under `app/assets/javascripts/app/controllers/_application_controller/*.coffee` to have better trace backs/debugging. * Moved classes with executed code from `app/assets/javascripts/app/controllers/widget/*.coffee` into `app/assets/javascripts/app/controllers/_plugin/` from now `app/assets/javascripts/app/controllers/widget/*.coffee` will only contain UI widgets like popovers. * Refactored second argument of `@navigate`. Old version was only `true` to hide `@navigate` redirect from browser back list. Now we introduced params instant of boolean argument. Now we support: * `hideCurrentLocationFromHistory: true` -> hide redirect from browser back list (old `true` argument) * `emptyEl: true` -> will empty `@el` before redirect to new location * `removeEl: true` -> will remove `@el` before redirect to new location
This commit is contained in:
parent
0eac6f0fd9
commit
5ee6418c18
193 changed files with 3846 additions and 3788 deletions
|
@ -2,12 +2,7 @@ class App.Controller extends Spine.Controller
|
||||||
@include App.LogInclude
|
@include App.LogInclude
|
||||||
@include App.RenderScreen
|
@include App.RenderScreen
|
||||||
|
|
||||||
constructor: (params) ->
|
constructor: ->
|
||||||
|
|
||||||
# unbind old bindings
|
|
||||||
if params && params.el && params.el.unbind
|
|
||||||
params.el.unbind()
|
|
||||||
|
|
||||||
super
|
super
|
||||||
|
|
||||||
# generate controllerId
|
# generate controllerId
|
||||||
|
@ -30,11 +25,14 @@ class App.Controller extends Spine.Controller
|
||||||
ajaxId = App.Ajax.request(data)
|
ajaxId = App.Ajax.request(data)
|
||||||
@ajaxCalls.push ajaxId
|
@ajaxCalls.push ajaxId
|
||||||
|
|
||||||
navigate: (location, hideCurrentLocationFromHistory = false) ->
|
navigate: (location, params = {}) ->
|
||||||
@log 'debug', "navigate to '#{location}', hide from history '#{hideCurrentLocationFromHistory}'"
|
@log 'debug', "navigate to '#{location}'"
|
||||||
|
@log 'debug', "navigate hide from history '#{params.hideCurrentLocationFromHistory}'" if params.hideCurrentLocationFromHistory
|
||||||
|
@el.empty() if params.emptyEl
|
||||||
|
@el.remove() if params.removeEl
|
||||||
|
|
||||||
# hide current location from browser history, allow to use back button in browser
|
# hide current location from browser history, allow to use back button in browser
|
||||||
if hideCurrentLocationFromHistory
|
if params.hideCurrentLocationFromHistory
|
||||||
if window.history
|
if window.history
|
||||||
history = App.Config.get('History')
|
history = App.Config.get('History')
|
||||||
oldLocation = history[history.length-2]
|
oldLocation = history[history.length-2]
|
||||||
|
@ -45,22 +43,14 @@ class App.Controller extends Spine.Controller
|
||||||
preventDefault: (e) ->
|
preventDefault: (e) ->
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
||||||
bind: (event, callback) =>
|
controllerBind: (event, callback) =>
|
||||||
App.Event.bind(
|
App.Event.bind(
|
||||||
event
|
event
|
||||||
callback
|
callback
|
||||||
@controllerId
|
@controllerId
|
||||||
)
|
)
|
||||||
|
|
||||||
one: (event, callback) =>
|
controllerUnbind: (event, callback) =>
|
||||||
App.Event.bind(
|
|
||||||
event
|
|
||||||
callback
|
|
||||||
@controllerId
|
|
||||||
true
|
|
||||||
)
|
|
||||||
|
|
||||||
unbind: (event, callback) =>
|
|
||||||
App.Event.unbind(
|
App.Event.unbind(
|
||||||
event
|
event
|
||||||
callback
|
callback
|
||||||
|
@ -85,6 +75,16 @@ class App.Controller extends Spine.Controller
|
||||||
App.Interval.clearLevel(@controllerId)
|
App.Interval.clearLevel(@controllerId)
|
||||||
@abortAjaxCalls()
|
@abortAjaxCalls()
|
||||||
|
|
||||||
|
# release bindings
|
||||||
|
if @el
|
||||||
|
@el.undelegate()
|
||||||
|
@el.unbind()
|
||||||
|
@el.empty()
|
||||||
|
|
||||||
|
# release spine bindings (see release() of spine.coffee)
|
||||||
|
@unbind()
|
||||||
|
@stopListening()
|
||||||
|
|
||||||
abortAjaxCalls: =>
|
abortAjaxCalls: =>
|
||||||
if !@ajaxCalls
|
if !@ajaxCalls
|
||||||
return
|
return
|
||||||
|
@ -125,11 +125,11 @@ class App.Controller extends Spine.Controller
|
||||||
|
|
||||||
# add @notify method to create notification
|
# add @notify method to create notification
|
||||||
notify: (data) ->
|
notify: (data) ->
|
||||||
App.Event.trigger 'notify', data
|
App.Event.trigger('notify', data)
|
||||||
|
|
||||||
# add @notifyDesktop method to create desktop notification
|
# add @notifyDesktop method to create desktop notification
|
||||||
notifyDesktop: (data) ->
|
notifyDesktop: (data) ->
|
||||||
App.Event.trigger 'notifyDesktop', data
|
App.Event.trigger('notifyDesktop', data)
|
||||||
|
|
||||||
# add @navupdate method to update navigation
|
# add @navupdate method to update navigation
|
||||||
navupdate: (url, force = false) ->
|
navupdate: (url, force = false) ->
|
||||||
|
@ -137,17 +137,7 @@ class App.Controller extends Spine.Controller
|
||||||
# ignore navupdate until #clues are gone
|
# ignore navupdate until #clues are gone
|
||||||
return if !force && window.location.hash is '#clues'
|
return if !force && window.location.hash is '#clues'
|
||||||
|
|
||||||
App.Event.trigger 'navupdate', url
|
App.Event.trigger('navupdate', url)
|
||||||
|
|
||||||
# show navigation
|
|
||||||
navShow: ->
|
|
||||||
return if $('#navigation').is(':visible')
|
|
||||||
$('#navigation').removeClass('hide')
|
|
||||||
|
|
||||||
# hide navigation
|
|
||||||
navHide: ->
|
|
||||||
return if !$('#navigation').is(':visible')
|
|
||||||
$('#navigation').addClass('hide')
|
|
||||||
|
|
||||||
updateNavMenu: =>
|
updateNavMenu: =>
|
||||||
delay = ->
|
delay = ->
|
||||||
|
@ -402,340 +392,3 @@ class App.Controller extends Spine.Controller
|
||||||
return true
|
return true
|
||||||
|
|
||||||
throw 'Cant reload page!'
|
throw 'Cant reload page!'
|
||||||
|
|
||||||
class App.ControllerPermanent extends App.Controller
|
|
||||||
constructor: ->
|
|
||||||
if @requiredPermission
|
|
||||||
@permissionCheckRedirect(@requiredPermission, true)
|
|
||||||
|
|
||||||
super
|
|
||||||
|
|
||||||
@navShow()
|
|
||||||
|
|
||||||
class App.ControllerSubContent extends App.Controller
|
|
||||||
constructor: ->
|
|
||||||
if @requiredPermission
|
|
||||||
@permissionCheckRedirect(@requiredPermission)
|
|
||||||
|
|
||||||
super
|
|
||||||
|
|
||||||
show: =>
|
|
||||||
if @genericController && @genericController.show
|
|
||||||
@genericController.show()
|
|
||||||
return if !@header
|
|
||||||
@title @header, true
|
|
||||||
|
|
||||||
hide: =>
|
|
||||||
if @genericController && @genericController.hide
|
|
||||||
@genericController.hide()
|
|
||||||
|
|
||||||
class App.ControllerContent extends App.Controller
|
|
||||||
constructor: ->
|
|
||||||
if @requiredPermission
|
|
||||||
@permissionCheckRedirect(@requiredPermission)
|
|
||||||
|
|
||||||
super
|
|
||||||
|
|
||||||
# hide tasks
|
|
||||||
App.TaskManager.hideAll()
|
|
||||||
$('#content').removeClass('hide').removeClass('active')
|
|
||||||
@navShow()
|
|
||||||
|
|
||||||
class App.ControllerModal extends App.Controller
|
|
||||||
authenticateRequired: false
|
|
||||||
backdrop: true
|
|
||||||
keyboard: true
|
|
||||||
large: false
|
|
||||||
small: false
|
|
||||||
veryLarge: false
|
|
||||||
head: '?'
|
|
||||||
autoFocusOnFirstInput: true
|
|
||||||
container: null
|
|
||||||
buttonClass: 'btn--success'
|
|
||||||
centerButtons: []
|
|
||||||
leftButtons: []
|
|
||||||
buttonClose: true
|
|
||||||
buttonCancel: false
|
|
||||||
buttonCancelClass: 'btn--text btn--subtle'
|
|
||||||
buttonSubmit: true
|
|
||||||
includeForm: true
|
|
||||||
headPrefix: ''
|
|
||||||
shown: true
|
|
||||||
closeOnAnyClick: false
|
|
||||||
initalFormParams: {}
|
|
||||||
initalFormParamsIgnore: false
|
|
||||||
showTrySupport: false
|
|
||||||
showTryMax: 10
|
|
||||||
showTrydelay: 1000
|
|
||||||
|
|
||||||
events:
|
|
||||||
'submit form': 'submit'
|
|
||||||
'click .js-submit:not(.is-disabled)': 'submit'
|
|
||||||
'click .js-cancel': 'cancel'
|
|
||||||
'click .js-close': 'cancel'
|
|
||||||
|
|
||||||
className: 'modal fade'
|
|
||||||
|
|
||||||
constructor: ->
|
|
||||||
super
|
|
||||||
@showTryCount = 0
|
|
||||||
|
|
||||||
if @authenticateRequired
|
|
||||||
return if !@authenticateCheckRedirect()
|
|
||||||
|
|
||||||
# rerender view, e. g. on langauge change
|
|
||||||
@bind('ui:rerender', =>
|
|
||||||
@update()
|
|
||||||
'modal'
|
|
||||||
)
|
|
||||||
if @shown
|
|
||||||
@render()
|
|
||||||
|
|
||||||
showDelayed: =>
|
|
||||||
delay = =>
|
|
||||||
@showTryCount += 1
|
|
||||||
@render()
|
|
||||||
@delay(delay, @showTrydelay)
|
|
||||||
|
|
||||||
modalAlreadyExists: ->
|
|
||||||
return true if $('.modal').length > 0
|
|
||||||
false
|
|
||||||
|
|
||||||
content: ->
|
|
||||||
'You need to implement a one @content()!'
|
|
||||||
|
|
||||||
update: =>
|
|
||||||
if @message
|
|
||||||
content = App.i18n.translateContent(@message)
|
|
||||||
else if @contentInline
|
|
||||||
content = @contentInline
|
|
||||||
else
|
|
||||||
content = @content()
|
|
||||||
modal = $(App.view('modal')(
|
|
||||||
head: @head
|
|
||||||
headPrefix: @headPrefix
|
|
||||||
message: @message
|
|
||||||
detail: @detail
|
|
||||||
buttonClose: @buttonClose
|
|
||||||
buttonCancel: @buttonCancel
|
|
||||||
buttonCancelClass: @buttonCancelClass
|
|
||||||
buttonSubmit: @buttonSubmit
|
|
||||||
buttonClass: @buttonClass
|
|
||||||
centerButtons: @centerButtons
|
|
||||||
leftButtons: @leftButtons
|
|
||||||
includeForm: @includeForm
|
|
||||||
))
|
|
||||||
modal.find('.modal-body').html(content)
|
|
||||||
if !@initRenderingDone
|
|
||||||
@initRenderingDone = true
|
|
||||||
@html(modal)
|
|
||||||
else
|
|
||||||
@$('.modal-dialog').replaceWith(modal)
|
|
||||||
@post()
|
|
||||||
|
|
||||||
post: ->
|
|
||||||
# nothing
|
|
||||||
|
|
||||||
element: =>
|
|
||||||
@el
|
|
||||||
|
|
||||||
render: =>
|
|
||||||
if @showTrySupport is true && @modalAlreadyExists() && @showTryCount <= @showTryMax
|
|
||||||
@showDelayed()
|
|
||||||
return
|
|
||||||
|
|
||||||
@initalFormParamsIgnore = false
|
|
||||||
|
|
||||||
if @buttonSubmit is true
|
|
||||||
@buttonSubmit = 'Submit'
|
|
||||||
if @buttonCancel is true
|
|
||||||
@buttonCancel = 'Cancel & Go Back'
|
|
||||||
|
|
||||||
@update()
|
|
||||||
|
|
||||||
if @container
|
|
||||||
@el.addClass('modal--local')
|
|
||||||
if @veryLarge
|
|
||||||
@el.addClass('modal--veryLarge')
|
|
||||||
if @large
|
|
||||||
@el.addClass('modal--large')
|
|
||||||
if @small
|
|
||||||
@el.addClass('modal--small')
|
|
||||||
|
|
||||||
@el
|
|
||||||
.on(
|
|
||||||
'show.bs.modal': @localOnShow
|
|
||||||
'shown.bs.modal': @localOnShown
|
|
||||||
'hide.bs.modal': @localOnClose
|
|
||||||
'hidden.bs.modal': @localOnClosed
|
|
||||||
'dismiss.bs.modal': @localOnCancel
|
|
||||||
).modal(
|
|
||||||
keyboard: @keyboard
|
|
||||||
show: true
|
|
||||||
backdrop: @backdrop
|
|
||||||
container: @container
|
|
||||||
)
|
|
||||||
|
|
||||||
if @closeOnAnyClick
|
|
||||||
@el.on('click', =>
|
|
||||||
@close()
|
|
||||||
)
|
|
||||||
|
|
||||||
close: (e) =>
|
|
||||||
if e
|
|
||||||
e.preventDefault()
|
|
||||||
@initalFormParamsIgnore = true
|
|
||||||
@el.modal('hide')
|
|
||||||
|
|
||||||
formParams: =>
|
|
||||||
if @container
|
|
||||||
return @formParam(@container.find('.modal form'))
|
|
||||||
return @formParam(@$('.modal form'))
|
|
||||||
|
|
||||||
showAlert: (message, suffix = 'danger') ->
|
|
||||||
alert = $('<div>')
|
|
||||||
.addClass("alert alert--#{suffix}")
|
|
||||||
.text(message)
|
|
||||||
|
|
||||||
@$('.modal-alerts-container').html(alert)
|
|
||||||
|
|
||||||
clearAlerts: ->
|
|
||||||
@$('.modal-alerts-container').empty()
|
|
||||||
|
|
||||||
localOnShow: (e) =>
|
|
||||||
@onShow(e)
|
|
||||||
|
|
||||||
onShow: (e) ->
|
|
||||||
# do nothing
|
|
||||||
|
|
||||||
localOnShown: (e) =>
|
|
||||||
@onShown(e)
|
|
||||||
|
|
||||||
onShown: (e) =>
|
|
||||||
if @autoFocusOnFirstInput
|
|
||||||
|
|
||||||
# select generated form
|
|
||||||
form = @$('.form-group').first()
|
|
||||||
|
|
||||||
# if not exists, use whole @el
|
|
||||||
if !form.get(0)
|
|
||||||
form = @el
|
|
||||||
|
|
||||||
# focus first input, select or textarea
|
|
||||||
form.find('input:not([disabled]):not([type="hidden"]):not(".btn"), select:not([disabled]), textarea:not([disabled])').first().focus()
|
|
||||||
|
|
||||||
@initalFormParams = @formParams()
|
|
||||||
|
|
||||||
localOnClose: (e) =>
|
|
||||||
diff = difference(@initalFormParams, @formParams())
|
|
||||||
if @initalFormParamsIgnore is false && !_.isEmpty(diff)
|
|
||||||
if !confirm(App.i18n.translateContent('The form content has been changed. Do you want to close it and lose your changes?'))
|
|
||||||
e.preventDefault()
|
|
||||||
return
|
|
||||||
@onClose(e)
|
|
||||||
|
|
||||||
onClose: ->
|
|
||||||
# do nothing
|
|
||||||
|
|
||||||
localOnClosed: (e) =>
|
|
||||||
@onClosed(e)
|
|
||||||
@el.modal('remove')
|
|
||||||
|
|
||||||
onClosed: (e) ->
|
|
||||||
# do nothing
|
|
||||||
|
|
||||||
localOnCancel: (e) =>
|
|
||||||
@onCancel(e)
|
|
||||||
|
|
||||||
onCancel: (e) ->
|
|
||||||
# do nothing
|
|
||||||
|
|
||||||
cancel: (e) =>
|
|
||||||
@close(e)
|
|
||||||
@onCancel(e)
|
|
||||||
|
|
||||||
onSubmit: (e) ->
|
|
||||||
# do nothing
|
|
||||||
|
|
||||||
submit: (e) =>
|
|
||||||
e.stopPropagation()
|
|
||||||
e.preventDefault()
|
|
||||||
@clearAlerts()
|
|
||||||
@onSubmit(e)
|
|
||||||
|
|
||||||
startLoading: =>
|
|
||||||
@$('.modal-body').addClass('hide')
|
|
||||||
@$('.modal-loader').removeClass('hide')
|
|
||||||
|
|
||||||
stopLoading: =>
|
|
||||||
@$('.modal-body').removeClass('hide')
|
|
||||||
@$('.modal-loader').addClass('hide')
|
|
||||||
|
|
||||||
class App.SessionMessage extends App.ControllerModal
|
|
||||||
showTrySupport: true
|
|
||||||
|
|
||||||
onCancel: (e) =>
|
|
||||||
if @forceReload
|
|
||||||
@windowReload(e)
|
|
||||||
|
|
||||||
onClose: (e) =>
|
|
||||||
if @forceReload
|
|
||||||
@windowReload(e)
|
|
||||||
|
|
||||||
onSubmit: (e) =>
|
|
||||||
if @forceReload
|
|
||||||
@windowReload(e)
|
|
||||||
else
|
|
||||||
@close()
|
|
||||||
|
|
||||||
class App.UpdateHeader extends App.Controller
|
|
||||||
constructor: ->
|
|
||||||
super
|
|
||||||
|
|
||||||
# subscribe and reload data / fetch new data if triggered
|
|
||||||
@subscribeId = @genericObject.subscribe(@render)
|
|
||||||
|
|
||||||
release: =>
|
|
||||||
App[ @genericObject.constructor.className ].unsubscribe(@subscribeId)
|
|
||||||
|
|
||||||
render: (genericObject) =>
|
|
||||||
@el.find('.page-header h1').html(genericObject.displayName())
|
|
||||||
|
|
||||||
|
|
||||||
class App.UpdateTastbar extends App.Controller
|
|
||||||
constructor: ->
|
|
||||||
super
|
|
||||||
|
|
||||||
# subscribe and reload data / fetch new data if triggered
|
|
||||||
@subscribeId = @genericObject.subscribe(@update)
|
|
||||||
|
|
||||||
release: =>
|
|
||||||
App[ @genericObject.constructor.className ].unsubscribe(@subscribeId)
|
|
||||||
|
|
||||||
update: (genericObject) =>
|
|
||||||
|
|
||||||
# update taskbar with new meta data
|
|
||||||
App.TaskManager.touch(@taskKey)
|
|
||||||
|
|
||||||
class App.ControllerWidgetPermanent extends App.Controller
|
|
||||||
constructor: (params) ->
|
|
||||||
if params.el
|
|
||||||
params.el.append('<div id="' + params.key + '"></div>')
|
|
||||||
params.el = ("##{params.key}")
|
|
||||||
|
|
||||||
super(params)
|
|
||||||
|
|
||||||
class App.ControllerWidgetOnDemand extends App.Controller
|
|
||||||
constructor: (params) ->
|
|
||||||
params.el = $("##{params.key}")
|
|
||||||
super
|
|
||||||
|
|
||||||
element: =>
|
|
||||||
$("##{@key}")
|
|
||||||
|
|
||||||
html: (raw) =>
|
|
||||||
|
|
||||||
# check if parent exists
|
|
||||||
if !$("##{@key}").get(0)
|
|
||||||
$('#app').before("<div id=\"#{@key}\" class=\"#{@className}\"></div>")
|
|
||||||
$("##{@key}").html raw
|
|
|
@ -0,0 +1,229 @@
|
||||||
|
class App.ControllerModal extends App.Controller
|
||||||
|
authenticateRequired: false
|
||||||
|
backdrop: true
|
||||||
|
keyboard: true
|
||||||
|
large: false
|
||||||
|
small: false
|
||||||
|
veryLarge: false
|
||||||
|
head: '?'
|
||||||
|
autoFocusOnFirstInput: true
|
||||||
|
container: null
|
||||||
|
buttonClass: 'btn--success'
|
||||||
|
centerButtons: []
|
||||||
|
leftButtons: []
|
||||||
|
buttonClose: true
|
||||||
|
buttonCancel: false
|
||||||
|
buttonCancelClass: 'btn--text btn--subtle'
|
||||||
|
buttonSubmit: true
|
||||||
|
includeForm: true
|
||||||
|
headPrefix: ''
|
||||||
|
shown: true
|
||||||
|
closeOnAnyClick: false
|
||||||
|
initalFormParams: {}
|
||||||
|
initalFormParamsIgnore: false
|
||||||
|
showTrySupport: false
|
||||||
|
showTryMax: 10
|
||||||
|
showTrydelay: 1000
|
||||||
|
|
||||||
|
events:
|
||||||
|
'submit form': 'submit'
|
||||||
|
'click .js-submit:not(.is-disabled)': 'submit'
|
||||||
|
'click .js-cancel': 'cancel'
|
||||||
|
'click .js-close': 'cancel'
|
||||||
|
|
||||||
|
className: 'modal fade'
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
@showTryCount = 0
|
||||||
|
|
||||||
|
if @authenticateRequired
|
||||||
|
return if !@authenticateCheckRedirect()
|
||||||
|
|
||||||
|
# rerender view, e. g. on langauge change
|
||||||
|
@controllerBind('ui:rerender', =>
|
||||||
|
@update()
|
||||||
|
'modal'
|
||||||
|
)
|
||||||
|
if @shown
|
||||||
|
@render()
|
||||||
|
|
||||||
|
showDelayed: =>
|
||||||
|
delay = =>
|
||||||
|
@showTryCount += 1
|
||||||
|
@render()
|
||||||
|
@delay(delay, @showTrydelay)
|
||||||
|
|
||||||
|
modalAlreadyExists: ->
|
||||||
|
return true if $('.modal').length > 0
|
||||||
|
false
|
||||||
|
|
||||||
|
content: ->
|
||||||
|
'You need to implement a one @content()!'
|
||||||
|
|
||||||
|
update: =>
|
||||||
|
if @message
|
||||||
|
content = App.i18n.translateContent(@message)
|
||||||
|
else if @contentInline
|
||||||
|
content = @contentInline
|
||||||
|
else
|
||||||
|
content = @content()
|
||||||
|
modal = $(App.view('modal')(
|
||||||
|
head: @head
|
||||||
|
headPrefix: @headPrefix
|
||||||
|
message: @message
|
||||||
|
detail: @detail
|
||||||
|
buttonClose: @buttonClose
|
||||||
|
buttonCancel: @buttonCancel
|
||||||
|
buttonCancelClass: @buttonCancelClass
|
||||||
|
buttonSubmit: @buttonSubmit
|
||||||
|
buttonClass: @buttonClass
|
||||||
|
centerButtons: @centerButtons
|
||||||
|
leftButtons: @leftButtons
|
||||||
|
includeForm: @includeForm
|
||||||
|
))
|
||||||
|
modal.find('.modal-body').html(content)
|
||||||
|
if !@initRenderingDone
|
||||||
|
@initRenderingDone = true
|
||||||
|
@html(modal)
|
||||||
|
else
|
||||||
|
@$('.modal-dialog').replaceWith(modal)
|
||||||
|
@post()
|
||||||
|
|
||||||
|
post: ->
|
||||||
|
# nothing
|
||||||
|
|
||||||
|
element: =>
|
||||||
|
@el
|
||||||
|
|
||||||
|
render: =>
|
||||||
|
if @showTrySupport is true && @modalAlreadyExists() && @showTryCount <= @showTryMax
|
||||||
|
@showDelayed()
|
||||||
|
return
|
||||||
|
|
||||||
|
@initalFormParamsIgnore = false
|
||||||
|
|
||||||
|
if @buttonSubmit is true
|
||||||
|
@buttonSubmit = 'Submit'
|
||||||
|
if @buttonCancel is true
|
||||||
|
@buttonCancel = 'Cancel & Go Back'
|
||||||
|
|
||||||
|
@update()
|
||||||
|
|
||||||
|
if @container
|
||||||
|
@el.addClass('modal--local')
|
||||||
|
if @veryLarge
|
||||||
|
@el.addClass('modal--veryLarge')
|
||||||
|
if @large
|
||||||
|
@el.addClass('modal--large')
|
||||||
|
if @small
|
||||||
|
@el.addClass('modal--small')
|
||||||
|
|
||||||
|
@el
|
||||||
|
.on(
|
||||||
|
'show.bs.modal': @localOnShow
|
||||||
|
'shown.bs.modal': @localOnShown
|
||||||
|
'hide.bs.modal': @localOnClose
|
||||||
|
'hidden.bs.modal': @localOnClosed
|
||||||
|
'dismiss.bs.modal': @localOnCancel
|
||||||
|
).modal(
|
||||||
|
keyboard: @keyboard
|
||||||
|
show: true
|
||||||
|
backdrop: @backdrop
|
||||||
|
container: @container
|
||||||
|
)
|
||||||
|
|
||||||
|
if @closeOnAnyClick
|
||||||
|
@el.on('click', =>
|
||||||
|
@close()
|
||||||
|
)
|
||||||
|
|
||||||
|
close: (e) =>
|
||||||
|
if e
|
||||||
|
e.preventDefault()
|
||||||
|
@initalFormParamsIgnore = true
|
||||||
|
@el.modal('hide')
|
||||||
|
|
||||||
|
formParams: =>
|
||||||
|
if @container
|
||||||
|
return @formParam(@container.find('.modal form'))
|
||||||
|
return @formParam(@$('.modal form'))
|
||||||
|
|
||||||
|
showAlert: (message, suffix = 'danger') ->
|
||||||
|
alert = $('<div>')
|
||||||
|
.addClass("alert alert--#{suffix}")
|
||||||
|
.text(message)
|
||||||
|
|
||||||
|
@$('.modal-alerts-container').html(alert)
|
||||||
|
|
||||||
|
clearAlerts: ->
|
||||||
|
@$('.modal-alerts-container').empty()
|
||||||
|
|
||||||
|
localOnShow: (e) =>
|
||||||
|
@onShow(e)
|
||||||
|
|
||||||
|
onShow: (e) ->
|
||||||
|
# do nothing
|
||||||
|
|
||||||
|
localOnShown: (e) =>
|
||||||
|
@onShown(e)
|
||||||
|
|
||||||
|
onShown: (e) =>
|
||||||
|
if @autoFocusOnFirstInput
|
||||||
|
|
||||||
|
# select generated form
|
||||||
|
form = @$('.form-group').first()
|
||||||
|
|
||||||
|
# if not exists, use whole @el
|
||||||
|
if !form.get(0)
|
||||||
|
form = @el
|
||||||
|
|
||||||
|
# focus first input, select or textarea
|
||||||
|
form.find('input:not([disabled]):not([type="hidden"]):not(".btn"), select:not([disabled]), textarea:not([disabled])').first().focus()
|
||||||
|
|
||||||
|
@initalFormParams = @formParams()
|
||||||
|
|
||||||
|
localOnClose: (e) =>
|
||||||
|
diff = difference(@initalFormParams, @formParams())
|
||||||
|
if @initalFormParamsIgnore is false && !_.isEmpty(diff)
|
||||||
|
if !confirm(App.i18n.translateContent('The form content has been changed. Do you want to close it and lose your changes?'))
|
||||||
|
e.preventDefault()
|
||||||
|
return
|
||||||
|
@onClose(e)
|
||||||
|
|
||||||
|
onClose: ->
|
||||||
|
# do nothing
|
||||||
|
|
||||||
|
localOnClosed: (e) =>
|
||||||
|
@onClosed(e)
|
||||||
|
@el.modal('remove')
|
||||||
|
|
||||||
|
onClosed: (e) ->
|
||||||
|
# do nothing
|
||||||
|
|
||||||
|
localOnCancel: (e) =>
|
||||||
|
@onCancel(e)
|
||||||
|
|
||||||
|
onCancel: (e) ->
|
||||||
|
# do nothing
|
||||||
|
|
||||||
|
cancel: (e) =>
|
||||||
|
@close(e)
|
||||||
|
@onCancel(e)
|
||||||
|
|
||||||
|
onSubmit: (e) ->
|
||||||
|
# do nothing
|
||||||
|
|
||||||
|
submit: (e) =>
|
||||||
|
e.stopPropagation()
|
||||||
|
e.preventDefault()
|
||||||
|
@clearAlerts()
|
||||||
|
@onSubmit(e)
|
||||||
|
|
||||||
|
startLoading: =>
|
||||||
|
@$('.modal-body').addClass('hide')
|
||||||
|
@$('.modal-loader').removeClass('hide')
|
||||||
|
|
||||||
|
stopLoading: =>
|
||||||
|
@$('.modal-body').removeClass('hide')
|
||||||
|
@$('.modal-loader').addClass('hide')
|
|
@ -0,0 +1,15 @@
|
||||||
|
class App.ControllerAppContent extends App.Controller
|
||||||
|
constructor: (params) ->
|
||||||
|
if @requiredPermission
|
||||||
|
@permissionCheckRedirect(@requiredPermission)
|
||||||
|
|
||||||
|
# hide tasks
|
||||||
|
App.TaskManager.hideAll()
|
||||||
|
|
||||||
|
params.el = params.appEl.find('#content')
|
||||||
|
params.el.removeClass('hide').removeClass('active')
|
||||||
|
if !params.el.get(0)
|
||||||
|
params.appEl.append('<div id="content" class="content flex horizontal"></div>')
|
||||||
|
params.el = $('#content')
|
||||||
|
|
||||||
|
super(params)
|
|
@ -0,0 +1,331 @@
|
||||||
|
class App.CollectionController extends App.Controller
|
||||||
|
events:
|
||||||
|
'click .js-remove': 'remove'
|
||||||
|
'click .js-item': 'click'
|
||||||
|
'click .js-locationVerify': 'location'
|
||||||
|
observe:
|
||||||
|
field1: true
|
||||||
|
field2: false
|
||||||
|
#currentItems: {}
|
||||||
|
#1:
|
||||||
|
# a: 123
|
||||||
|
# b: 'some string'
|
||||||
|
#2:
|
||||||
|
# a: 123
|
||||||
|
# b: 'some string'
|
||||||
|
#renderList: {}
|
||||||
|
#1: ..dom..ref..
|
||||||
|
#2: ..dom..ref..
|
||||||
|
template: '_need_to_be_defined_'
|
||||||
|
uniqKey: 'id'
|
||||||
|
model: '_need_to_be_defined_'
|
||||||
|
sortBy: 'name'
|
||||||
|
order: 'ASC',
|
||||||
|
insertPosition: 'after'
|
||||||
|
globalRerender: true
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
@events = @constructor.events unless @events
|
||||||
|
@observe = @constructor.observe unless @observe
|
||||||
|
@currentItems = {}
|
||||||
|
@renderList = {}
|
||||||
|
@queue = []
|
||||||
|
@queueRunning = false
|
||||||
|
@lastOrder = []
|
||||||
|
|
||||||
|
super
|
||||||
|
|
||||||
|
@queue.push ['renderAll']
|
||||||
|
@uIRunner()
|
||||||
|
|
||||||
|
# bind to changes
|
||||||
|
if @model
|
||||||
|
@subscribeId = App[@model].subscribe(@collectionSync)
|
||||||
|
|
||||||
|
# render on generic ui call
|
||||||
|
if @globalRerender
|
||||||
|
@controllerBind('ui:rerender', =>
|
||||||
|
@queue.push ['renderAll']
|
||||||
|
@uIRunner()
|
||||||
|
)
|
||||||
|
|
||||||
|
# render on login
|
||||||
|
@controllerBind('auth:login', =>
|
||||||
|
@queue.push ['renderAll']
|
||||||
|
@uIRunner()
|
||||||
|
)
|
||||||
|
|
||||||
|
# reset current tasks on logout
|
||||||
|
@controllerBind('auth:logout', =>
|
||||||
|
@queue.push ['renderAll']
|
||||||
|
@uIRunner()
|
||||||
|
)
|
||||||
|
|
||||||
|
@log 'debug', 'Init @uniqKey', @uniqKey
|
||||||
|
@log 'debug', 'Init @observe', @observe
|
||||||
|
@log 'debug', 'Init @model', @model
|
||||||
|
|
||||||
|
release: =>
|
||||||
|
if @subscribeId
|
||||||
|
App[@model].unsubscribe(@subscribeId)
|
||||||
|
|
||||||
|
uIRunner: =>
|
||||||
|
return if !@queue[0]
|
||||||
|
return if @queueRunning
|
||||||
|
@queueRunning = true
|
||||||
|
loop
|
||||||
|
param = @queue.shift()
|
||||||
|
if param[0] is 'domChange'
|
||||||
|
@domChange(param[1])
|
||||||
|
else if param[0] is 'domRemove'
|
||||||
|
@domRemove(param[1])
|
||||||
|
else if param[0] is 'change'
|
||||||
|
@collectionSync(param[1])
|
||||||
|
else if param[0] is 'destroy'
|
||||||
|
@collectionSync(param[1], 'destroy')
|
||||||
|
else if param[0] is 'renderAll'
|
||||||
|
@renderAll()
|
||||||
|
else
|
||||||
|
@log 'error', "Unknown type #{param[0]}", param[1]
|
||||||
|
if !@queue[0]
|
||||||
|
@onRenderEnd()
|
||||||
|
@queueRunning = false
|
||||||
|
break
|
||||||
|
|
||||||
|
collectionOrderGet: =>
|
||||||
|
newOrder = []
|
||||||
|
all = @itemsAll()
|
||||||
|
for item in all
|
||||||
|
newOrder.push item[@uniqKey]
|
||||||
|
newOrder
|
||||||
|
|
||||||
|
collectionOrderSet: (newOrder = false) =>
|
||||||
|
if !newOrder
|
||||||
|
newOrder = @collectionOrderGet()
|
||||||
|
@lastOrder = newOrder
|
||||||
|
|
||||||
|
collectionSync: (items, type) =>
|
||||||
|
|
||||||
|
# remove items
|
||||||
|
if type is 'destroy'
|
||||||
|
ids = []
|
||||||
|
for item in items
|
||||||
|
ids.push item[@uniqKey]
|
||||||
|
@queue.push ['domRemove', ids]
|
||||||
|
@uIRunner()
|
||||||
|
return
|
||||||
|
|
||||||
|
# inital render
|
||||||
|
if _.isEmpty(@renderList)
|
||||||
|
@queue.push ['renderAll']
|
||||||
|
@uIRunner()
|
||||||
|
return
|
||||||
|
|
||||||
|
# check if item order is the same
|
||||||
|
newOrder = @collectionOrderGet()
|
||||||
|
removedIds = _.difference(@lastOrder, newOrder)
|
||||||
|
addedIds = _.difference(newOrder, @lastOrder)
|
||||||
|
|
||||||
|
@log 'debug', 'collectionSync removedIds', removedIds
|
||||||
|
@log 'debug', 'collectionSync addedIds', addedIds
|
||||||
|
@log 'debug', 'collectionSync @lastOrder', @lastOrder
|
||||||
|
@log 'debug', 'collectionSync newOrder', newOrder
|
||||||
|
|
||||||
|
# add items
|
||||||
|
alreadyRemoved = false
|
||||||
|
if !_.isEmpty(addedIds)
|
||||||
|
lastOrderNew = []
|
||||||
|
for id in @lastOrder
|
||||||
|
if !_.contains(removedIds, id)
|
||||||
|
lastOrderNew.push id
|
||||||
|
|
||||||
|
# try to find positions of new items
|
||||||
|
@log 'debug', 'collectionSync lastOrderNew', lastOrderNew
|
||||||
|
applyOrder = App.Utils.diffPositionAdd(lastOrderNew, newOrder)
|
||||||
|
@log 'debug', 'collectionSync applyOrder', applyOrder
|
||||||
|
if !applyOrder
|
||||||
|
@queue.push ['renderAll']
|
||||||
|
@uIRunner()
|
||||||
|
return
|
||||||
|
|
||||||
|
if !_.isEmpty(removedIds)
|
||||||
|
alreadyRemoved = true
|
||||||
|
@queue.push ['domRemove', removedIds]
|
||||||
|
@uIRunner()
|
||||||
|
|
||||||
|
newItems = []
|
||||||
|
for apply in applyOrder
|
||||||
|
item = @itemGet(apply.id)
|
||||||
|
item.meta_position = apply.position
|
||||||
|
newItems.push item
|
||||||
|
@queue.push ['domChange', newItems]
|
||||||
|
@uIRunner()
|
||||||
|
|
||||||
|
# remove items
|
||||||
|
if !alreadyRemoved && !_.isEmpty(removedIds)
|
||||||
|
@queue.push ['domRemove', removedIds]
|
||||||
|
@uIRunner()
|
||||||
|
|
||||||
|
# update items
|
||||||
|
newItems = []
|
||||||
|
for item in items
|
||||||
|
if !_.contains(removedIds, item.id) && !_.contains(addedIds, item.id)
|
||||||
|
newItems.push item
|
||||||
|
return if _.isEmpty(newItems)
|
||||||
|
@queue.push ['domChange', newItems]
|
||||||
|
@uIRunner()
|
||||||
|
#return
|
||||||
|
|
||||||
|
# rerender all items
|
||||||
|
#@queue.push ['renderAll']
|
||||||
|
#@uIRunner()
|
||||||
|
|
||||||
|
domRemove: (ids) =>
|
||||||
|
@log 'debug', 'domRemove', ids
|
||||||
|
for id in ids
|
||||||
|
@itemAttributesDelete(id)
|
||||||
|
if @renderList[id]
|
||||||
|
@renderList[id].remove()
|
||||||
|
delete @renderList[id]
|
||||||
|
@onRemoved(id)
|
||||||
|
@collectionOrderSet()
|
||||||
|
|
||||||
|
domChange: (items) =>
|
||||||
|
@log 'debug', 'domChange items', items
|
||||||
|
@log 'debug', 'domChange @currentItems', @currentItems
|
||||||
|
changedItems = []
|
||||||
|
for item in items
|
||||||
|
@log 'debug', 'domChange|item', item
|
||||||
|
attributes = @itemAttributes(item)
|
||||||
|
currentItem = @itemAttributesGet(item[@uniqKey])
|
||||||
|
if !currentItem
|
||||||
|
@log 'debug', 'domChange|add', item
|
||||||
|
changedItems.push item
|
||||||
|
@itemAttributesSet(item[@uniqKey], attributes)
|
||||||
|
else
|
||||||
|
@log 'debug', 'domChange|change', item
|
||||||
|
@log 'debug', 'domChange|change|observe attributes', @observe
|
||||||
|
@log 'debug', 'domChange|change|current', currentItem
|
||||||
|
@log 'debug', 'domChange|change|new', attributes
|
||||||
|
for field of @observe
|
||||||
|
@log 'debug', 'domChange|change|compare', field, currentItem[field], attributes[field]
|
||||||
|
diff = !_.isEqual(currentItem[field], attributes[field])
|
||||||
|
@log 'debug', 'domChange|diff', diff
|
||||||
|
if diff
|
||||||
|
changedItems.push item
|
||||||
|
@itemAttributesSet(item[@uniqKey], attributes)
|
||||||
|
break
|
||||||
|
return if _.isEmpty(changedItems)
|
||||||
|
@renderParts(changedItems)
|
||||||
|
|
||||||
|
renderAll: =>
|
||||||
|
items = @itemsAll()
|
||||||
|
@log 'debug', 'renderAll', items
|
||||||
|
localeEls = []
|
||||||
|
for item in items
|
||||||
|
attributes = @itemAttributes(item)
|
||||||
|
@itemAttributesSet(item[@uniqKey], attributes)
|
||||||
|
localeEls.push @renderItem(item, false)
|
||||||
|
@html localeEls
|
||||||
|
@collectionOrderSet()
|
||||||
|
@onRenderEnd()
|
||||||
|
|
||||||
|
itemDestroy: (id) =>
|
||||||
|
App[@model].destroy(id)
|
||||||
|
|
||||||
|
itemsAll: =>
|
||||||
|
App[@model].search(sortBy: @sortBy, order: @order)
|
||||||
|
|
||||||
|
itemAttributesDiff: (item) =>
|
||||||
|
attributes = @itemAttributes(item)
|
||||||
|
currentItem = @itemAttributesGet(item[@uniqKey])
|
||||||
|
for field of @observe
|
||||||
|
@log 'debug', 'itemAttributesDiff|compare', field, currentItem[field], attributes[field]
|
||||||
|
diff = !_.isEqual(currentItem[field], attributes[field])
|
||||||
|
if diff
|
||||||
|
@log 'debug', 'itemAttributesDiff|diff', diff
|
||||||
|
return true
|
||||||
|
false
|
||||||
|
|
||||||
|
itemAttributesDelete: (id) =>
|
||||||
|
delete @currentItems[id]
|
||||||
|
|
||||||
|
itemAttributesGet: (id) =>
|
||||||
|
@currentItems[id]
|
||||||
|
|
||||||
|
itemAttributesSet: (id, attributes) =>
|
||||||
|
@currentItems[id] = attributes
|
||||||
|
|
||||||
|
itemAttributes: (item) =>
|
||||||
|
attributes = {}
|
||||||
|
for field of @observe
|
||||||
|
attributes[field] = item[field]
|
||||||
|
attributes
|
||||||
|
|
||||||
|
itemGet: (id) =>
|
||||||
|
App[@model].find(id)
|
||||||
|
|
||||||
|
renderParts: (items) =>
|
||||||
|
@log 'debug', 'renderParts', items
|
||||||
|
for item in items
|
||||||
|
if !@renderList[item[@uniqKey]]
|
||||||
|
@renderItem(item)
|
||||||
|
else
|
||||||
|
@renderItem(item, @renderList[item[@uniqKey]])
|
||||||
|
@collectionOrderSet()
|
||||||
|
|
||||||
|
renderItem: (item, el) =>
|
||||||
|
if @prepareForObjectListItemSupport
|
||||||
|
item = @prepareForObjectListItem(item)
|
||||||
|
@log 'debug', 'renderItem', item, @template, el, @renderList[item[@uniqKey]]
|
||||||
|
html = $(App.view(@template)(
|
||||||
|
item: item
|
||||||
|
))
|
||||||
|
if @onRenderItemEnd
|
||||||
|
@onRenderItemEnd(item, html)
|
||||||
|
itemCount = Object.keys(@renderList).length
|
||||||
|
@renderList[item[@uniqKey]] = html
|
||||||
|
if el is false
|
||||||
|
return html
|
||||||
|
else if !el
|
||||||
|
position = item.meta_position
|
||||||
|
if itemCount > position
|
||||||
|
position += 1
|
||||||
|
element = @el.find(".js-item:nth-child(#{position})")
|
||||||
|
if !element.get(0)
|
||||||
|
@el.append(html)
|
||||||
|
return
|
||||||
|
if @insertPosition is 'before'
|
||||||
|
element.before(html)
|
||||||
|
else
|
||||||
|
element.after(html)
|
||||||
|
else
|
||||||
|
el.replaceWith(html)
|
||||||
|
|
||||||
|
onRenderEnd: ->
|
||||||
|
# nothing
|
||||||
|
|
||||||
|
location: (e) =>
|
||||||
|
@locationVerify(e)
|
||||||
|
|
||||||
|
click: (e) =>
|
||||||
|
row = $(e.target).closest('.js-item')
|
||||||
|
id = row.data('id')
|
||||||
|
@onClick(id, e)
|
||||||
|
|
||||||
|
onClick: (id, e) ->
|
||||||
|
# nothing
|
||||||
|
|
||||||
|
remove: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
row = $(e.target).closest('.js-item')
|
||||||
|
id = row.data('id')
|
||||||
|
@onRemove(id,e)
|
||||||
|
@itemDestroy(id)
|
||||||
|
|
||||||
|
onRemove: (id, e) ->
|
||||||
|
# nothing
|
||||||
|
|
||||||
|
onRemoved: (id) ->
|
||||||
|
# nothing
|
|
@ -0,0 +1,19 @@
|
||||||
|
class App.ControllerDrox extends App.Controller
|
||||||
|
constructor: (params) ->
|
||||||
|
super
|
||||||
|
|
||||||
|
if params.data && ( params.data.text || params.data.html )
|
||||||
|
@inline(params.data)
|
||||||
|
|
||||||
|
inline: (data) ->
|
||||||
|
@html App.view('generic/drox')(data)
|
||||||
|
if data.text
|
||||||
|
@$('.drox-body').text(data.text)
|
||||||
|
if data.html
|
||||||
|
@$('.drox-body').html(data.html)
|
||||||
|
|
||||||
|
template: (data) ->
|
||||||
|
drox = $( App.view('generic/drox')(data) )
|
||||||
|
content = App.view(data.file)(data.params)
|
||||||
|
drox.find('.drox-body').append(content)
|
||||||
|
drox
|
|
@ -0,0 +1,20 @@
|
||||||
|
class App.ControllerFullPage extends App.Controller
|
||||||
|
constructor: (params) ->
|
||||||
|
if @requiredPermission
|
||||||
|
@permissionCheckRedirect(@requiredPermission)
|
||||||
|
super
|
||||||
|
|
||||||
|
replaceWith: (localElement) =>
|
||||||
|
@appEl.find('>').not(".#{@className}").remove() if @className
|
||||||
|
@appEl.find('>').filter(".#{@className}").remove() if @forceRender
|
||||||
|
@el = $(localElement)
|
||||||
|
container = @appEl.find('>').filter(".#{@className}")
|
||||||
|
if !container.get(0)
|
||||||
|
@el.addClass(@className)
|
||||||
|
@appEl.append(@el)
|
||||||
|
@delegateEvents(@events)
|
||||||
|
@refreshElements()
|
||||||
|
@el.on('remove', @releaseController)
|
||||||
|
@el.on('remove', @release)
|
||||||
|
else
|
||||||
|
container.html(@el.children())
|
|
@ -0,0 +1,11 @@
|
||||||
|
class App.ControllerGenericDescription extends App.ControllerModal
|
||||||
|
buttonClose: true
|
||||||
|
buttonCancel: false
|
||||||
|
buttonSubmit: 'Close'
|
||||||
|
head: 'Description'
|
||||||
|
|
||||||
|
content: =>
|
||||||
|
marked(App.i18n.translateContent(@description))
|
||||||
|
|
||||||
|
onSubmit: =>
|
||||||
|
@close()
|
|
@ -0,0 +1,37 @@
|
||||||
|
class App.ControllerGenericDestroyConfirm extends App.ControllerModal
|
||||||
|
buttonClose: true
|
||||||
|
buttonCancel: true
|
||||||
|
buttonSubmit: 'delete'
|
||||||
|
buttonClass: 'btn--danger'
|
||||||
|
head: 'Confirm'
|
||||||
|
small: true
|
||||||
|
|
||||||
|
content: ->
|
||||||
|
App.i18n.translateContent('Sure to delete this object?')
|
||||||
|
|
||||||
|
onSubmit: =>
|
||||||
|
options = @options || {}
|
||||||
|
options.done = =>
|
||||||
|
@close()
|
||||||
|
if @callback
|
||||||
|
@callback()
|
||||||
|
options.fail = =>
|
||||||
|
@log 'errors'
|
||||||
|
@close()
|
||||||
|
@item.destroy(options)
|
||||||
|
|
||||||
|
class App.ControllerConfirm extends App.ControllerModal
|
||||||
|
buttonClose: true
|
||||||
|
buttonCancel: true
|
||||||
|
buttonSubmit: 'yes'
|
||||||
|
buttonClass: 'btn--danger'
|
||||||
|
head: 'Confirm'
|
||||||
|
small: true
|
||||||
|
|
||||||
|
content: ->
|
||||||
|
App.i18n.translateContent(@message)
|
||||||
|
|
||||||
|
onSubmit: =>
|
||||||
|
@close()
|
||||||
|
if @callback
|
||||||
|
@callback()
|
|
@ -0,0 +1,53 @@
|
||||||
|
class App.ControllerGenericEdit extends App.ControllerModal
|
||||||
|
buttonClose: true
|
||||||
|
buttonCancel: true
|
||||||
|
buttonSubmit: true
|
||||||
|
headPrefix: 'Edit'
|
||||||
|
|
||||||
|
content: =>
|
||||||
|
@item = App[ @genericObject ].find( @id )
|
||||||
|
@head = @pageData.head || @pageData.object
|
||||||
|
|
||||||
|
@controller = new App.ControllerForm(
|
||||||
|
model: App[ @genericObject ]
|
||||||
|
params: @item
|
||||||
|
screen: @screen || 'edit'
|
||||||
|
autofocus: true
|
||||||
|
handlers: @handlers
|
||||||
|
)
|
||||||
|
@controller.form
|
||||||
|
|
||||||
|
onSubmit: (e) ->
|
||||||
|
params = @formParam(e.target)
|
||||||
|
@item.load(params)
|
||||||
|
|
||||||
|
# validate form using HTML5 validity check
|
||||||
|
element = $(e.target).closest('form').get(0)
|
||||||
|
if element && element.reportValidity && !element.reportValidity()
|
||||||
|
return false
|
||||||
|
|
||||||
|
# validate
|
||||||
|
errors = @item.validate()
|
||||||
|
if errors
|
||||||
|
@log 'error', errors
|
||||||
|
@formValidate( form: e.target, errors: errors )
|
||||||
|
return false
|
||||||
|
|
||||||
|
# disable form
|
||||||
|
@formDisable(e)
|
||||||
|
|
||||||
|
# save object
|
||||||
|
ui = @
|
||||||
|
@item.save(
|
||||||
|
done: ->
|
||||||
|
if ui.callback
|
||||||
|
item = App[ ui.genericObject ].fullLocal(@id)
|
||||||
|
ui.callback(item)
|
||||||
|
ui.close()
|
||||||
|
|
||||||
|
fail: (settings, details) ->
|
||||||
|
App[ ui.genericObject ].fetch(id: @id)
|
||||||
|
ui.log 'errors'
|
||||||
|
ui.formEnable(e)
|
||||||
|
ui.controller.showAlert(details.error_human || details.error || 'Unable to update object!')
|
||||||
|
)
|
|
@ -0,0 +1,17 @@
|
||||||
|
class App.ControllerErrorModal extends App.ControllerModal
|
||||||
|
buttonClose: true
|
||||||
|
buttonCancel: false
|
||||||
|
buttonSubmit: 'Close'
|
||||||
|
#buttonClass: 'btn--danger'
|
||||||
|
head: 'Error'
|
||||||
|
#small: true
|
||||||
|
#shown: true
|
||||||
|
showTrySupport: true
|
||||||
|
|
||||||
|
content: ->
|
||||||
|
@message
|
||||||
|
|
||||||
|
onSubmit: =>
|
||||||
|
@close()
|
||||||
|
if @callback
|
||||||
|
@callback()
|
|
@ -0,0 +1,112 @@
|
||||||
|
class App.GenericHistory extends App.ControllerModal
|
||||||
|
@extend App.PopoverProvidable
|
||||||
|
@registerPopovers 'User'
|
||||||
|
|
||||||
|
buttonClose: true
|
||||||
|
buttonCancel: false
|
||||||
|
buttonSubmit: false
|
||||||
|
head: 'History'
|
||||||
|
shown: false
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
@fetch()
|
||||||
|
|
||||||
|
content: =>
|
||||||
|
localItem = @reworkItems(@items)
|
||||||
|
|
||||||
|
content = $ App.view('generic/history')(
|
||||||
|
items: localItem
|
||||||
|
)
|
||||||
|
content.find('a[data-type="sortorder"]').bind('click', (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
@sortorder()
|
||||||
|
)
|
||||||
|
content
|
||||||
|
|
||||||
|
onShown: =>
|
||||||
|
@renderPopovers()
|
||||||
|
|
||||||
|
sortorder: =>
|
||||||
|
@items = @items.reverse()
|
||||||
|
@update()
|
||||||
|
|
||||||
|
T: (name) ->
|
||||||
|
App.i18n.translateInline(name)
|
||||||
|
|
||||||
|
reworkItems: (items) ->
|
||||||
|
newItems = []
|
||||||
|
newItem = {}
|
||||||
|
lastUserId = undefined
|
||||||
|
lastTime = undefined
|
||||||
|
items = clone(items)
|
||||||
|
for item in items
|
||||||
|
|
||||||
|
if item.object is 'Ticket::Article'
|
||||||
|
item.object = 'Article'
|
||||||
|
|
||||||
|
data = item
|
||||||
|
data.created_by = App.User.find( item.created_by_id )
|
||||||
|
|
||||||
|
currentItemTime = new Date( item.created_at )
|
||||||
|
lastItemTime = new Date( new Date( lastTime ).getTime() + (15 * 1000) )
|
||||||
|
|
||||||
|
# start new section if user or time has changed
|
||||||
|
if lastUserId isnt item.created_by_id || currentItemTime > lastItemTime
|
||||||
|
lastTime = item.created_at
|
||||||
|
lastUserId = item.created_by_id
|
||||||
|
if !_.isEmpty(newItem)
|
||||||
|
newItems.push newItem
|
||||||
|
newItem =
|
||||||
|
created_at: item.created_at
|
||||||
|
created_by: App.User.find( item.created_by_id )
|
||||||
|
records: []
|
||||||
|
|
||||||
|
# build content
|
||||||
|
content = ''
|
||||||
|
if item.type is 'notification' || item.type is 'email'
|
||||||
|
content = "#{ @T( item.type ) } #{ @T( 'sent to' ) } '#{ item.value_to }'"
|
||||||
|
else if item.type is 'received_merge'
|
||||||
|
ticket = App.Ticket.find( item.id_from )
|
||||||
|
ticket_link = if ticket
|
||||||
|
"<a href=\"#ticket/zoom/#{ item.id_from }\">##{ ticket.number }</a>"
|
||||||
|
else
|
||||||
|
item.value_from
|
||||||
|
content = "#{ @T( 'Ticket' ) } #{ ticket_link } #{ @T( 'was merged into this ticket' ) }"
|
||||||
|
else if item.type is 'merged_into'
|
||||||
|
ticket = App.Ticket.find( item.id_to )
|
||||||
|
ticket_link = if ticket
|
||||||
|
"<a href=\"#ticket/zoom/#{ item.id_to }\">##{ ticket.number }</a>"
|
||||||
|
else
|
||||||
|
item.value_to
|
||||||
|
content = "#{ @T( 'This ticket was merged into' ) } #{ @T( 'ticket' ) } #{ ticket_link }"
|
||||||
|
else
|
||||||
|
content = "#{ @T( item.type ) } #{ @T(item.object) } "
|
||||||
|
if item.attribute
|
||||||
|
content += "#{ @T(item.attribute) }"
|
||||||
|
|
||||||
|
# convert time stamps
|
||||||
|
if item.object is 'User' && item.attribute is 'last_login'
|
||||||
|
if item.value_from
|
||||||
|
item.value_from = App.i18n.translateTimestamp( item.value_from )
|
||||||
|
if item.value_to
|
||||||
|
item.value_to = App.i18n.translateTimestamp( item.value_to )
|
||||||
|
|
||||||
|
if item.value_from
|
||||||
|
if item.value_to
|
||||||
|
content += " #{ @T( 'from' ) }"
|
||||||
|
content += " '#{ App.Utils.htmlEscape(item.value_from) }'"
|
||||||
|
|
||||||
|
if item.value_to
|
||||||
|
if item.value_from
|
||||||
|
content += ' →'
|
||||||
|
content += " '#{ App.Utils.htmlEscape(item.value_to) }'"
|
||||||
|
else if item.value_from
|
||||||
|
content += " → '-'"
|
||||||
|
|
||||||
|
newItem.records.push content
|
||||||
|
|
||||||
|
if !_.isEmpty(newItem)
|
||||||
|
newItems.push newItem
|
||||||
|
|
||||||
|
newItems
|
|
@ -0,0 +1,192 @@
|
||||||
|
class App.ControllerGenericIndex extends App.Controller
|
||||||
|
events:
|
||||||
|
'click [data-type=edit]': 'edit'
|
||||||
|
'click [data-type=new]': 'new'
|
||||||
|
'click [data-type=import]': 'import'
|
||||||
|
'click .js-description': 'description'
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
|
||||||
|
# set title
|
||||||
|
if @pageData.title
|
||||||
|
@title @pageData.title, true
|
||||||
|
|
||||||
|
# set nav bar
|
||||||
|
if @pageData.navupdate
|
||||||
|
@navupdate @pageData.navupdate
|
||||||
|
|
||||||
|
# bind render after a change is done
|
||||||
|
if !@disableRender
|
||||||
|
@subscribeId = App[ @genericObject ].subscribe(@render)
|
||||||
|
|
||||||
|
App[ @genericObject ].bind 'ajaxError', (rec, msg) =>
|
||||||
|
@log 'error', 'ajax', msg.status
|
||||||
|
if msg.status is 401
|
||||||
|
@log 'error', 'ajax', rec, msg, msg.status
|
||||||
|
@navigate 'login'
|
||||||
|
|
||||||
|
# execute fetch
|
||||||
|
@render()
|
||||||
|
|
||||||
|
# fetch all
|
||||||
|
if !@disableInitFetch && !@pageData.pagerAjax
|
||||||
|
App[ @genericObject ].fetchFull(
|
||||||
|
->
|
||||||
|
clear: true
|
||||||
|
)
|
||||||
|
|
||||||
|
show: =>
|
||||||
|
if @table
|
||||||
|
@table.show()
|
||||||
|
|
||||||
|
hide: =>
|
||||||
|
if @table
|
||||||
|
@table.hide()
|
||||||
|
|
||||||
|
release: =>
|
||||||
|
if @subscribeId
|
||||||
|
App[ @genericObject ].unsubscribe(@subscribeId)
|
||||||
|
|
||||||
|
paginate: (page) =>
|
||||||
|
return if page is @pageData.pagerSelected
|
||||||
|
@pageData.pagerSelected = page
|
||||||
|
@render()
|
||||||
|
|
||||||
|
render: =>
|
||||||
|
if @pageData.pagerAjax
|
||||||
|
sortBy = @table?.customOrderBy || @table?.orderBy || @defaultSortBy || 'id'
|
||||||
|
orderBy = @table?.customOrderDirection || @table?.orderDirection || @defaultOrder || 'ASC'
|
||||||
|
|
||||||
|
fallbackSortBy = sortBy
|
||||||
|
fallbackOrderBy = orderBy
|
||||||
|
if sortBy isnt 'id'
|
||||||
|
fallbackSortBy = "#{sortBy}, id"
|
||||||
|
fallbackOrderBy = "#{orderBy}, ASC"
|
||||||
|
|
||||||
|
@startLoading()
|
||||||
|
App[@genericObject].indexFull(
|
||||||
|
(collection, data) =>
|
||||||
|
@pageData.pagerTotalCount = data.total_count
|
||||||
|
@stopLoading()
|
||||||
|
@renderObjects(collection)
|
||||||
|
{
|
||||||
|
refresh: false
|
||||||
|
sort_by: fallbackSortBy
|
||||||
|
order_by: fallbackOrderBy
|
||||||
|
page: @pageData.pagerSelected
|
||||||
|
per_page: @pageData.pagerPerPage
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
objects = App[@genericObject].search(
|
||||||
|
sortBy: @defaultSortBy || 'name'
|
||||||
|
order: @defaultOrder
|
||||||
|
)
|
||||||
|
@renderObjects(objects)
|
||||||
|
|
||||||
|
renderObjects: (objects) =>
|
||||||
|
|
||||||
|
# remove ignored items from collection
|
||||||
|
if @ignoreObjectIDs
|
||||||
|
objects = _.filter( objects, (item) ->
|
||||||
|
return if item.id is 1
|
||||||
|
return item
|
||||||
|
)
|
||||||
|
|
||||||
|
if !@table
|
||||||
|
|
||||||
|
# show description button, only if content exists
|
||||||
|
showDescription = false
|
||||||
|
if App[ @genericObject ].description && !_.isEmpty(objects)
|
||||||
|
showDescription = true
|
||||||
|
|
||||||
|
@html App.view('generic/admin/index')(
|
||||||
|
head: @pageData.objects
|
||||||
|
notes: @pageData.notes
|
||||||
|
buttons: @pageData.buttons
|
||||||
|
menus: @pageData.menus
|
||||||
|
showDescription: showDescription
|
||||||
|
)
|
||||||
|
|
||||||
|
# show description in content if no no content exists
|
||||||
|
if _.isEmpty(objects) && App[ @genericObject ].description
|
||||||
|
description = marked(App[ @genericObject ].description)
|
||||||
|
@$('.table-overview').html(description)
|
||||||
|
return
|
||||||
|
|
||||||
|
# append content table
|
||||||
|
params = _.extend(
|
||||||
|
{
|
||||||
|
tableId: "#{@genericObject}-generic-overview"
|
||||||
|
el: @$('.table-overview')
|
||||||
|
model: App[ @genericObject ]
|
||||||
|
objects: objects
|
||||||
|
bindRow:
|
||||||
|
events:
|
||||||
|
click: @edit
|
||||||
|
container: @container
|
||||||
|
explanation: @pageData.explanation
|
||||||
|
groupBy: @groupBy
|
||||||
|
dndCallback: @dndCallback
|
||||||
|
},
|
||||||
|
@pageData.tableExtend
|
||||||
|
)
|
||||||
|
|
||||||
|
if @pageData.pagerAjax
|
||||||
|
params = _.extend(
|
||||||
|
{
|
||||||
|
pagerAjax: @pageData.pagerAjax
|
||||||
|
pagerBaseUrl: @pageData.pagerBaseUrl
|
||||||
|
pagerSelected: @pageData.pagerSelected
|
||||||
|
pagerPerPage: @pageData.pagerPerPage
|
||||||
|
pagerTotalCount: @pageData.pagerTotalCount
|
||||||
|
sortRenderCallback: @render
|
||||||
|
},
|
||||||
|
params
|
||||||
|
)
|
||||||
|
|
||||||
|
if !@table
|
||||||
|
@table = new App.ControllerTable(params)
|
||||||
|
else
|
||||||
|
@table.update(objects: objects, pagerSelected: @pageData.pagerSelected, pagerTotalCount: @pageData.pagerTotalCount)
|
||||||
|
|
||||||
|
edit: (id, e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
item = App[ @genericObject ].find(id)
|
||||||
|
|
||||||
|
if @editCallback
|
||||||
|
@editCallback(item)
|
||||||
|
return
|
||||||
|
|
||||||
|
new App.ControllerGenericEdit(
|
||||||
|
id: item.id
|
||||||
|
pageData: @pageData
|
||||||
|
genericObject: @genericObject
|
||||||
|
container: @container
|
||||||
|
small: @small
|
||||||
|
large: @large
|
||||||
|
veryLarge: @veryLarge
|
||||||
|
)
|
||||||
|
|
||||||
|
new: (e) ->
|
||||||
|
e.preventDefault()
|
||||||
|
new App.ControllerGenericNew(
|
||||||
|
pageData: @pageData
|
||||||
|
genericObject: @genericObject
|
||||||
|
container: @container
|
||||||
|
small: @small
|
||||||
|
large: @large
|
||||||
|
veryLarge: @veryLarge
|
||||||
|
)
|
||||||
|
|
||||||
|
import: (e) ->
|
||||||
|
e.preventDefault()
|
||||||
|
@importCallback()
|
||||||
|
|
||||||
|
description: (e) =>
|
||||||
|
new App.ControllerGenericDescription(
|
||||||
|
description: App[ @genericObject ].description
|
||||||
|
container: @container
|
||||||
|
)
|
|
@ -0,0 +1,53 @@
|
||||||
|
class App.ControllerGenericNew extends App.ControllerModal
|
||||||
|
buttonClose: true
|
||||||
|
buttonCancel: true
|
||||||
|
buttonSubmit: true
|
||||||
|
headPrefix: 'New'
|
||||||
|
showTrySupport: true
|
||||||
|
|
||||||
|
content: =>
|
||||||
|
@head = @pageData.head || @pageData.object
|
||||||
|
@controller = new App.ControllerForm(
|
||||||
|
model: App[ @genericObject ]
|
||||||
|
params: @item
|
||||||
|
screen: @screen || 'edit'
|
||||||
|
autofocus: true
|
||||||
|
handlers: @handlers
|
||||||
|
)
|
||||||
|
@controller.form
|
||||||
|
|
||||||
|
onSubmit: (e) ->
|
||||||
|
params = @formParam(e.target)
|
||||||
|
|
||||||
|
object = new App[ @genericObject ]
|
||||||
|
object.load(params)
|
||||||
|
|
||||||
|
# validate form using HTML5 validity check
|
||||||
|
element = $(e.target).closest('form').get(0)
|
||||||
|
if element && element.reportValidity && !element.reportValidity()
|
||||||
|
return false
|
||||||
|
|
||||||
|
# validate
|
||||||
|
errors = object.validate()
|
||||||
|
if errors
|
||||||
|
@log 'error', errors
|
||||||
|
@formValidate( form: e.target, errors: errors )
|
||||||
|
return false
|
||||||
|
|
||||||
|
# disable form
|
||||||
|
@formDisable(e)
|
||||||
|
|
||||||
|
# save object
|
||||||
|
ui = @
|
||||||
|
object.save(
|
||||||
|
done: ->
|
||||||
|
if ui.callback
|
||||||
|
item = App[ ui.genericObject ].fullLocal(@id)
|
||||||
|
ui.callback(item)
|
||||||
|
ui.close()
|
||||||
|
|
||||||
|
fail: (settings, details) ->
|
||||||
|
ui.log 'errors', details
|
||||||
|
ui.formEnable(e)
|
||||||
|
ui.controller.showAlert(details.error_human || details.error || 'Unable to create object!')
|
||||||
|
)
|
|
@ -0,0 +1,48 @@
|
||||||
|
class App.ControllerModalLoading extends App.Controller
|
||||||
|
className: 'modal fade'
|
||||||
|
showTrySupport: true
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
|
||||||
|
if @container
|
||||||
|
@el.addClass('modal--local')
|
||||||
|
|
||||||
|
@render()
|
||||||
|
|
||||||
|
@el.modal(
|
||||||
|
keyboard: false
|
||||||
|
show: true
|
||||||
|
backdrop: 'static'
|
||||||
|
container: @container
|
||||||
|
).on(
|
||||||
|
'hidden.bs.modal': @localOnClosed
|
||||||
|
)
|
||||||
|
|
||||||
|
render: ->
|
||||||
|
@html App.view('generic/modal_loader')(
|
||||||
|
head: @head
|
||||||
|
message: App.i18n.translateContent(@message)
|
||||||
|
)
|
||||||
|
|
||||||
|
update: (message, translate = true) =>
|
||||||
|
if translate
|
||||||
|
message = App.i18n.translateContent(message)
|
||||||
|
@$('.js-loading').html(message)
|
||||||
|
|
||||||
|
hideIcon: =>
|
||||||
|
@$('.js-loadingIcon').addClass('hide')
|
||||||
|
|
||||||
|
showIcon: =>
|
||||||
|
@$('.js-loadingIcon').removeClass('hide')
|
||||||
|
|
||||||
|
localOnClosed: =>
|
||||||
|
@el.remove()
|
||||||
|
|
||||||
|
hide: (delay) =>
|
||||||
|
remove = =>
|
||||||
|
@el.modal('hide')
|
||||||
|
if !delay
|
||||||
|
remove()
|
||||||
|
return
|
||||||
|
App.Delay.set(remove, delay * 1000)
|
|
@ -0,0 +1,135 @@
|
||||||
|
class App.ControllerNavSidbar extends App.Controller
|
||||||
|
constructor: (params) ->
|
||||||
|
super
|
||||||
|
|
||||||
|
if @authenticateRequired
|
||||||
|
@authenticateCheckRedirect()
|
||||||
|
|
||||||
|
@render(true)
|
||||||
|
|
||||||
|
@controllerBind('ui:rerender',
|
||||||
|
=>
|
||||||
|
@render(true)
|
||||||
|
@updateNavigation(true, params)
|
||||||
|
)
|
||||||
|
|
||||||
|
show: (params = {}) =>
|
||||||
|
@navupdate ''
|
||||||
|
@shown = true
|
||||||
|
if params
|
||||||
|
for key, value of params
|
||||||
|
if key isnt 'el' && key isnt 'shown' && key isnt 'match'
|
||||||
|
@[key] = value
|
||||||
|
@updateNavigation(false, params)
|
||||||
|
if @activeController && _.isFunction(@activeController.show)
|
||||||
|
@activeController.show(params)
|
||||||
|
|
||||||
|
hide: =>
|
||||||
|
@shown = false
|
||||||
|
if @activeController && _.isFunction(@activeController.hide)
|
||||||
|
@activeController.hide()
|
||||||
|
|
||||||
|
render: (force = false) =>
|
||||||
|
groups = @groupsSorted()
|
||||||
|
selectedItem = @selectedItem(groups)
|
||||||
|
|
||||||
|
@html App.view('generic/navbar_level2/index')(
|
||||||
|
className: @configKey
|
||||||
|
)
|
||||||
|
@$('.sidebar').html App.view('generic/navbar_level2/navbar')(
|
||||||
|
groups: groups
|
||||||
|
className: @configKey
|
||||||
|
selectedItem: selectedItem
|
||||||
|
)
|
||||||
|
|
||||||
|
updateNavigation: (force, params) =>
|
||||||
|
groups = @groupsSorted()
|
||||||
|
selectedItem = @selectedItem(groups)
|
||||||
|
return if !selectedItem
|
||||||
|
return if !force && @lastTarget && selectedItem.target is @lastTarget
|
||||||
|
@lastTarget = selectedItem.target
|
||||||
|
@$('.sidebar li').removeClass('active')
|
||||||
|
@$(".sidebar li a[href=\"#{selectedItem.target}\"]").parent().addClass('active')
|
||||||
|
|
||||||
|
@executeController(selectedItem, params)
|
||||||
|
|
||||||
|
groupsSorted: =>
|
||||||
|
|
||||||
|
# get accessable groups
|
||||||
|
groups = App.Config.get(@configKey)
|
||||||
|
groupsUnsorted = []
|
||||||
|
for key, item of groups
|
||||||
|
if !item.controller
|
||||||
|
if !item.permission
|
||||||
|
groupsUnsorted.push item
|
||||||
|
else
|
||||||
|
match = false
|
||||||
|
for permissionName in item.permission
|
||||||
|
if !match && @permissionCheck(permissionName)
|
||||||
|
match = true
|
||||||
|
groupsUnsorted.push item
|
||||||
|
_.sortBy(groupsUnsorted, (item) -> return item.prio)
|
||||||
|
|
||||||
|
selectedItem: (groups) =>
|
||||||
|
|
||||||
|
# get items of group
|
||||||
|
for group in groups
|
||||||
|
items = App.Config.get(@configKey)
|
||||||
|
itemsUnsorted = []
|
||||||
|
for key, item of items
|
||||||
|
if item.parent is group.target
|
||||||
|
if item.controller
|
||||||
|
if !item.permission
|
||||||
|
itemsUnsorted.push item
|
||||||
|
else
|
||||||
|
match = false
|
||||||
|
for permissionName in item.permission
|
||||||
|
if !match && @permissionCheck(permissionName)
|
||||||
|
match = true
|
||||||
|
itemsUnsorted.push item
|
||||||
|
|
||||||
|
group.items = _.sortBy(itemsUnsorted, (item) -> return item.prio)
|
||||||
|
|
||||||
|
# set active item
|
||||||
|
selectedItem = undefined
|
||||||
|
for group in groups
|
||||||
|
if group.items
|
||||||
|
for item in group.items
|
||||||
|
if item.target.match("/#{@target}$")
|
||||||
|
item.active = true
|
||||||
|
selectedItem = item
|
||||||
|
else
|
||||||
|
item.active = false
|
||||||
|
|
||||||
|
if !selectedItem
|
||||||
|
for group in groups
|
||||||
|
break if selectedItem
|
||||||
|
if group.items
|
||||||
|
for item in group.items
|
||||||
|
item.active = true
|
||||||
|
selectedItem = item
|
||||||
|
break
|
||||||
|
|
||||||
|
selectedItem
|
||||||
|
|
||||||
|
executeController: (selectedItem, params) =>
|
||||||
|
|
||||||
|
if @activeController
|
||||||
|
@activeController.el.remove()
|
||||||
|
@activeController = undefined
|
||||||
|
|
||||||
|
@$('.main').append('<div>')
|
||||||
|
@activeController = new selectedItem.controller(_.extend(params, el: @$('.main div')))
|
||||||
|
|
||||||
|
setPosition: (position) =>
|
||||||
|
return if @shown
|
||||||
|
return if !position
|
||||||
|
if position.main
|
||||||
|
@$('.main').scrollTop(position.main)
|
||||||
|
if position.sidebar
|
||||||
|
@$('.sidebar').scrollTop(position.sidebar)
|
||||||
|
|
||||||
|
currentPosition: =>
|
||||||
|
data =
|
||||||
|
main: @$('.main').scrollTop()
|
||||||
|
sidebar: @$('.sidebar').scrollTop()
|
|
@ -0,0 +1,82 @@
|
||||||
|
class App.ControllerObserver extends App.Controller
|
||||||
|
model: 'Ticket'
|
||||||
|
template: 'tba'
|
||||||
|
globalRerender: true
|
||||||
|
|
||||||
|
###
|
||||||
|
observe:
|
||||||
|
title: true
|
||||||
|
|
||||||
|
observeNot:
|
||||||
|
title: true
|
||||||
|
|
||||||
|
###
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
#console.trace()
|
||||||
|
@log 'debug', 'new', @object_id, @model
|
||||||
|
|
||||||
|
if App[@model].exists(@object_id)
|
||||||
|
@maybeRender(App[@model].fullLocal(@object_id))
|
||||||
|
else
|
||||||
|
App[@model].full(@object_id, @maybeRender)
|
||||||
|
|
||||||
|
# rerender, e. g. on language change
|
||||||
|
if @globalRerender
|
||||||
|
@controllerBind('ui:rerender', =>
|
||||||
|
@lastAttributres = undefined
|
||||||
|
@maybeRender(App[@model].fullLocal(@object_id))
|
||||||
|
)
|
||||||
|
|
||||||
|
subscribe: (object, typeOfChange) =>
|
||||||
|
@maybeRender(object, typeOfChange)
|
||||||
|
|
||||||
|
maybeRender: (object, typeOfChange) =>
|
||||||
|
if typeOfChange is 'remove'
|
||||||
|
@release()
|
||||||
|
@el.remove()
|
||||||
|
return
|
||||||
|
|
||||||
|
@log 'debug', 'maybeRender', @object_id, object, @model
|
||||||
|
|
||||||
|
if !@subscribeId
|
||||||
|
@subscribeId = object.subscribe(@subscribe)
|
||||||
|
|
||||||
|
# remember current attributes
|
||||||
|
currentAttributes = {}
|
||||||
|
if @observe
|
||||||
|
for key, active of @observe
|
||||||
|
if active
|
||||||
|
currentAttributes[key] = object[key]
|
||||||
|
if @observeNot
|
||||||
|
for key, value of object
|
||||||
|
if key isnt 'cid' && !@observeNot[key] && !_.isFunction(value) && !_.isObject(value)
|
||||||
|
currentAttributes[key] = value
|
||||||
|
|
||||||
|
if !@lastAttributres
|
||||||
|
@lastAttributres = {}
|
||||||
|
else
|
||||||
|
diff = difference(currentAttributes, @lastAttributres)
|
||||||
|
if _.isEmpty(diff)
|
||||||
|
@log 'debug', 'maybeRender no diff, no rerender'
|
||||||
|
return
|
||||||
|
|
||||||
|
@log 'debug', 'maybeRender.diff', diff, @observe, @model
|
||||||
|
@lastAttributres = currentAttributes
|
||||||
|
|
||||||
|
@render(object, diff)
|
||||||
|
|
||||||
|
render: (object, diff) =>
|
||||||
|
@log 'debug', 'render', @template, object, diff
|
||||||
|
@html App.view(@template)(
|
||||||
|
object: object
|
||||||
|
)
|
||||||
|
|
||||||
|
if @renderPost
|
||||||
|
@renderPost(object)
|
||||||
|
|
||||||
|
release: =>
|
||||||
|
#console.trace()
|
||||||
|
@log 'debug', 'release', @object_id, @model, @subscribeId
|
||||||
|
App[@model].unsubscribe(@subscribeId)
|
|
@ -0,0 +1,20 @@
|
||||||
|
class App.ControllerObserverActionRow extends App.ControllerObserver
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
|
||||||
|
render: (object) =>
|
||||||
|
return if _.isEmpty(object)
|
||||||
|
actions = @actions(object)
|
||||||
|
@html App.view('generic/actions')(
|
||||||
|
items: actions
|
||||||
|
type: @type
|
||||||
|
)
|
||||||
|
|
||||||
|
for item in actions
|
||||||
|
do (item) =>
|
||||||
|
@$("[data-type=\"#{item.name}\"]").on(
|
||||||
|
'click'
|
||||||
|
(e) ->
|
||||||
|
e.preventDefault()
|
||||||
|
item.callback(object)
|
||||||
|
)
|
|
@ -0,0 +1,5 @@
|
||||||
|
class App.ControllerPermanent extends App.Controller
|
||||||
|
constructor: ->
|
||||||
|
if @requiredPermission
|
||||||
|
@permissionCheckRedirect(@requiredPermission, true)
|
||||||
|
super
|
|
@ -0,0 +1,16 @@
|
||||||
|
class App.ControllerSubContent extends App.Controller
|
||||||
|
constructor: ->
|
||||||
|
if @requiredPermission
|
||||||
|
@permissionCheckRedirect(@requiredPermission)
|
||||||
|
|
||||||
|
super
|
||||||
|
|
||||||
|
show: =>
|
||||||
|
if @genericController && @genericController.show
|
||||||
|
@genericController.show()
|
||||||
|
return if !@header
|
||||||
|
@title @header, true
|
||||||
|
|
||||||
|
hide: =>
|
||||||
|
if @genericController && @genericController.hide
|
||||||
|
@genericController.hide()
|
|
@ -0,0 +1,61 @@
|
||||||
|
class App.ControllerTabs extends App.Controller
|
||||||
|
events:
|
||||||
|
'click .nav-tabs [data-toggle="tab"]': 'tabRemember'
|
||||||
|
|
||||||
|
constructor: (params) ->
|
||||||
|
@originParams = params # remember params for sub-controller
|
||||||
|
super(params)
|
||||||
|
|
||||||
|
# check authentication
|
||||||
|
if @requiredPermission
|
||||||
|
if !@permissionCheckRedirect(@requiredPermission)
|
||||||
|
throw "No permission for #{@requiredPermission}"
|
||||||
|
|
||||||
|
show: =>
|
||||||
|
return if !@controllerList
|
||||||
|
for localeController in @controllerList
|
||||||
|
if localeController && localeController.show
|
||||||
|
localeController.show()
|
||||||
|
|
||||||
|
hide: =>
|
||||||
|
return if !@controllerList
|
||||||
|
for localeController in @controllerList
|
||||||
|
if localeController && localeController.hide
|
||||||
|
localeController.hide()
|
||||||
|
|
||||||
|
render: ->
|
||||||
|
@html App.view('generic/tabs')(
|
||||||
|
header: @header
|
||||||
|
subHeader: @subHeader
|
||||||
|
tabs: @tabs
|
||||||
|
addTab: @addTab
|
||||||
|
headerSwitchName: @headerSwitchName
|
||||||
|
headerSwitchChecked: @headerSwitchChecked
|
||||||
|
)
|
||||||
|
|
||||||
|
# insert content
|
||||||
|
for tab in @tabs
|
||||||
|
@$('.tab-content').append("<div class=\"tab-pane\" id=\"#{tab.target}\"></div>")
|
||||||
|
if tab.controller
|
||||||
|
params = tab.params || {}
|
||||||
|
params.name = tab.name
|
||||||
|
params.target = tab.target
|
||||||
|
params.el = @$("##{tab.target}")
|
||||||
|
@controllerList ||= []
|
||||||
|
@controllerList.push new tab.controller(_.extend(@originParams, params))
|
||||||
|
|
||||||
|
# check if tabs need to be show / cant' use .tab(), because tabs are note shown (only one tab exists)
|
||||||
|
if @tabs.length <= 1
|
||||||
|
@$('.tab-pane').addClass('active')
|
||||||
|
return
|
||||||
|
|
||||||
|
# set last or first tab to active
|
||||||
|
@lastActiveTab = @Config.get('lastTab')
|
||||||
|
if @lastActiveTab && @$(".nav-tabs li a[href='#{@lastActiveTab}']")[0]
|
||||||
|
@$(".nav-tabs li a[href='#{@lastActiveTab}']").tab('show')
|
||||||
|
else
|
||||||
|
@$('.nav-tabs li:first a').tab('show')
|
||||||
|
|
||||||
|
tabRemember: (e) =>
|
||||||
|
@lastActiveTab = $(e.target).attr('href')
|
||||||
|
@Config.set('lastTab', @lastActiveTab)
|
|
@ -0,0 +1,52 @@
|
||||||
|
class App.ControllerWizardModal extends App.ControllerFullPage
|
||||||
|
className: 'modal fade'
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
|
||||||
|
# rerender view, e. g. on langauge change
|
||||||
|
@controllerBind('ui:rerender', =>
|
||||||
|
@render()
|
||||||
|
'wizard'
|
||||||
|
)
|
||||||
|
|
||||||
|
goToSlide: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
slide = $(e.target).data('slide')
|
||||||
|
return if !slide
|
||||||
|
@showSlide(slide)
|
||||||
|
|
||||||
|
showSlide: (name) =>
|
||||||
|
@hideAlert(name)
|
||||||
|
@$('.setup.wizard').addClass('hide')
|
||||||
|
@$(".setup.wizard.#{name}").removeClass('hide')
|
||||||
|
@$(".setup.wizard.#{name} input, .setup.wizard.#{name} select").first().focus()
|
||||||
|
|
||||||
|
showAlert: (screen, message) =>
|
||||||
|
@$(".#{screen}").find('.alert').first().removeClass('hide').text(App.i18n.translatePlain(message))
|
||||||
|
|
||||||
|
hideAlert: (screen) =>
|
||||||
|
@$(".#{screen}").find('.alert').first().addClass('hide')
|
||||||
|
|
||||||
|
disable: (e) =>
|
||||||
|
@formDisable(e)
|
||||||
|
@$('.wizard-controls .btn').attr('disabled', true)
|
||||||
|
|
||||||
|
enable: (e) =>
|
||||||
|
@formEnable(e)
|
||||||
|
@$('.wizard-controls .btn').attr('disabled', false)
|
||||||
|
|
||||||
|
hide: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
@el.modal('hide')
|
||||||
|
|
||||||
|
showInvalidField: (screen, fields) =>
|
||||||
|
@$(".#{screen}").find('.form-group').removeClass('has-error')
|
||||||
|
return if !fields
|
||||||
|
for field, type of fields
|
||||||
|
if type
|
||||||
|
@$(".#{screen}").find("[name=\"options::#{field}\"]").closest('.form-group').addClass('has-error')
|
||||||
|
|
||||||
|
render: ->
|
||||||
|
# do nothing
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
class App.ControllerWizardFullScreen extends App.ControllerWizardModal
|
||||||
|
forceRender: true
|
||||||
|
className: 'getstarted'
|
||||||
|
|
||||||
|
# login check / get session user
|
||||||
|
redirectToLogin: =>
|
||||||
|
App.Auth.loginCheck()
|
||||||
|
@el.remove()
|
||||||
|
App.Plugin.init()
|
||||||
|
@navigate '#', { removeEl: true }
|
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,4 @@
|
||||||
class App.ChannelChat extends App.ControllerSubContent
|
class ChannelChat extends App.ControllerSubContent
|
||||||
requiredPermission: 'admin.channel_chat'
|
requiredPermission: 'admin.channel_chat'
|
||||||
header: 'Chat'
|
header: 'Chat'
|
||||||
events:
|
events:
|
||||||
|
@ -353,7 +353,7 @@ class App.ChannelChat extends App.ControllerSubContent
|
||||||
@code.each (i, block) ->
|
@code.each (i, block) ->
|
||||||
hljs.highlightBlock block
|
hljs.highlightBlock block
|
||||||
|
|
||||||
App.Config.set('Chat', { prio: 4000, name: 'Chat', parent: '#channels', target: '#channels/chat', controller: App.ChannelChat, permission: ['admin.channel_chat'] }, 'NavBarAdmin')
|
App.Config.set('Chat', { prio: 4000, name: 'Chat', parent: '#channels', target: '#channels/chat', controller: ChannelChat, permission: ['admin.channel_chat'] }, 'NavBarAdmin')
|
||||||
|
|
||||||
class Topics extends App.Controller
|
class Topics extends App.Controller
|
||||||
events:
|
events:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class App.ChannelEmail extends App.ControllerTabs
|
class ChannelEmail extends App.ControllerTabs
|
||||||
requiredPermission: 'admin.channel_email'
|
requiredPermission: 'admin.channel_email'
|
||||||
header: 'Email'
|
header: 'Email'
|
||||||
constructor: ->
|
constructor: ->
|
||||||
|
@ -10,17 +10,17 @@ class App.ChannelEmail extends App.ControllerTabs
|
||||||
{
|
{
|
||||||
name: 'Accounts',
|
name: 'Accounts',
|
||||||
target: 'c-account',
|
target: 'c-account',
|
||||||
controller: App.ChannelEmailAccountOverview,
|
controller: ChannelEmailAccountOverview,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Filter',
|
name: 'Filter',
|
||||||
target: 'c-filter',
|
target: 'c-filter',
|
||||||
controller: App.ChannelEmailFilter,
|
controller: ChannelEmailFilter,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Signatures',
|
name: 'Signatures',
|
||||||
target: 'c-signature',
|
target: 'c-signature',
|
||||||
controller: App.ChannelEmailSignature,
|
controller: ChannelEmailSignature,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Settings',
|
name: 'Settings',
|
||||||
|
@ -32,7 +32,7 @@ class App.ChannelEmail extends App.ControllerTabs
|
||||||
|
|
||||||
@render()
|
@render()
|
||||||
|
|
||||||
class App.ChannelEmailFilter extends App.Controller
|
class ChannelEmailFilter extends App.Controller
|
||||||
events:
|
events:
|
||||||
'click [data-type=new]': 'new'
|
'click [data-type=new]': 'new'
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ class App.ChannelEmailFilter extends App.Controller
|
||||||
callback: @load
|
callback: @load
|
||||||
)
|
)
|
||||||
|
|
||||||
class App.ChannelEmailSignature extends App.Controller
|
class ChannelEmailSignature extends App.Controller
|
||||||
events:
|
events:
|
||||||
'click [data-type=new]': 'new'
|
'click [data-type=new]': 'new'
|
||||||
|
|
||||||
|
@ -111,19 +111,19 @@ Once you have created a signature here, you need also to edit the groups where y
|
||||||
|
|
||||||
new: (e) =>
|
new: (e) =>
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
new App.ChannelEmailSignatureEdit(
|
new ChannelEmailSignatureEdit(
|
||||||
container: @el.closest('.content')
|
container: @el.closest('.content')
|
||||||
)
|
)
|
||||||
|
|
||||||
edit: (id, e) =>
|
edit: (id, e) =>
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
item = App.Signature.find(id)
|
item = App.Signature.find(id)
|
||||||
new App.ChannelEmailSignatureEdit(
|
new ChannelEmailSignatureEdit(
|
||||||
object: item
|
object: item
|
||||||
container: @el.closest('.content')
|
container: @el.closest('.content')
|
||||||
)
|
)
|
||||||
|
|
||||||
class App.ChannelEmailSignatureEdit extends App.ControllerModal
|
class ChannelEmailSignatureEdit extends App.ControllerModal
|
||||||
buttonClose: true
|
buttonClose: true
|
||||||
buttonCancel: true
|
buttonCancel: true
|
||||||
buttonSubmit: true
|
buttonSubmit: true
|
||||||
|
@ -174,7 +174,7 @@ class App.ChannelEmailSignatureEdit extends App.ControllerModal
|
||||||
@form.showAlert(details.error_human || details.error || 'Unable to create object!')
|
@form.showAlert(details.error_human || details.error || 'Unable to create object!')
|
||||||
)
|
)
|
||||||
|
|
||||||
class App.ChannelEmailAccountOverview extends App.Controller
|
class ChannelEmailAccountOverview extends App.Controller
|
||||||
events:
|
events:
|
||||||
'click .js-channelNew': 'wizard'
|
'click .js-channelNew': 'wizard'
|
||||||
'click .js-channelDelete': 'delete'
|
'click .js-channelDelete': 'delete'
|
||||||
|
@ -248,7 +248,7 @@ class App.ChannelEmailAccountOverview extends App.Controller
|
||||||
|
|
||||||
wizard: (e) =>
|
wizard: (e) =>
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
new App.ChannelEmailAccountWizard(
|
new ChannelEmailAccountWizard(
|
||||||
container: @el.closest('.content')
|
container: @el.closest('.content')
|
||||||
callback: @load
|
callback: @load
|
||||||
channelDriver: @channelDriver
|
channelDriver: @channelDriver
|
||||||
|
@ -259,7 +259,7 @@ class App.ChannelEmailAccountOverview extends App.Controller
|
||||||
id = $(e.target).closest('.action').data('id')
|
id = $(e.target).closest('.action').data('id')
|
||||||
channel = App.Channel.find(id)
|
channel = App.Channel.find(id)
|
||||||
slide = 'js-inbound'
|
slide = 'js-inbound'
|
||||||
new App.ChannelEmailAccountWizard(
|
new ChannelEmailAccountWizard(
|
||||||
container: @el.closest('.content')
|
container: @el.closest('.content')
|
||||||
slide: slide
|
slide: slide
|
||||||
channel: channel
|
channel: channel
|
||||||
|
@ -272,7 +272,7 @@ class App.ChannelEmailAccountOverview extends App.Controller
|
||||||
id = $(e.target).closest('.action').data('id')
|
id = $(e.target).closest('.action').data('id')
|
||||||
channel = App.Channel.find(id)
|
channel = App.Channel.find(id)
|
||||||
slide = 'js-outbound'
|
slide = 'js-outbound'
|
||||||
new App.ChannelEmailAccountWizard(
|
new ChannelEmailAccountWizard(
|
||||||
container: @el.closest('.content')
|
container: @el.closest('.content')
|
||||||
slide: slide
|
slide: slide
|
||||||
channel: channel
|
channel: channel
|
||||||
|
@ -328,7 +328,7 @@ class App.ChannelEmailAccountOverview extends App.Controller
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
id = $(e.target).closest('.action').data('id')
|
id = $(e.target).closest('.action').data('id')
|
||||||
item = App.Channel.find(id)
|
item = App.Channel.find(id)
|
||||||
new App.ChannelEmailEdit(
|
new ChannelEmailEdit(
|
||||||
container: @el.closest('.content')
|
container: @el.closest('.content')
|
||||||
item: item
|
item: item
|
||||||
callback: @load
|
callback: @load
|
||||||
|
@ -374,7 +374,7 @@ class App.ChannelEmailAccountOverview extends App.Controller
|
||||||
id = $(e.target).closest('.action').data('id')
|
id = $(e.target).closest('.action').data('id')
|
||||||
channel = App.Channel.find(id)
|
channel = App.Channel.find(id)
|
||||||
slide = 'js-outbound'
|
slide = 'js-outbound'
|
||||||
new App.ChannelEmailNotificationWizard(
|
new ChannelEmailNotificationWizard(
|
||||||
container: @el.closest('.content')
|
container: @el.closest('.content')
|
||||||
channel: channel
|
channel: channel
|
||||||
callback: @load
|
callback: @load
|
||||||
|
@ -391,7 +391,8 @@ class App.ChannelEmailAccountOverview extends App.Controller
|
||||||
id = $(e.target).closest('.action').data('id')
|
id = $(e.target).closest('.action').data('id')
|
||||||
@navigate "#channels/microsoft365/#{id}"
|
@navigate "#channels/microsoft365/#{id}"
|
||||||
|
|
||||||
class App.ChannelEmailEdit extends App.ControllerModal
|
|
||||||
|
class ChannelEmailEdit extends App.ControllerModal
|
||||||
buttonClose: true
|
buttonClose: true
|
||||||
buttonCancel: true
|
buttonCancel: true
|
||||||
buttonSubmit: true
|
buttonSubmit: true
|
||||||
|
@ -442,7 +443,7 @@ class App.ChannelEmailEdit extends App.ControllerModal
|
||||||
@el.find('.alert').removeClass('hidden').text(data.error || 'Unable to save changes.')
|
@el.find('.alert').removeClass('hidden').text(data.error || 'Unable to save changes.')
|
||||||
)
|
)
|
||||||
|
|
||||||
class App.ChannelEmailAccountWizard extends App.WizardModal
|
class ChannelEmailAccountWizard extends App.ControllerWizardModal
|
||||||
elements:
|
elements:
|
||||||
'.modal-body': 'body'
|
'.modal-body': 'body'
|
||||||
events:
|
events:
|
||||||
|
@ -896,7 +897,7 @@ class App.ChannelEmailAccountWizard extends App.WizardModal
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
@el.modal('hide')
|
@el.modal('hide')
|
||||||
|
|
||||||
class App.ChannelEmailNotificationWizard extends App.WizardModal
|
class ChannelEmailNotificationWizard extends App.ControllerWizardModal
|
||||||
elements:
|
elements:
|
||||||
'.modal-body': 'body'
|
'.modal-body': 'body'
|
||||||
events:
|
events:
|
||||||
|
@ -1030,4 +1031,4 @@ class App.ChannelEmailNotificationWizard extends App.WizardModal
|
||||||
@enable(e)
|
@enable(e)
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Config.set('Email', { prio: 3000, name: 'Email', parent: '#channels', target: '#channels/email', controller: App.ChannelEmail, permission: ['admin.channel_email'] }, 'NavBarAdmin')
|
App.Config.set('Email', { prio: 3000, name: 'Email', parent: '#channels', target: '#channels/email', controller: ChannelEmail, permission: ['admin.channel_email'] }, 'NavBarAdmin')
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerSubContent
|
class ChannelFacebook extends App.ControllerSubContent
|
||||||
requiredPermission: 'admin.channel_facebook'
|
requiredPermission: 'admin.channel_facebook'
|
||||||
header: 'Facebook'
|
header: 'Facebook'
|
||||||
events:
|
events:
|
||||||
|
@ -254,4 +254,4 @@ class AccountEdit extends App.ControllerModal
|
||||||
@el.find('.alert').removeClass('hidden').text(data.error || 'Unable to save changes.')
|
@el.find('.alert').removeClass('hidden').text(data.error || 'Unable to save changes.')
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Config.set('Facebook', { prio: 5100, name: 'Facebook', parent: '#channels', target: '#channels/facebook', controller: Index, permission: ['admin.channel_facebook'] }, 'NavBarAdmin')
|
App.Config.set('Facebook', { prio: 5100, name: 'Facebook', parent: '#channels', target: '#channels/facebook', controller: ChannelFacebook, permission: ['admin.channel_facebook'] }, 'NavBarAdmin')
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# coffeelint: disable=no_unnecessary_double_quotes
|
# coffeelint: disable=no_unnecessary_double_quotes
|
||||||
class App.ChannelForm extends App.ControllerSubContent
|
class ChannelForm extends App.ControllerSubContent
|
||||||
requiredPermission: 'admin.channel_formular'
|
requiredPermission: 'admin.channel_formular'
|
||||||
header: 'Form'
|
header: 'Form'
|
||||||
events:
|
events:
|
||||||
|
@ -88,4 +88,4 @@ class App.ChannelForm extends App.ControllerSubContent
|
||||||
value = @paramsSetting.find('[name=group_id]').val()
|
value = @paramsSetting.find('[name=group_id]').val()
|
||||||
App.Setting.set('form_ticket_create_group_id', value)
|
App.Setting.set('form_ticket_create_group_id', value)
|
||||||
|
|
||||||
App.Config.set('Form', { prio: 2000, name: 'Form', parent: '#channels', target: '#channels/form', controller: App.ChannelForm, permission: ['admin.formular'] }, 'NavBarAdmin')
|
App.Config.set('Form', { prio: 2000, name: 'Form', parent: '#channels', target: '#channels/form', controller: ChannelForm, permission: ['admin.formular'] }, 'NavBarAdmin')
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class App.ChannelSms extends App.ControllerTabs
|
class ChannelSms extends App.ControllerTabs
|
||||||
requiredPermission: 'admin.channel_sms'
|
requiredPermission: 'admin.channel_sms'
|
||||||
header: 'SMS'
|
header: 'SMS'
|
||||||
constructor: ->
|
constructor: ->
|
||||||
|
@ -9,13 +9,13 @@ class App.ChannelSms extends App.ControllerTabs
|
||||||
{
|
{
|
||||||
name: 'Accounts',
|
name: 'Accounts',
|
||||||
target: 'c-account',
|
target: 'c-account',
|
||||||
controller: App.ChannelSmsAccountOverview,
|
controller: ChannelSmsAccountOverview,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@render()
|
@render()
|
||||||
|
|
||||||
class App.ChannelSmsAccountOverview extends App.Controller
|
class ChannelSmsAccountOverview extends App.Controller
|
||||||
events:
|
events:
|
||||||
'click .js-channelEdit': 'change'
|
'click .js-channelEdit': 'change'
|
||||||
'click .js-channelDelete': 'delete'
|
'click .js-channelDelete': 'delete'
|
||||||
|
@ -76,7 +76,7 @@ class App.ChannelSmsAccountOverview extends App.Controller
|
||||||
channel = new App.Channel(active: true)
|
channel = new App.Channel(active: true)
|
||||||
else
|
else
|
||||||
channel = App.Channel.find(id)
|
channel = App.Channel.find(id)
|
||||||
new App.ChannelSmsAccount(
|
new ChannelSmsAccount(
|
||||||
container: @el.closest('.content')
|
container: @el.closest('.content')
|
||||||
channel: channel
|
channel: channel
|
||||||
callback: @load
|
callback: @load
|
||||||
|
@ -127,7 +127,7 @@ class App.ChannelSmsAccountOverview extends App.Controller
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
id = $(e.target).closest('.action').data('id')
|
id = $(e.target).closest('.action').data('id')
|
||||||
channel = App.Channel.find(id)
|
channel = App.Channel.find(id)
|
||||||
new App.ChannelSmsNotification(
|
new ChannelSmsNotification(
|
||||||
container: @el.closest('.content')
|
container: @el.closest('.content')
|
||||||
channel: channel
|
channel: channel
|
||||||
callback: @load
|
callback: @load
|
||||||
|
@ -135,7 +135,7 @@ class App.ChannelSmsAccountOverview extends App.Controller
|
||||||
config: @config
|
config: @config
|
||||||
)
|
)
|
||||||
|
|
||||||
class App.ChannelSmsAccount extends App.ControllerModal
|
class ChannelSmsAccount extends App.ControllerModal
|
||||||
head: 'SMS Account'
|
head: 'SMS Account'
|
||||||
buttonCancel: true
|
buttonCancel: true
|
||||||
centerButtons: [
|
centerButtons: [
|
||||||
|
@ -272,7 +272,7 @@ class App.ChannelSmsAccount extends App.ControllerModal
|
||||||
container: @el.closest('.content')
|
container: @el.closest('.content')
|
||||||
)
|
)
|
||||||
|
|
||||||
class App.ChannelSmsNotification extends App.ControllerModal
|
class ChannelSmsNotification extends App.ControllerModal
|
||||||
head: 'SMS Notification'
|
head: 'SMS Notification'
|
||||||
buttonCancel: true
|
buttonCancel: true
|
||||||
centerButtons: [
|
centerButtons: [
|
||||||
|
@ -439,4 +439,4 @@ class TestModal extends App.ControllerModal
|
||||||
.removeClass('hide')
|
.removeClass('hide')
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Config.set('SMS', { prio: 3100, name: 'SMS', parent: '#channels', target: '#channels/sms', controller: App.ChannelSms, permission: ['admin.channel_sms'] }, 'NavBarAdmin')
|
App.Config.set('SMS', { prio: 3100, name: 'SMS', parent: '#channels', target: '#channels/sms', controller: ChannelSms, permission: ['admin.channel_sms'] }, 'NavBarAdmin')
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerSubContent
|
class ChannelTelegram extends App.ControllerSubContent
|
||||||
requiredPermission: 'admin.channel_telegram'
|
requiredPermission: 'admin.channel_telegram'
|
||||||
events:
|
events:
|
||||||
'click .js-new': 'new'
|
'click .js-new': 'new'
|
||||||
|
@ -201,4 +201,4 @@ class BotEdit extends App.ControllerModal
|
||||||
@el.find('.alert').removeClass('hidden').text(error_message)
|
@el.find('.alert').removeClass('hidden').text(error_message)
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Config.set('Telegram', { prio: 5100, name: 'Telegram', parent: '#channels', target: '#channels/telegram', controller: Index, permission: ['admin.channel_telegram'] }, 'NavBarAdmin')
|
App.Config.set('Telegram', { prio: 5100, name: 'Telegram', parent: '#channels', target: '#channels/telegram', controller: ChannelTelegram, permission: ['admin.channel_telegram'] }, 'NavBarAdmin')
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerSubContent
|
class ChannelTwitter extends App.ControllerSubContent
|
||||||
requiredPermission: 'admin.channel_twitter'
|
requiredPermission: 'admin.channel_twitter'
|
||||||
events:
|
events:
|
||||||
'click .js-new': 'new'
|
'click .js-new': 'new'
|
||||||
|
@ -299,4 +299,4 @@ class AccountEdit extends App.ControllerModal
|
||||||
@el.find('.alert').removeClass('hidden').text(data.error || 'Unable to save changes.')
|
@el.find('.alert').removeClass('hidden').text(data.error || 'Unable to save changes.')
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Config.set('Twitter', { prio: 5000, name: 'Twitter', parent: '#channels', target: '#channels/twitter', controller: Index, permission: ['admin.channel_twitter'] }, 'NavBarAdmin')
|
App.Config.set('Twitter', { prio: 5000, name: 'Twitter', parent: '#channels', target: '#channels/twitter', controller: ChannelTwitter, permission: ['admin.channel_twitter'] }, 'NavBarAdmin')
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class App.ChannelWeb extends App.ControllerTabs
|
class ChannelWeb extends App.ControllerTabs
|
||||||
requiredPermission: 'admin.channel_web'
|
requiredPermission: 'admin.channel_web'
|
||||||
header: 'Web'
|
header: 'Web'
|
||||||
constructor: ->
|
constructor: ->
|
||||||
|
@ -16,4 +16,4 @@ class App.ChannelWeb extends App.ControllerTabs
|
||||||
|
|
||||||
@render()
|
@render()
|
||||||
|
|
||||||
App.Config.set('Web', { prio: 1000, name: 'Web', parent: '#channels', target: '#channels/web', controller: App.ChannelWeb, permission: ['admin.channel_web'] }, 'NavBarAdmin')
|
App.Config.set('Web', { prio: 1000, name: 'Web', parent: '#channels', target: '#channels/web', controller: ChannelWeb, permission: ['admin.channel_web'] }, 'NavBarAdmin')
|
||||||
|
|
|
@ -13,7 +13,7 @@ class App.DashboardActivityStream extends App.CollectionController
|
||||||
@fetch()
|
@fetch()
|
||||||
|
|
||||||
# bind to rebuild view event
|
# bind to rebuild view event
|
||||||
@bind('activity_stream_rebuild', @load)
|
@controllerBind('activity_stream_rebuild', @load)
|
||||||
|
|
||||||
fetch: =>
|
fetch: =>
|
||||||
|
|
||||||
|
|
|
@ -54,8 +54,9 @@ class App.FirstStepsClues extends App.Controller
|
||||||
|
|
||||||
constructor: (params) ->
|
constructor: (params) ->
|
||||||
|
|
||||||
$('#app').append('<div class="js-modal--clue"></div>')
|
el = $('<div class="js-modal--clue"></div>')
|
||||||
params.el = $('#app .js-modal--clue')
|
params.appEl.append(el)
|
||||||
|
params.el = el
|
||||||
|
|
||||||
super params
|
super params
|
||||||
|
|
||||||
|
@ -69,7 +70,7 @@ class App.FirstStepsClues extends App.Controller
|
||||||
@position = 0
|
@position = 0
|
||||||
@render()
|
@render()
|
||||||
|
|
||||||
@bind('ui:rerender', =>
|
@controllerBind('ui:rerender', =>
|
||||||
@render()
|
@render()
|
||||||
'clues'
|
'clues'
|
||||||
)
|
)
|
||||||
|
@ -106,7 +107,7 @@ class App.FirstStepsClues extends App.Controller
|
||||||
cleanUp: (callback) ->
|
cleanUp: (callback) ->
|
||||||
@hideWindow =>
|
@hideWindow =>
|
||||||
clue = @clues[@position]
|
clue = @clues[@position]
|
||||||
container = $("#app #{clue.container}")
|
container = @appEl.find(clue.container)
|
||||||
container.removeClass('selected-clue')
|
container.removeClass('selected-clue')
|
||||||
|
|
||||||
# undo click perform by doing it again
|
# undo click perform by doing it again
|
||||||
|
@ -128,7 +129,7 @@ class App.FirstStepsClues extends App.Controller
|
||||||
|
|
||||||
showClue: =>
|
showClue: =>
|
||||||
clue = @clues[@position]
|
clue = @clues[@position]
|
||||||
container = $("#app #{clue.container}")
|
container = @appEl.find(clue.container)
|
||||||
container.addClass('selected-clue')
|
container.addClass('selected-clue')
|
||||||
|
|
||||||
if clue.actions
|
if clue.actions
|
||||||
|
@ -324,7 +325,7 @@ class App.FirstStepsClues extends App.Controller
|
||||||
when 'hover'
|
when 'hover'
|
||||||
|
|
||||||
# disable active navbar elements
|
# disable active navbar elements
|
||||||
$('#app .navigation .is-active').removeClass('is-active')
|
@appEl.find('.navigation .is-active').removeClass('is-active')
|
||||||
|
|
||||||
if type is 'show'
|
if type is 'show'
|
||||||
target.addClass('is-hovered')
|
target.addClass('is-hovered')
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
class App.DashboardStats extends App.Controller
|
class App.DashboardStats extends App.Controller
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super
|
super
|
||||||
@load()
|
@setupStatsWidgets()
|
||||||
@bind('dashboard_stats_rebuild', @load)
|
@controllerBind('dashboard_stats_rebuild', @setupStatsWidgets)
|
||||||
|
|
||||||
load: =>
|
setupStatsWidgets: =>
|
||||||
@setupStatsWidget('Stats', 'stats', @el)
|
@setupStatsWidget('Stats', 'stats', @el)
|
||||||
|
|
||||||
setupStatsWidget: (config, event, el) ->
|
setupStatsWidget: (config, event, el) ->
|
||||||
|
@ -20,11 +20,11 @@ class App.DashboardStats extends App.Controller
|
||||||
if @permissionCheck(widget.permission)
|
if @permissionCheck(widget.permission)
|
||||||
try
|
try
|
||||||
new widget.controller(
|
new widget.controller(
|
||||||
el: el
|
parentEl: @el
|
||||||
|
className: widget.className
|
||||||
)
|
)
|
||||||
@$('.js-stat-help').tooltip()
|
@$('.js-stat-help').tooltip()
|
||||||
catch e
|
catch e
|
||||||
@log 'error', "statsWidgets #{widget}:", e
|
@log 'error', "statsWidgets #{widget}:", e
|
||||||
|
|
||||||
|
|
||||||
App.Event.trigger(event + ':ready')
|
App.Event.trigger(event + ':ready')
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
class App.ControllerDashboardStatsBase extends App.Controller
|
||||||
|
constructor: (params) ->
|
||||||
|
if params.parentEl
|
||||||
|
el = params.parentEl.find(".column.#{params.className}")
|
||||||
|
if !el.get(0)
|
||||||
|
el = $("<div class=\"column #{params.className}\"></div>")
|
||||||
|
params.parentEl.append(el)
|
||||||
|
params.el = el
|
||||||
|
super(params)
|
||||||
|
@load()
|
||||||
|
|
||||||
|
load: =>
|
||||||
|
stats_store = App.StatsStore.first()
|
||||||
|
if stats_store
|
||||||
|
@render(stats_store.data)
|
||||||
|
else
|
||||||
|
@render()
|
|
@ -1,15 +1,4 @@
|
||||||
class Stats extends App.Controller
|
class Stats extends App.ControllerDashboardStatsBase
|
||||||
constructor: ->
|
|
||||||
super
|
|
||||||
@load()
|
|
||||||
|
|
||||||
load: =>
|
|
||||||
stats_store = App.StatsStore.first()
|
|
||||||
if stats_store
|
|
||||||
@render(stats_store.data)
|
|
||||||
else
|
|
||||||
@render()
|
|
||||||
|
|
||||||
render: (data = {}) ->
|
render: (data = {}) ->
|
||||||
if !data.StatsTicketChannelDistribution
|
if !data.StatsTicketChannelDistribution
|
||||||
data.StatsTicketChannelDistribution =
|
data.StatsTicketChannelDistribution =
|
||||||
|
@ -44,4 +33,4 @@ class Stats extends App.Controller
|
||||||
else
|
else
|
||||||
@el.append(content)
|
@el.append(content)
|
||||||
|
|
||||||
App.Config.set('ticket_channel_distribution', {controller: Stats, permission: 'ticket.agent', prio: 300 }, 'Stats')
|
App.Config.set('ticket_channel_distribution', { controller: Stats, permission: 'ticket.agent', prio: 300, className: 'ticket_channel_distribution' }, 'Stats')
|
||||||
|
|
|
@ -1,15 +1,4 @@
|
||||||
class Stats extends App.Controller
|
class Stats extends App.ControllerDashboardStatsBase
|
||||||
constructor: ->
|
|
||||||
super
|
|
||||||
@load()
|
|
||||||
|
|
||||||
load: =>
|
|
||||||
stats_store = App.StatsStore.first()
|
|
||||||
if stats_store
|
|
||||||
@render(stats_store.data)
|
|
||||||
else
|
|
||||||
@render()
|
|
||||||
|
|
||||||
render: (data = {}) ->
|
render: (data = {}) ->
|
||||||
if !data.StatsTicketEscalation
|
if !data.StatsTicketEscalation
|
||||||
data.StatsTicketEscalation =
|
data.StatsTicketEscalation =
|
||||||
|
@ -26,4 +15,4 @@ class Stats extends App.Controller
|
||||||
else
|
else
|
||||||
@el.append(content)
|
@el.append(content)
|
||||||
|
|
||||||
App.Config.set('ticket_escalation', {controller: Stats, permission: 'ticket.agent', prio: 200 }, 'Stats')
|
App.Config.set('ticket_escalation', { controller: Stats, permission: 'ticket.agent', prio: 200, className: 'ticket_escalation' }, 'Stats')
|
||||||
|
|
|
@ -1,20 +1,10 @@
|
||||||
class Stats extends App.Controller
|
class Stats extends App.ControllerDashboardStatsBase
|
||||||
constructor: ->
|
|
||||||
super
|
|
||||||
@load()
|
|
||||||
|
|
||||||
load: =>
|
|
||||||
stats_store = App.StatsStore.first()
|
|
||||||
if stats_store
|
|
||||||
@render(stats_store.data)
|
|
||||||
else
|
|
||||||
@render()
|
|
||||||
|
|
||||||
render: (data = {}) ->
|
render: (data = {}) ->
|
||||||
if !data.StatsTicketInProcess
|
if !data.StatsTicketInProcess
|
||||||
data.StatsTicketInProcess =
|
data.StatsTicketInProcess =
|
||||||
state: 'supergood'
|
state: 'supergood'
|
||||||
percent: 0
|
percent: 0
|
||||||
|
in_process: 0
|
||||||
average_per_agent: 0
|
average_per_agent: 0
|
||||||
|
|
||||||
data.StatsTicketInProcess.description = 'What percentage of your tickets have you responded to, updated, or modified in some way today?'
|
data.StatsTicketInProcess.description = 'What percentage of your tickets have you responded to, updated, or modified in some way today?'
|
||||||
|
@ -26,5 +16,4 @@ class Stats extends App.Controller
|
||||||
else
|
else
|
||||||
@el.append(content)
|
@el.append(content)
|
||||||
|
|
||||||
|
App.Config.set('ticket_in_process', { controller: Stats, permission: 'ticket.agent', prio: 500, className: 'ticket_in_process' }, 'Stats')
|
||||||
App.Config.set('ticket_in_process', {controller: Stats, permission: 'ticket.agent', prio: 500 }, 'Stats')
|
|
||||||
|
|
|
@ -1,15 +1,4 @@
|
||||||
class Stats extends App.Controller
|
class Stats extends App.ControllerDashboardStatsBase
|
||||||
constructor: ->
|
|
||||||
super
|
|
||||||
@load()
|
|
||||||
|
|
||||||
load: =>
|
|
||||||
stats_store = App.StatsStore.first()
|
|
||||||
if stats_store
|
|
||||||
@render(stats_store.data)
|
|
||||||
else
|
|
||||||
@render()
|
|
||||||
|
|
||||||
render: (data = {}) ->
|
render: (data = {}) ->
|
||||||
if !data.StatsTicketLoadMeasure
|
if !data.StatsTicketLoadMeasure
|
||||||
data.StatsTicketLoadMeasure =
|
data.StatsTicketLoadMeasure =
|
||||||
|
@ -28,4 +17,4 @@ class Stats extends App.Controller
|
||||||
else
|
else
|
||||||
@el.append(content)
|
@el.append(content)
|
||||||
|
|
||||||
App.Config.set('ticket_load_measure', {controller: Stats, permission: 'ticket.agent', prio: 400 }, 'Stats')
|
App.Config.set('ticket_load_measure', { controller: Stats, permission: 'ticket.agent', prio: 400, className: 'ticket_load_measure' }, 'Stats')
|
||||||
|
|
|
@ -1,15 +1,4 @@
|
||||||
class Stats extends App.Controller
|
class Stats extends App.ControllerDashboardStatsBase
|
||||||
constructor: ->
|
|
||||||
super
|
|
||||||
@load()
|
|
||||||
|
|
||||||
load: =>
|
|
||||||
stats_store = App.StatsStore.first()
|
|
||||||
if stats_store
|
|
||||||
@render(stats_store.data)
|
|
||||||
else
|
|
||||||
@render()
|
|
||||||
|
|
||||||
render: (data = {}) ->
|
render: (data = {}) ->
|
||||||
if !data.StatsTicketReopen
|
if !data.StatsTicketReopen
|
||||||
data.StatsTicketReopen =
|
data.StatsTicketReopen =
|
||||||
|
@ -25,4 +14,4 @@ class Stats extends App.Controller
|
||||||
else
|
else
|
||||||
@el.append(content)
|
@el.append(content)
|
||||||
|
|
||||||
App.Config.set('ticket_reopen', {controller: Stats, permission: 'ticket.agent', prio: 600 }, 'Stats')
|
App.Config.set('ticket_reopen', { controller: Stats, permission: 'ticket.agent', prio: 600, className: 'ticket_reopen' }, 'Stats')
|
||||||
|
|
|
@ -1,15 +1,4 @@
|
||||||
class Stats extends App.Controller
|
class Stats extends App.ControllerDashboardStatsBase
|
||||||
constructor: ->
|
|
||||||
super
|
|
||||||
@load()
|
|
||||||
|
|
||||||
load: =>
|
|
||||||
stats_store = App.StatsStore.first()
|
|
||||||
if stats_store
|
|
||||||
@render(stats_store.data)
|
|
||||||
else
|
|
||||||
@render()
|
|
||||||
|
|
||||||
render: (data = {}) ->
|
render: (data = {}) ->
|
||||||
if !data.StatsTicketWaitingTime
|
if !data.StatsTicketWaitingTime
|
||||||
data.StatsTicketWaitingTime =
|
data.StatsTicketWaitingTime =
|
||||||
|
@ -75,4 +64,4 @@ class Stats extends App.Controller
|
||||||
ctx.closePath()
|
ctx.closePath()
|
||||||
ctx.fill()
|
ctx.fill()
|
||||||
|
|
||||||
App.Config.set('ticket_waiting_time', {controller: Stats, permission: 'ticket.agent', prio: 100 }, 'Stats')
|
App.Config.set('ticket_waiting_time', { controller: Stats, permission: 'ticket.agent', prio: 100, className: 'ticket_waiting_time' }, 'Stats')
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerIntegrationBase
|
class CheckMk extends App.ControllerIntegrationBase
|
||||||
featureIntegration: 'check_mk_integration'
|
featureIntegration: 'check_mk_integration'
|
||||||
featureName: 'Checkmk'
|
featureName: 'Checkmk'
|
||||||
featureConfig: 'check_mk_config'
|
featureConfig: 'check_mk_config'
|
||||||
|
@ -55,7 +55,7 @@ App.Config.set(
|
||||||
name: 'Checkmk'
|
name: 'Checkmk'
|
||||||
target: '#system/integration/check_mk'
|
target: '#system/integration/check_mk'
|
||||||
description: 'An open source monitoring tool.'
|
description: 'An open source monitoring tool.'
|
||||||
controller: Index
|
controller: CheckMk
|
||||||
state: State
|
state: State
|
||||||
permission: ['admin.integration.check_mk']
|
permission: ['admin.integration.check_mk']
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerIntegrationBase
|
class Clearbit extends App.ControllerIntegrationBase
|
||||||
featureIntegration: 'clearbit_integration'
|
featureIntegration: 'clearbit_integration'
|
||||||
featureName: 'Clearbit'
|
featureName: 'Clearbit'
|
||||||
featureConfig: 'clearbit_config'
|
featureConfig: 'clearbit_config'
|
||||||
|
@ -155,7 +155,7 @@ App.Config.set(
|
||||||
name: 'Clearbit'
|
name: 'Clearbit'
|
||||||
target: '#system/integration/clearbit'
|
target: '#system/integration/clearbit'
|
||||||
description: 'A powerful service to get more information about your customers.'
|
description: 'A powerful service to get more information about your customers.'
|
||||||
controller: Index
|
controller: Clearbit
|
||||||
state: State
|
state: State
|
||||||
permission: ['admin.integration.clearbit']
|
permission: ['admin.integration.clearbit']
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerIntegrationBase
|
class Cti extends App.ControllerIntegrationBase
|
||||||
featureIntegration: 'cti_integration'
|
featureIntegration: 'cti_integration'
|
||||||
featureName: 'CTI (generic)'
|
featureName: 'CTI (generic)'
|
||||||
featureConfig: 'cti_config'
|
featureConfig: 'cti_config'
|
||||||
|
@ -234,7 +234,7 @@ App.Config.set(
|
||||||
name: 'CTI (generic)'
|
name: 'CTI (generic)'
|
||||||
target: '#system/integration/cti'
|
target: '#system/integration/cti'
|
||||||
description: 'Generic API to integrate VoIP service provider with realtime push.'
|
description: 'Generic API to integrate VoIP service provider with realtime push.'
|
||||||
controller: Index
|
controller: Cti
|
||||||
state: State
|
state: State
|
||||||
}
|
}
|
||||||
'NavBarIntegrations'
|
'NavBarIntegrations'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerIntegrationBase
|
class Exchange extends App.ControllerIntegrationBase
|
||||||
featureIntegration: 'exchange_integration'
|
featureIntegration: 'exchange_integration'
|
||||||
featureName: 'Exchange'
|
featureName: 'Exchange'
|
||||||
featureConfig: 'exchange_config'
|
featureConfig: 'exchange_config'
|
||||||
|
@ -166,7 +166,7 @@ class State
|
||||||
@current: ->
|
@current: ->
|
||||||
App.Setting.get('exchange_integration')
|
App.Setting.get('exchange_integration')
|
||||||
|
|
||||||
class ConnectionWizard extends App.WizardModal
|
class ConnectionWizard extends App.ControllerWizardModal
|
||||||
wizardConfig: {}
|
wizardConfig: {}
|
||||||
slideMethod:
|
slideMethod:
|
||||||
'js-folders': 'foldersShow'
|
'js-folders': 'foldersShow'
|
||||||
|
@ -557,7 +557,7 @@ App.Config.set(
|
||||||
name: 'Exchange'
|
name: 'Exchange'
|
||||||
target: '#system/integration/exchange'
|
target: '#system/integration/exchange'
|
||||||
description: 'Exchange integration for contacts management.'
|
description: 'Exchange integration for contacts management.'
|
||||||
controller: Index
|
controller: Exchange
|
||||||
state: State
|
state: State
|
||||||
permission: ['admin.integration.exchange']
|
permission: ['admin.integration.exchange']
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerIntegrationBase
|
class Icinga extends App.ControllerIntegrationBase
|
||||||
featureIntegration: 'icinga_integration'
|
featureIntegration: 'icinga_integration'
|
||||||
featureName: 'Icinga'
|
featureName: 'Icinga'
|
||||||
featureConfig: 'icinga_config'
|
featureConfig: 'icinga_config'
|
||||||
|
@ -24,7 +24,7 @@ App.Config.set(
|
||||||
name: 'Icinga'
|
name: 'Icinga'
|
||||||
target: '#system/integration/icinga'
|
target: '#system/integration/icinga'
|
||||||
description: 'An open source monitoring tool.'
|
description: 'An open source monitoring tool.'
|
||||||
controller: Index
|
controller: Icinga
|
||||||
state: State
|
state: State
|
||||||
permission: ['admin.integration.icinga']
|
permission: ['admin.integration.icinga']
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerIntegrationBase
|
class Idoit extends App.ControllerIntegrationBase
|
||||||
featureIntegration: 'idoit_integration'
|
featureIntegration: 'idoit_integration'
|
||||||
featureName: 'i-doit'
|
featureName: 'i-doit'
|
||||||
featureConfig: 'idoit_config'
|
featureConfig: 'idoit_config'
|
||||||
|
@ -58,7 +58,7 @@ class Form extends App.Controller
|
||||||
)
|
)
|
||||||
success: (data, status, xhr) =>
|
success: (data, status, xhr) =>
|
||||||
if data.result is 'failed'
|
if data.result is 'failed'
|
||||||
new App.ControllerErrorModal(
|
new App.ErrorModal(
|
||||||
message: data.message
|
message: data.message
|
||||||
container: @el.closest('.content')
|
container: @el.closest('.content')
|
||||||
)
|
)
|
||||||
|
@ -87,7 +87,7 @@ App.Config.set(
|
||||||
name: 'i-doit'
|
name: 'i-doit'
|
||||||
target: '#system/integration/idoit'
|
target: '#system/integration/idoit'
|
||||||
description: 'CMDB to document complex relations of your network components.'
|
description: 'CMDB to document complex relations of your network components.'
|
||||||
controller: Index
|
controller: Idoit
|
||||||
state: State
|
state: State
|
||||||
}
|
}
|
||||||
'NavBarIntegrations'
|
'NavBarIntegrations'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerIntegrationBase
|
class Ldap extends App.ControllerIntegrationBase
|
||||||
featureIntegration: 'ldap_integration'
|
featureIntegration: 'ldap_integration'
|
||||||
featureName: 'LDAP'
|
featureName: 'LDAP'
|
||||||
featureConfig: 'ldap_config'
|
featureConfig: 'ldap_config'
|
||||||
|
@ -71,6 +71,7 @@ class Form extends App.Controller
|
||||||
group_role_map = {}
|
group_role_map = {}
|
||||||
for source, dests of @config.group_role_map
|
for source, dests of @config.group_role_map
|
||||||
group_role_map[source] = dests.map((dest) ->
|
group_role_map[source] = dests.map((dest) ->
|
||||||
|
return '?' if !App.Role.exists(dest)
|
||||||
App.Role.find(dest).displayName()
|
App.Role.find(dest).displayName()
|
||||||
).join ', '
|
).join ', '
|
||||||
|
|
||||||
|
@ -135,6 +136,7 @@ class Form extends App.Controller
|
||||||
if !job.result.roles
|
if !job.result.roles
|
||||||
job.result.roles = {}
|
job.result.roles = {}
|
||||||
for role_id, statistic of job.result.role_ids
|
for role_id, statistic of job.result.role_ids
|
||||||
|
if App.Role.exists(role_id)
|
||||||
role = App.Role.find(role_id)
|
role = App.Role.find(role_id)
|
||||||
job.result.roles[role.displayName()] = statistic
|
job.result.roles[role.displayName()] = statistic
|
||||||
el = $(App.view('integration/ldap_last_import')(job: job))
|
el = $(App.view('integration/ldap_last_import')(job: job))
|
||||||
|
@ -167,9 +169,7 @@ class State
|
||||||
@current: ->
|
@current: ->
|
||||||
App.Setting.get('ldap_integration')
|
App.Setting.get('ldap_integration')
|
||||||
|
|
||||||
class ConnectionWizard extends App.WizardModal
|
class ConnectionWizard extends App.ControllerWizardModal
|
||||||
className: 'modal fade modal--large'
|
|
||||||
|
|
||||||
wizardConfig: {}
|
wizardConfig: {}
|
||||||
slideMethod:
|
slideMethod:
|
||||||
'js-bind': 'bindShow'
|
'js-bind': 'bindShow'
|
||||||
|
@ -562,6 +562,7 @@ class ConnectionWizard extends App.WizardModal
|
||||||
if !job.result.roles
|
if !job.result.roles
|
||||||
job.result.roles = {}
|
job.result.roles = {}
|
||||||
for role_id, statistic of job.result.role_ids
|
for role_id, statistic of job.result.role_ids
|
||||||
|
if App.Role.find(role_id)
|
||||||
role = App.Role.find(role_id)
|
role = App.Role.find(role_id)
|
||||||
job.result.roles[role.displayName()] = statistic
|
job.result.roles[role.displayName()] = statistic
|
||||||
@showSlide('js-try')
|
@showSlide('js-try')
|
||||||
|
@ -574,7 +575,7 @@ App.Config.set(
|
||||||
name: 'LDAP'
|
name: 'LDAP'
|
||||||
target: '#system/integration/ldap'
|
target: '#system/integration/ldap'
|
||||||
description: 'LDAP integration for user management.'
|
description: 'LDAP integration for user management.'
|
||||||
controller: Index
|
controller: Ldap
|
||||||
state: State
|
state: State
|
||||||
permission: ['admin.integration.ldap']
|
permission: ['admin.integration.ldap']
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerIntegrationBase
|
class Monit extends App.ControllerIntegrationBase
|
||||||
featureIntegration: 'monit_integration'
|
featureIntegration: 'monit_integration'
|
||||||
featureName: 'Monit'
|
featureName: 'Monit'
|
||||||
featureConfig: 'monit_config'
|
featureConfig: 'monit_config'
|
||||||
|
@ -24,7 +24,7 @@ App.Config.set(
|
||||||
name: 'Monit'
|
name: 'Monit'
|
||||||
target: '#system/integration/monit'
|
target: '#system/integration/monit'
|
||||||
description: 'An open source monitoring tool.'
|
description: 'An open source monitoring tool.'
|
||||||
controller: Index
|
controller: Monit
|
||||||
state: State
|
state: State
|
||||||
permission: ['admin.integration.monit']
|
permission: ['admin.integration.monit']
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerIntegrationBase
|
class Nagios extends App.ControllerIntegrationBase
|
||||||
featureIntegration: 'nagios_integration'
|
featureIntegration: 'nagios_integration'
|
||||||
featureName: 'Nagios'
|
featureName: 'Nagios'
|
||||||
featureConfig: 'nagios_config'
|
featureConfig: 'nagios_config'
|
||||||
|
@ -24,7 +24,7 @@ App.Config.set(
|
||||||
name: 'Nagios'
|
name: 'Nagios'
|
||||||
target: '#system/integration/nagios'
|
target: '#system/integration/nagios'
|
||||||
description: 'An open source monitoring tool.'
|
description: 'An open source monitoring tool.'
|
||||||
controller: Index
|
controller: Nagios
|
||||||
state: State
|
state: State
|
||||||
}
|
}
|
||||||
'NavBarIntegrations'
|
'NavBarIntegrations'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerIntegrationBase
|
class Placetel extends App.ControllerIntegrationBase
|
||||||
featureIntegration: 'placetel_integration'
|
featureIntegration: 'placetel_integration'
|
||||||
featureName: 'Placetel'
|
featureName: 'Placetel'
|
||||||
featureConfig: 'placetel_config'
|
featureConfig: 'placetel_config'
|
||||||
|
@ -188,7 +188,7 @@ App.Config.set(
|
||||||
name: 'Placetel'
|
name: 'Placetel'
|
||||||
target: '#system/integration/placetel'
|
target: '#system/integration/placetel'
|
||||||
description: 'VoIP service provider with realtime push.'
|
description: 'VoIP service provider with realtime push.'
|
||||||
controller: Index
|
controller: Placetel
|
||||||
state: State
|
state: State
|
||||||
}
|
}
|
||||||
'NavBarIntegrations'
|
'NavBarIntegrations'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerIntegrationBase
|
class SipgateIo extends App.ControllerIntegrationBase
|
||||||
featureIntegration: 'sipgate_integration'
|
featureIntegration: 'sipgate_integration'
|
||||||
featureName: 'sipgate.io'
|
featureName: 'sipgate.io'
|
||||||
featureConfig: 'sipgate_config'
|
featureConfig: 'sipgate_config'
|
||||||
|
@ -188,7 +188,7 @@ App.Config.set(
|
||||||
name: 'sipgate.io'
|
name: 'sipgate.io'
|
||||||
target: '#system/integration/sipgate'
|
target: '#system/integration/sipgate'
|
||||||
description: 'VoIP service provider with realtime push.'
|
description: 'VoIP service provider with realtime push.'
|
||||||
controller: Index
|
controller: SipgateIo
|
||||||
state: State
|
state: State
|
||||||
}
|
}
|
||||||
'NavBarIntegrations'
|
'NavBarIntegrations'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerIntegrationBase
|
class Slack extends App.ControllerIntegrationBase
|
||||||
featureIntegration: 'slack_integration'
|
featureIntegration: 'slack_integration'
|
||||||
featureName: 'Slack'
|
featureName: 'Slack'
|
||||||
featureConfig: 'slack_config'
|
featureConfig: 'slack_config'
|
||||||
|
@ -85,7 +85,7 @@ App.Config.set(
|
||||||
target: '#system/integration/slack'
|
target: '#system/integration/slack'
|
||||||
description: 'A team communication tool for the 21st century. Compatible with tools like %s.'
|
description: 'A team communication tool for the 21st century. Compatible with tools like %s.'
|
||||||
descriptionSubstitute: 'Mattermost, RocketChat'
|
descriptionSubstitute: 'Mattermost, RocketChat'
|
||||||
controller: Index
|
controller: Slack
|
||||||
state: State
|
state: State
|
||||||
}
|
}
|
||||||
'NavBarIntegrations'
|
'NavBarIntegrations'
|
||||||
|
|
|
@ -99,11 +99,9 @@ class Certificate extends App.ControllerModal
|
||||||
cache: false
|
cache: false
|
||||||
data: params
|
data: params
|
||||||
success: (data, status, xhr) =>
|
success: (data, status, xhr) =>
|
||||||
console.log('success')
|
|
||||||
@close()
|
@close()
|
||||||
@callback()
|
@callback()
|
||||||
error: (data) =>
|
error: (data) =>
|
||||||
console.log('error')
|
|
||||||
@close()
|
@close()
|
||||||
details = data.responseJSON || {}
|
details = data.responseJSON || {}
|
||||||
@notify
|
@notify
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
class Widget extends App.Controller
|
class AppConfigUpdate
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super
|
|
||||||
|
|
||||||
App.Event.bind(
|
App.Event.bind(
|
||||||
'config_update'
|
'config_update'
|
||||||
(data) ->
|
(data) ->
|
||||||
|
@ -9,4 +7,7 @@ class Widget extends App.Controller
|
||||||
App.Event.trigger('config_update_local', data)
|
App.Event.trigger('config_update_local', data)
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Config.set('app_config_update', Widget, 'Widgets')
|
release: ->
|
||||||
|
App.Event.unbind('config_update')
|
||||||
|
|
||||||
|
App.Config.set('app_config_update', AppConfigUpdate, 'Plugins')
|
|
@ -16,8 +16,8 @@ class DefaultLocale extends App.Controller
|
||||||
processData: true
|
processData: true
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Event.bind('auth:login', (session) =>
|
@controllerBind('auth:login', (session) =>
|
||||||
@delay(check, 3500, 'default_locale')
|
@delay(check, 3500, 'default_locale')
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Config.set('default_locale', DefaultLocale, 'Widgets')
|
App.Config.set('default_locale', DefaultLocale, 'Plugins')
|
|
@ -26,11 +26,11 @@ class DefaultTimezone extends App.Controller
|
||||||
# processData: true
|
# processData: true
|
||||||
#)
|
#)
|
||||||
|
|
||||||
App.Event.bind('auth:login', (session) =>
|
@controllerBind('auth:login', (session) =>
|
||||||
@delay(check, 8500, 'default_timezone')
|
@delay(check, 8500, 'default_timezone')
|
||||||
)
|
)
|
||||||
|
|
||||||
updateSetting: (timezone) ->
|
updateSetting: (timezone) ->
|
||||||
App.Setting.set('timezone_default', timezone)
|
App.Setting.set('timezone_default', timezone)
|
||||||
|
|
||||||
App.Config.set('default_timezone', DefaultTimezone, 'Widgets')
|
App.Config.set('default_timezone', DefaultTimezone, 'Plugins')
|
|
@ -1,4 +1,4 @@
|
||||||
class Widget
|
class DevBanner
|
||||||
constructor: ->
|
constructor: ->
|
||||||
return if !App.Config.get('developer_mode')
|
return if !App.Config.get('developer_mode')
|
||||||
return if App.Log.config('banner') is false
|
return if App.Log.config('banner') is false
|
||||||
|
@ -17,4 +17,4 @@ class Widget
|
||||||
"""
|
"""
|
||||||
console.log(banner)
|
console.log(banner)
|
||||||
|
|
||||||
App.Config.set('dev_banner', Widget, 'Widgets')
|
App.Config.set('dev_banner', DevBanner, 'Plugins')
|
|
@ -1,18 +1,19 @@
|
||||||
class Widget
|
class ElectronEvents extends App.Controller
|
||||||
constructor: ->
|
constructor: ->
|
||||||
return if !window.require
|
return if !window.require
|
||||||
electron = window.require('electron')
|
electron = window.require('electron')
|
||||||
return if !electron
|
return if !electron
|
||||||
remote = electron.remote
|
remote = electron.remote
|
||||||
ipc = electron.ipcRenderer
|
ipc = electron.ipcRenderer
|
||||||
|
super
|
||||||
|
|
||||||
App.Event.bind('window-title-set', (arg) ->
|
@controllerBind('window-title-set', (arg) ->
|
||||||
ipc.send('window-title-set', arg)
|
ipc.send('window-title-set', arg)
|
||||||
)
|
)
|
||||||
App.Event.bind('online_notification_counter', (e) ->
|
@controllerBind('online_notification_counter', (e) ->
|
||||||
setBadge(e)
|
setBadge(e)
|
||||||
)
|
)
|
||||||
ipc.on('global-shortcut', (e, arg) ->
|
ipc.off('global-shortcut').on('global-shortcut', (e, arg) ->
|
||||||
App.Event.trigger('global-shortcut', arg)
|
App.Event.trigger('global-shortcut', arg)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -91,4 +92,4 @@ class Widget
|
||||||
else if process.platform is 'darwin'
|
else if process.platform is 'darwin'
|
||||||
setBadgeOSX(content)
|
setBadgeOSX(content)
|
||||||
|
|
||||||
App.Config.set('aaa_electron_events', Widget, 'Navigations')
|
App.Config.set('aaa_electron_events', ElectronEvents, 'Plugins')
|
|
@ -1,12 +1,13 @@
|
||||||
class App.GlobalSearchWidget extends Spine.Module
|
class App.GlobalSearchWidget extends App.Controller
|
||||||
shiftHeld = false
|
shiftHeld = false
|
||||||
|
|
||||||
constructor: ->
|
constructor: ->
|
||||||
$('body').on('mousedown', (e) =>
|
super
|
||||||
|
$('body').off('mousedown.globalsearch').on('mousedown.globalsearch', (e) =>
|
||||||
@shiftHeldToogle(e)
|
@shiftHeldToogle(e)
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
App.Event.bind('global:search:set', (data) =>
|
@controllerBind('global:search:set', (data) =>
|
||||||
item = data[0]
|
item = data[0]
|
||||||
attribute = data[1]
|
attribute = data[1]
|
||||||
item = item.replace('"', '')
|
item = item.replace('"', '')
|
||||||
|
@ -36,4 +37,4 @@ class App.GlobalSearchWidget extends Spine.Module
|
||||||
@search: (item, attribute) ->
|
@search: (item, attribute) ->
|
||||||
App.Event.trigger('global:search:set', [item, attribute])
|
App.Event.trigger('global:search:set', [item, attribute])
|
||||||
|
|
||||||
App.Config.set('global_navigation', App.GlobalSearchWidget, 'Widgets')
|
App.Config.set('global_navigation', App.GlobalSearchWidget, 'Plugins')
|
|
@ -1,4 +1,4 @@
|
||||||
class Widget
|
class HelloBanner
|
||||||
constructor: ->
|
constructor: ->
|
||||||
return if App.Config.get('developer_mode')
|
return if App.Config.get('developer_mode')
|
||||||
banner = """
|
banner = """
|
||||||
|
@ -17,4 +17,4 @@ class Widget
|
||||||
"""
|
"""
|
||||||
console.log(banner, 'text-decoration: underline;', 'text-decoration: none;')
|
console.log(banner, 'text-decoration: underline;', 'text-decoration: none;')
|
||||||
|
|
||||||
App.Config.set('hello_banner', Widget, 'Widgets')
|
App.Config.set('hello_banner', HelloBanner, 'Plugins')
|
|
@ -8,7 +8,7 @@ class App.KeyboardShortcutModal extends App.ControllerModal
|
||||||
|
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super
|
super
|
||||||
@bind('keyboard_shortcuts_close', @close)
|
@controllerBind('keyboard_shortcuts_close', @close)
|
||||||
|
|
||||||
content: ->
|
content: ->
|
||||||
App.view('keyboard_shortcuts')(
|
App.view('keyboard_shortcuts')(
|
||||||
|
@ -25,10 +25,11 @@ class App.KeyboardShortcutModal extends App.ControllerModal
|
||||||
return if window.location.hash isnt '#keyboard_shortcuts'
|
return if window.location.hash isnt '#keyboard_shortcuts'
|
||||||
window.history.back()
|
window.history.back()
|
||||||
|
|
||||||
class App.KeyboardShortcutWidget extends Spine.Module
|
class App.KeyboardShortcutWidget extends App.Controller
|
||||||
@include App.LogInclude
|
@include App.LogInclude
|
||||||
|
|
||||||
constructor: ->
|
constructor: ->
|
||||||
|
super
|
||||||
@observerKeys()
|
@observerKeys()
|
||||||
@lastKey = undefined
|
@lastKey = undefined
|
||||||
|
|
||||||
|
@ -38,6 +39,7 @@ class App.KeyboardShortcutWidget extends Spine.Module
|
||||||
)
|
)
|
||||||
|
|
||||||
observerKeys: =>
|
observerKeys: =>
|
||||||
|
$(document).unbind('keydown.shortcuts')
|
||||||
navigationHotkeys = App.Browser.hotkeys()
|
navigationHotkeys = App.Browser.hotkeys()
|
||||||
|
|
||||||
areas = App.Config.get('keyboard_shortcuts')
|
areas = App.Config.get('keyboard_shortcuts')
|
||||||
|
@ -54,7 +56,7 @@ class App.KeyboardShortcutWidget extends Spine.Module
|
||||||
modifier += shortcut.key
|
modifier += shortcut.key
|
||||||
if shortcut.callback
|
if shortcut.callback
|
||||||
@log 'debug', 'bind for', modifier
|
@log 'debug', 'bind for', modifier
|
||||||
$(document).bind('keydown', modifier, (e) =>
|
$(document).bind('keydown.shortcuts', modifier, (e) =>
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
if @lastKey && @lastKey.modifier is modifier && @lastKey.time + 5500 > new Date().getTime()
|
if @lastKey && @lastKey.modifier is modifier && @lastKey.time + 5500 > new Date().getTime()
|
||||||
@lastKey.count += 1
|
@lastKey.count += 1
|
||||||
|
@ -67,7 +69,7 @@ class App.KeyboardShortcutWidget extends Spine.Module
|
||||||
shortcut.callback(shortcut, @lastKey, modifier)
|
shortcut.callback(shortcut, @lastKey, modifier)
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Event.bind('global-shortcut', (e) ->
|
@controllerBind('global-shortcut', (e) ->
|
||||||
for area in areas
|
for area in areas
|
||||||
for item in area.content
|
for item in area.content
|
||||||
for shortcut in item.shortcuts
|
for shortcut in item.shortcuts
|
||||||
|
@ -75,7 +77,7 @@ class App.KeyboardShortcutWidget extends Spine.Module
|
||||||
shortcut.callback(shortcut)
|
shortcut.callback(shortcut)
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Config.set('keyboard_shortcuts', App.KeyboardShortcutWidget, 'Widgets')
|
App.Config.set('keyboard_shortcuts', App.KeyboardShortcutWidget, 'Plugins')
|
||||||
App.Config.set(
|
App.Config.set(
|
||||||
'keyboard_shortcuts',
|
'keyboard_shortcuts',
|
||||||
[
|
[
|
|
@ -1,9 +1,8 @@
|
||||||
class Widget extends App.Controller
|
class Maintenance extends App.Controller
|
||||||
serverRestarted: false
|
serverRestarted: false
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super
|
super
|
||||||
|
@controllerBind(
|
||||||
App.Event.bind(
|
|
||||||
'maintenance'
|
'maintenance'
|
||||||
(data) =>
|
(data) =>
|
||||||
if data.type is 'message'
|
if data.type is 'message'
|
||||||
|
@ -18,7 +17,6 @@ class Widget extends App.Controller
|
||||||
@maintanaceRestartAuto(data)
|
@maintanaceRestartAuto(data)
|
||||||
if data.type is 'restart_manual'
|
if data.type is 'restart_manual'
|
||||||
@maintanaceRestartManual(data)
|
@maintanaceRestartManual(data)
|
||||||
'maintenance'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
showMessage: (message = {}) =>
|
showMessage: (message = {}) =>
|
||||||
|
@ -129,4 +127,4 @@ class Widget extends App.Controller
|
||||||
timeout ?= 1000
|
timeout ?= 1000
|
||||||
@delay(delay, timeout)
|
@delay(delay, timeout)
|
||||||
|
|
||||||
App.Config.set('maintenance', Widget, 'Widgets')
|
App.Config.set('maintenance', Maintenance, 'Plugins')
|
|
@ -1,9 +1,7 @@
|
||||||
class App.Navigation extends App.ControllerWidgetPermanent
|
class Navigation extends App.Controller
|
||||||
@extend App.PopoverProvidable
|
@extend App.PopoverProvidable
|
||||||
@registerAllPopovers()
|
@registerAllPopovers()
|
||||||
|
|
||||||
className: 'navigation vertical'
|
|
||||||
|
|
||||||
elements:
|
elements:
|
||||||
'#global-search': 'searchInput'
|
'#global-search': 'searchInput'
|
||||||
'.search': 'searchContainer'
|
'.search': 'searchContainer'
|
||||||
|
@ -33,36 +31,37 @@ class App.Navigation extends App.ControllerWidgetPermanent
|
||||||
)
|
)
|
||||||
|
|
||||||
# rerender view, e. g. on langauge change
|
# rerender view, e. g. on langauge change
|
||||||
@bind 'ui:rerender', =>
|
@controllerBind('ui:rerender', =>
|
||||||
@renderMenu()
|
@renderMenu()
|
||||||
@renderPersonal()
|
@renderPersonal()
|
||||||
|
)
|
||||||
|
|
||||||
# rerender menu
|
# rerender menu
|
||||||
@bind 'menu:render', =>
|
@controllerBind('menu:render', =>
|
||||||
@renderMenu()
|
@renderMenu()
|
||||||
|
)
|
||||||
|
|
||||||
# rerender menu
|
# rerender menu
|
||||||
@bind 'personal:render', =>
|
@controllerBind('personal:render', =>
|
||||||
@renderPersonal()
|
@renderPersonal()
|
||||||
|
)
|
||||||
|
|
||||||
# update selected item
|
# update selected item
|
||||||
@bind 'navupdate', (params) =>
|
@controllerBind('navupdate', (params) =>
|
||||||
@update(params)
|
@update(params)
|
||||||
|
)
|
||||||
# rebuild nav bar with given user data
|
|
||||||
@bind 'auth', (user) =>
|
|
||||||
@render()
|
|
||||||
|
|
||||||
# fetch new recent viewed after collection change
|
# fetch new recent viewed after collection change
|
||||||
@bind 'RecentView::changed', =>
|
@controllerBind('RecentView::changed', =>
|
||||||
@delay(
|
@delay(
|
||||||
=> @fetchRecentView()
|
=> @fetchRecentView()
|
||||||
1000
|
1000
|
||||||
'recent-view-changed'
|
'recent-view-changed'
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# bell on / bell off
|
# bell on / bell off
|
||||||
@bind 'bell', (data) =>
|
@controllerBind('bell', (data) =>
|
||||||
if data is 'on'
|
if data is 'on'
|
||||||
@$('.bell').addClass('show')
|
@$('.bell').addClass('show')
|
||||||
App.Audio.play( 'https://www.sounddogs.com/previews/2193/mp3/219024_SOUNDDOGS__be.mp3' )
|
App.Audio.play( 'https://www.sounddogs.com/previews/2193/mp3/219024_SOUNDDOGS__be.mp3' )
|
||||||
|
@ -72,6 +71,7 @@ class App.Navigation extends App.ControllerWidgetPermanent
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
@$('.bell').removeClass('show')
|
@$('.bell').removeClass('show')
|
||||||
|
)
|
||||||
|
|
||||||
release: =>
|
release: =>
|
||||||
if @notificationWidget
|
if @notificationWidget
|
||||||
|
@ -187,13 +187,27 @@ class App.Navigation extends App.ControllerWidgetPermanent
|
||||||
@renderPopovers()
|
@renderPopovers()
|
||||||
|
|
||||||
render: ->
|
render: ->
|
||||||
|
|
||||||
user = App.Session.get()
|
user = App.Session.get()
|
||||||
@html App.view('navigation')(
|
if _.isEmpty(user)
|
||||||
user: user
|
@appEl.find('#navigation').remove()
|
||||||
)
|
return
|
||||||
|
|
||||||
@taskbar = new App.TaskbarWidget( el: @$('.tasks') )
|
navigation = $(App.view('navigation')(
|
||||||
|
user: user
|
||||||
|
))
|
||||||
|
|
||||||
|
@taskbar = new App.TaskbarWidget(el: navigation.find('.tasks'))
|
||||||
|
|
||||||
|
@el = navigation
|
||||||
|
if !@appEl.find('#navigation').get(0)
|
||||||
|
@appEl.prepend(navigation)
|
||||||
|
@delegateEvents(@events)
|
||||||
|
@refreshElements()
|
||||||
|
@el.on('remove', @releaseController)
|
||||||
|
@el.on('remove', @release)
|
||||||
|
else
|
||||||
|
@el = @appEl.find('#navigation')
|
||||||
|
@html(navigation)
|
||||||
|
|
||||||
# renderMenu
|
# renderMenu
|
||||||
@renderMenu()
|
@renderMenu()
|
||||||
|
@ -204,7 +218,7 @@ class App.Navigation extends App.ControllerWidgetPermanent
|
||||||
if @notificationWidget
|
if @notificationWidget
|
||||||
@notificationWidget.remove()
|
@notificationWidget.remove()
|
||||||
@notificationWidget = new App.OnlineNotificationWidget()
|
@notificationWidget = new App.OnlineNotificationWidget()
|
||||||
$('#app').append @notificationWidget.el
|
@appEl.append @notificationWidget.el
|
||||||
|
|
||||||
searchFocus: (e) =>
|
searchFocus: (e) =>
|
||||||
@clearDelay('emptyAndCloseDelayed')
|
@clearDelay('emptyAndCloseDelayed')
|
||||||
|
@ -490,6 +504,7 @@ class App.Navigation extends App.ControllerWidgetPermanent
|
||||||
App.RecentView.fetchFull(load, clear: true)
|
App.RecentView.fetchFull(load, clear: true)
|
||||||
|
|
||||||
toggleNotifications: (e) ->
|
toggleNotifications: (e) ->
|
||||||
|
console.log('toggleNotifications', @notificationWidget)
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
@notificationWidget.toggle()
|
@notificationWidget.toggle()
|
||||||
|
|
||||||
|
@ -503,4 +518,4 @@ class App.Navigation extends App.ControllerWidgetPermanent
|
||||||
return
|
return
|
||||||
@navigate('#search')
|
@navigate('#search')
|
||||||
|
|
||||||
App.Config.set('navigation', App.Navigation, 'Navigations')
|
App.Config.set('aaa_navigation', Navigation, 'Plugins')
|
|
@ -1,4 +1,4 @@
|
||||||
class App.Notify extends App.ControllerWidgetPermanent
|
class App.Notify extends App.Controller
|
||||||
desktopNotify: {}
|
desktopNotify: {}
|
||||||
desktopNotifyCounter: 0
|
desktopNotifyCounter: 0
|
||||||
|
|
||||||
|
@ -8,14 +8,14 @@ class App.Notify extends App.ControllerWidgetPermanent
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super
|
super
|
||||||
|
|
||||||
@bind 'notify', (data) =>
|
@controllerBind('notify', (data) =>
|
||||||
@render(data)
|
@render(data)
|
||||||
|
)
|
||||||
@bind 'notify:removeall', =>
|
@controllerBind('notify:removeall', =>
|
||||||
@log 'notify:removeall', @
|
@log 'notify:removeall', @
|
||||||
@destroyAll()
|
@destroyAll()
|
||||||
|
)
|
||||||
@bind 'notifyDesktop', (data) =>
|
@controllerBind('notifyDesktop', (data) =>
|
||||||
return if !window.Notification
|
return if !window.Notification
|
||||||
|
|
||||||
if !data['icon']
|
if !data['icon']
|
||||||
|
@ -48,13 +48,14 @@ class App.Notify extends App.ControllerWidgetPermanent
|
||||||
-> notification.close()
|
-> notification.close()
|
||||||
data.timeout || timeout
|
data.timeout || timeout
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# request desktop notification after login
|
# request desktop notification after login
|
||||||
@bind 'auth', (data) ->
|
@controllerBind('auth', (data) ->
|
||||||
if !_.isEmpty(data)
|
if !_.isEmpty(data)
|
||||||
return if !window.Notification
|
return if !window.Notification
|
||||||
window.Notification.requestPermission()
|
window.Notification.requestPermission()
|
||||||
|
)
|
||||||
$(window).focus(
|
$(window).focus(
|
||||||
=>
|
=>
|
||||||
for counter, notification of @desktopNotify
|
for counter, notification of @desktopNotify
|
||||||
|
@ -63,6 +64,9 @@ class App.Notify extends App.ControllerWidgetPermanent
|
||||||
|
|
||||||
render: (data) ->
|
render: (data) ->
|
||||||
|
|
||||||
|
if !$('#notify').get(0)
|
||||||
|
$('body').append('<div id="notify"></div>')
|
||||||
|
|
||||||
# map noty naming
|
# map noty naming
|
||||||
if data['type'] is 'info'
|
if data['type'] is 'info'
|
||||||
data['type'] = 'information'
|
data['type'] = 'information'
|
||||||
|
@ -73,7 +77,8 @@ class App.Notify extends App.ControllerWidgetPermanent
|
||||||
$.noty.closeAll()
|
$.noty.closeAll()
|
||||||
if data.link
|
if data.link
|
||||||
data.msg = '<a href="' + data.link + '">' + data.msg + '</a>'
|
data.msg = '<a href="' + data.link + '">' + data.msg + '</a>'
|
||||||
$('#notify').noty
|
|
||||||
|
$('#notify').noty(
|
||||||
text: data.msg
|
text: data.msg
|
||||||
type: data.type
|
type: data.type
|
||||||
template: App.view('notify')
|
template: App.view('notify')
|
||||||
|
@ -83,6 +88,7 @@ class App.Notify extends App.ControllerWidgetPermanent
|
||||||
close: 'animated fadeOutDown'
|
close: 'animated fadeOutDown'
|
||||||
timeout: data.timeout || 3800
|
timeout: data.timeout || 3800
|
||||||
closeWith: ['click']
|
closeWith: ['click']
|
||||||
|
)
|
||||||
|
|
||||||
destroy: (e) ->
|
destroy: (e) ->
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
@ -90,4 +96,4 @@ class App.Notify extends App.ControllerWidgetPermanent
|
||||||
destroyAll: ->
|
destroyAll: ->
|
||||||
$.noty.closeAll()
|
$.noty.closeAll()
|
||||||
|
|
||||||
App.Config.set('notify', App.Notify, 'Widgets')
|
App.Config.set('notify', App.Notify, 'Plugins')
|
|
@ -1,4 +1,4 @@
|
||||||
class Widget extends App.Controller
|
class RemoteTask extends App.Controller
|
||||||
serverRestarted: false
|
serverRestarted: false
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super
|
super
|
||||||
|
@ -12,4 +12,4 @@ class Widget extends App.Controller
|
||||||
'remote_task'
|
'remote_task'
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Config.set('remote_task', Widget, 'Widgets')
|
App.Config.set('remote_task', RemoteTask, 'Plugins')
|
|
@ -1,12 +1,9 @@
|
||||||
class Widget extends App.Controller
|
class SessionTakeOver extends App.Controller
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super
|
super
|
||||||
@bind()
|
|
||||||
|
|
||||||
bind: ->
|
|
||||||
|
|
||||||
# only do takeover check after spool messages are finished
|
# only do takeover check after spool messages are finished
|
||||||
App.Event.bind(
|
@controllerBind(
|
||||||
'spool:sent'
|
'spool:sent'
|
||||||
=>
|
=>
|
||||||
@spoolSent = true
|
@spoolSent = true
|
||||||
|
@ -22,11 +19,10 @@ class Widget extends App.Controller
|
||||||
data:
|
data:
|
||||||
taskbar_id: App.TaskManager.TaskbarId()
|
taskbar_id: App.TaskManager.TaskbarId()
|
||||||
)
|
)
|
||||||
'maintenance'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# session take over message
|
# session take over message
|
||||||
App.Event.bind(
|
@controllerBind(
|
||||||
'session:takeover'
|
'session:takeover'
|
||||||
(data) =>
|
(data) =>
|
||||||
|
|
||||||
|
@ -48,7 +44,6 @@ class Widget extends App.Controller
|
||||||
forceReload: true
|
forceReload: true
|
||||||
)
|
)
|
||||||
@disconnectClient()
|
@disconnectClient()
|
||||||
'maintenance'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Config.set('session_taken_over', Widget, 'Widgets')
|
App.Config.set('session_taken_over', SessionTakeOver, 'Plugins')
|
|
@ -1,20 +1,24 @@
|
||||||
class Widget extends App.ControllerWidgetOnDemand
|
class SwitchBackToUser extends App.Controller
|
||||||
className: 'switchBackToUser'
|
className: 'switchBackToUser'
|
||||||
|
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super
|
super
|
||||||
|
|
||||||
# start widget
|
# start widget
|
||||||
@bind 'app:ready', =>
|
@controllerBind('app:ready', =>
|
||||||
@render()
|
@render()
|
||||||
|
)
|
||||||
|
|
||||||
# e.g. if language has changed
|
# e.g. if language has changed
|
||||||
@bind 'ui:rerender', =>
|
@controllerBind('ui:rerender', =>
|
||||||
@render()
|
@render()
|
||||||
|
)
|
||||||
|
|
||||||
# remove widget
|
# remove widget
|
||||||
@bind 'auth:logout', =>
|
@controllerBind('auth:logout', =>
|
||||||
App.Config.set('switch_back_to_possible', false)
|
App.Config.set('switch_back_to_possible', false)
|
||||||
@render()
|
@render()
|
||||||
|
)
|
||||||
|
|
||||||
render: (user) ->
|
render: (user) ->
|
||||||
|
|
||||||
|
@ -47,4 +51,14 @@ class Widget extends App.ControllerWidgetOnDemand
|
||||||
800
|
800
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Config.set('switch_back_to_user', Widget, 'Widgets')
|
element: =>
|
||||||
|
$("##{@key}")
|
||||||
|
|
||||||
|
html: (raw) =>
|
||||||
|
|
||||||
|
# check if parent exists
|
||||||
|
if !$("##{@key}").get(0)
|
||||||
|
$('#app').before("<div id=\"#{@key}\" class=\"#{@className}\"></div>")
|
||||||
|
$("##{@key}").html raw
|
||||||
|
|
||||||
|
App.Config.set('switch_back_to_user', SwitchBackToUser, 'Plugins')
|
|
@ -1,9 +1,9 @@
|
||||||
class Widget extends App.Controller
|
class TranslationInline extends App.Controller
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super
|
super
|
||||||
@rebind()
|
@rebind()
|
||||||
App.Event.bind('auth', => @rebind())
|
@controllerBind('auth', => @rebind())
|
||||||
App.Event.bind('i18n:inline_translation', => @toogle())
|
@controllerBind('i18n:inline_translation', => @toogle())
|
||||||
|
|
||||||
rebind: =>
|
rebind: =>
|
||||||
$(document).off('keydown.translation')
|
$(document).off('keydown.translation')
|
||||||
|
@ -130,4 +130,4 @@ class Widget extends App.Controller
|
||||||
# rerender controllers
|
# rerender controllers
|
||||||
App.Event.trigger('ui:rerender')
|
App.Event.trigger('ui:rerender')
|
||||||
|
|
||||||
App.Config.set('translation_inline', Widget, 'Widgets')
|
App.Config.set('translation_inline', TranslationInline, 'Plugins')
|
|
@ -24,13 +24,14 @@ class TranslationSupport extends App.Controller
|
||||||
# show message
|
# show message
|
||||||
new Modal(percent: percent)
|
new Modal(percent: percent)
|
||||||
|
|
||||||
@bind 'i18n:language:change', =>
|
@controllerBind('i18n:language:change', =>
|
||||||
@delay(check, 2500, 'translation_support')
|
@delay(check, 2500, 'translation_support')
|
||||||
|
)
|
||||||
@bind 'auth:login', =>
|
@controllerBind('auth:login', =>
|
||||||
@delay(check, 2500, 'translation_support')
|
@delay(check, 2500, 'translation_support')
|
||||||
|
)
|
||||||
|
|
||||||
App.Config.set( 'translaton_support', TranslationSupport, 'Widgets' )
|
App.Config.set( 'translaton_support', TranslationSupport, 'Plugins' )
|
||||||
|
|
||||||
class Modal extends App.ControllerModal
|
class Modal extends App.ControllerModal
|
||||||
buttonClose: true
|
buttonClose: true
|
|
@ -0,0 +1,81 @@
|
||||||
|
class UserSignupCheck extends App.Controller
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
|
||||||
|
# for browser test
|
||||||
|
@controllerBind('user_signup_verify', (user) ->
|
||||||
|
new Modal(user: user)
|
||||||
|
)
|
||||||
|
|
||||||
|
@controllerBind('auth:login', (user) =>
|
||||||
|
return if !user
|
||||||
|
@verifyLater(user.id)
|
||||||
|
)
|
||||||
|
user = App.User.current()
|
||||||
|
@verifyLater(user.id) if user?
|
||||||
|
|
||||||
|
verifyLater: (userId) =>
|
||||||
|
delay = =>
|
||||||
|
@verify(userId)
|
||||||
|
@delay(delay, 5000, 'user_signup_verify_dialog')
|
||||||
|
|
||||||
|
verify: (userId) ->
|
||||||
|
return if !userId
|
||||||
|
return if !App.User.exists(userId)
|
||||||
|
user = App.User.find(userId)
|
||||||
|
return if user.source isnt 'signup'
|
||||||
|
return if user.verified is true
|
||||||
|
currentTime = new Date().getTime()
|
||||||
|
createdAt = Date.parse(user.created_at)
|
||||||
|
diff = currentTime - createdAt
|
||||||
|
max = 1000 * 60 * 30 # show message if account is older then 30 minutes
|
||||||
|
return if diff < max
|
||||||
|
new Modal(user: user)
|
||||||
|
|
||||||
|
class Modal extends App.ControllerModal
|
||||||
|
backdrop: false
|
||||||
|
keyboard: false
|
||||||
|
head: 'Account not verified'
|
||||||
|
small: true
|
||||||
|
buttonClose: false
|
||||||
|
buttonCancel: false
|
||||||
|
buttonSubmit: 'Resend verification email'
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
|
||||||
|
content: =>
|
||||||
|
if !@sent
|
||||||
|
return App.i18n.translateContent('Your account has not been verified. Please click the link in the verification email.')
|
||||||
|
content = App.i18n.translateContent('We\'ve sent an email to _%s_. Click the link in the email to verify your account.', @user.email)
|
||||||
|
content += '<br><br>'
|
||||||
|
content += App.i18n.translateContent('If you don\'t see the email, check other places it might be, like your junk, spam, social, or other folders.')
|
||||||
|
content
|
||||||
|
|
||||||
|
onSubmit: =>
|
||||||
|
@ajax(
|
||||||
|
id: 'email_verify_send'
|
||||||
|
type: 'POST'
|
||||||
|
url: @apiPath + '/users/email_verify_send'
|
||||||
|
data: JSON.stringify(email: @user.email)
|
||||||
|
processData: true
|
||||||
|
success: @success
|
||||||
|
error: @error
|
||||||
|
)
|
||||||
|
|
||||||
|
success: (data) =>
|
||||||
|
@sent = true
|
||||||
|
@update()
|
||||||
|
|
||||||
|
# if in developer mode, redirect to verify
|
||||||
|
if data.token && @Config.get('developer_mode') is true
|
||||||
|
redirect = =>
|
||||||
|
@close()
|
||||||
|
@navigate "#email_verify/#{data.token}"
|
||||||
|
App.Delay.set(redirect, 4000)
|
||||||
|
|
||||||
|
error: =>
|
||||||
|
@contentInline = App.i18n.translateContent('Unable to send verify email.')
|
||||||
|
@update()
|
||||||
|
|
||||||
|
App.Config.set('user_signup', UserSignupCheck, 'Plugins')
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerSubContent
|
class ProfileAvatar extends App.ControllerSubContent
|
||||||
requiredPermission: 'user_preferences.avatar'
|
requiredPermission: 'user_preferences.avatar'
|
||||||
header: 'Avatar'
|
header: 'Avatar'
|
||||||
elements:
|
elements:
|
||||||
|
@ -145,7 +145,7 @@ class Index extends App.ControllerSubContent
|
||||||
|
|
||||||
reader.readAsDataURL(@)
|
reader.readAsDataURL(@)
|
||||||
|
|
||||||
App.Config.set('Avatar', { prio: 1100, name: 'Avatar', parent: '#profile', target: '#profile/avatar', controller: Index, permission: ['user_preferences.avatar'] }, 'NavBarProfile')
|
App.Config.set('Avatar', { prio: 1100, name: 'Avatar', parent: '#profile', target: '#profile/avatar', controller: ProfileAvatar, permission: ['user_preferences.avatar'] }, 'NavBarProfile')
|
||||||
|
|
||||||
class ImageCropper extends App.ControllerModal
|
class ImageCropper extends App.ControllerModal
|
||||||
buttonClose: true
|
buttonClose: true
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class CalendarSubscriptions extends App.ControllerSubContent
|
class ProfileCalendarSubscriptions extends App.ControllerSubContent
|
||||||
requiredPermission: 'user_preferences.calendar+ticket.agent'
|
requiredPermission: 'user_preferences.calendar+ticket.agent'
|
||||||
header: 'Calendar'
|
header: 'Calendar'
|
||||||
elements:
|
elements:
|
||||||
|
@ -90,4 +90,4 @@ class CalendarSubscriptions extends App.ControllerSubContent
|
||||||
msg: App.i18n.translateContent(data.message)
|
msg: App.i18n.translateContent(data.message)
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Config.set('CalendarSubscriptions', { prio: 3000, name: 'Calendar', parent: '#profile', target: '#profile/calendar_subscriptions', permission: ['user_preferences.calendar+ticket.agent'], controller: CalendarSubscriptions }, 'NavBarProfile')
|
App.Config.set('CalendarSubscriptions', { prio: 3000, name: 'Calendar', parent: '#profile', target: '#profile/calendar_subscriptions', permission: ['user_preferences.calendar+ticket.agent'], controller: ProfileCalendarSubscriptions }, 'NavBarProfile')
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerSubContent
|
class ProfileDevices extends App.ControllerSubContent
|
||||||
requiredPermission: 'user_preferences.device'
|
requiredPermission: 'user_preferences.device'
|
||||||
header: 'Devices'
|
header: 'Devices'
|
||||||
events:
|
events:
|
||||||
|
@ -55,4 +55,4 @@ class Index extends App.ControllerSubContent
|
||||||
msg: App.i18n.translateContent(data.message)
|
msg: App.i18n.translateContent(data.message)
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Config.set('Devices', { prio: 3100, name: 'Devices', parent: '#profile', target: '#profile/devices', controller: Index, permission: ['user_preferences.device'] }, 'NavBarProfile')
|
App.Config.set('Devices', { prio: 3100, name: 'Devices', parent: '#profile', target: '#profile/devices', controller: ProfileDevices, permission: ['user_preferences.device'] }, 'NavBarProfile')
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerSubContent
|
class ProfileLanguage extends App.ControllerSubContent
|
||||||
requiredPermission: 'user_preferences.language'
|
requiredPermission: 'user_preferences.language'
|
||||||
header: 'Language'
|
header: 'Language'
|
||||||
events:
|
events:
|
||||||
|
@ -19,7 +19,7 @@ class Index extends App.ControllerSubContent
|
||||||
]
|
]
|
||||||
|
|
||||||
@form = new App.ControllerForm(
|
@form = new App.ControllerForm(
|
||||||
el: html.find('.language_item')
|
el: html.find('.js-language')
|
||||||
model: { configure_attributes: configure_attributes }
|
model: { configure_attributes: configure_attributes }
|
||||||
autofocus: false
|
autofocus: false
|
||||||
)
|
)
|
||||||
|
@ -69,4 +69,4 @@ class Index extends App.ControllerSubContent
|
||||||
msg: App.i18n.translateContent(data.message)
|
msg: App.i18n.translateContent(data.message)
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Config.set('Language', { prio: 1000, name: 'Language', parent: '#profile', target: '#profile/language', controller: Index, permission: ['user_preferences.language'] }, 'NavBarProfile')
|
App.Config.set('Language', { prio: 1000, name: 'Language', parent: '#profile', target: '#profile/language', controller: ProfileLanguage, permission: ['user_preferences.language'] }, 'NavBarProfile')
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerSubContent
|
class ProfileLinkedAccounts extends App.ControllerSubContent
|
||||||
requiredPermission: 'user_preferences.linked_accounts'
|
requiredPermission: 'user_preferences.linked_accounts'
|
||||||
header: 'Linked Accounts'
|
header: 'Linked Accounts'
|
||||||
events:
|
events:
|
||||||
|
@ -59,7 +59,7 @@ class Index extends App.ControllerSubContent
|
||||||
msg: App.i18n.translateContent(data.message)
|
msg: App.i18n.translateContent(data.message)
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Config.set('LinkedAccounts', { prio: 4000, name: 'Linked Accounts', parent: '#profile', target: '#profile/linked', controller: Index, permission: ['user_preferences.linked_accounts'] }, 'NavBarProfile')
|
App.Config.set('LinkedAccounts', { prio: 4000, name: 'Linked Accounts', parent: '#profile', target: '#profile/linked', controller: ProfileLinkedAccounts, permission: ['user_preferences.linked_accounts'] }, 'NavBarProfile')
|
||||||
App.Config.set('auth_provider_all', {
|
App.Config.set('auth_provider_all', {
|
||||||
facebook:
|
facebook:
|
||||||
url: '/auth/facebook'
|
url: '/auth/facebook'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerSubContent
|
class ProfileNotification extends App.ControllerSubContent
|
||||||
requiredPermission: 'user_preferences.notifications+ticket.agent'
|
requiredPermission: 'user_preferences.notifications+ticket.agent'
|
||||||
header: 'Notifications'
|
header: 'Notifications'
|
||||||
events:
|
events:
|
||||||
|
@ -192,4 +192,4 @@ class Index extends App.ControllerSubContent
|
||||||
return if !params.notification_sound.file
|
return if !params.notification_sound.file
|
||||||
App.OnlineNotification.play(params.notification_sound.file)
|
App.OnlineNotification.play(params.notification_sound.file)
|
||||||
|
|
||||||
App.Config.set('Notifications', { prio: 2600, name: 'Notifications', parent: '#profile', target: '#profile/notifications', permission: ['user_preferences.notifications+ticket.agent'], controller: Index }, 'NavBarProfile')
|
App.Config.set('Notifications', { prio: 2600, name: 'Notifications', parent: '#profile', target: '#profile/notifications', permission: ['user_preferences.notifications+ticket.agent'], controller: ProfileNotification }, 'NavBarProfile')
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerSubContent
|
class ProfileOutOfOffice extends App.ControllerSubContent
|
||||||
requiredPermission: 'user_preferences.out_of_office+ticket.agent'
|
requiredPermission: 'user_preferences.out_of_office+ticket.agent'
|
||||||
header: 'Out of Office'
|
header: 'Out of Office'
|
||||||
events:
|
events:
|
||||||
|
@ -161,4 +161,4 @@ class Index extends App.ControllerSubContent
|
||||||
msg: App.i18n.translateContent(message)
|
msg: App.i18n.translateContent(message)
|
||||||
removeAll: true
|
removeAll: true
|
||||||
|
|
||||||
App.Config.set('OutOfOffice', { prio: 2800, name: 'Out of Office', parent: '#profile', target: '#profile/out_of_office', permission: ['user_preferences.out_of_office+ticket.agent'], controller: Index }, 'NavBarProfile')
|
App.Config.set('OutOfOffice', { prio: 2800, name: 'Out of Office', parent: '#profile', target: '#profile/out_of_office', permission: ['user_preferences.out_of_office+ticket.agent'], controller: ProfileOutOfOffice }, 'NavBarProfile')
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerSubContent
|
class ProfilePassword extends App.ControllerSubContent
|
||||||
requiredPermission: 'user_preferences.password'
|
requiredPermission: 'user_preferences.password'
|
||||||
header: 'Password'
|
header: 'Password'
|
||||||
events:
|
events:
|
||||||
|
@ -78,4 +78,4 @@ class Index extends App.ControllerSubContent
|
||||||
removeAll: true
|
removeAll: true
|
||||||
@formEnable( @$('form') )
|
@formEnable( @$('form') )
|
||||||
|
|
||||||
App.Config.set('Password', { prio: 2000, name: 'Password', parent: '#profile', target: '#profile/password', controller: Index, permission: ['user_preferences.password'] }, 'NavBarProfile')
|
App.Config.set('Password', { prio: 2000, name: 'Password', parent: '#profile', target: '#profile/password', controller: ProfilePassword, permission: ['user_preferences.password'] }, 'NavBarProfile')
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerSubContent
|
class ProfileTokenAccess extends App.ControllerSubContent
|
||||||
requiredPermission: 'user_preferences.access_token'
|
requiredPermission: 'user_preferences.access_token'
|
||||||
header: 'Token Access'
|
header: 'Token Access'
|
||||||
events:
|
events:
|
||||||
|
@ -144,4 +144,4 @@ class Create extends App.ControllerModal
|
||||||
msg: App.i18n.translateContent(data.message || data.error)
|
msg: App.i18n.translateContent(data.message || data.error)
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Config.set('Token Access', { prio: 3200, name: 'Token Access', parent: '#profile', target: '#profile/token_access', controller: Index, permission: ['user_preferences.access_token'] }, 'NavBarProfile')
|
App.Config.set('Token Access', { prio: 3200, name: 'Token Access', parent: '#profile', target: '#profile/token_access', controller: ProfileTokenAccess, permission: ['user_preferences.access_token'] }, 'NavBarProfile')
|
||||||
|
|
|
@ -76,19 +76,19 @@ class App.SettingsForm extends App.Controller
|
||||||
ui.formEnable(e)
|
ui.formEnable(e)
|
||||||
count -= 1
|
count -= 1
|
||||||
if count == 0
|
if count == 0
|
||||||
App.Event.trigger 'notify', {
|
App.Event.trigger('notify', {
|
||||||
type: 'success'
|
type: 'success'
|
||||||
msg: App.i18n.translateContent('Update successful!')
|
msg: App.i18n.translateContent('Update successful!')
|
||||||
timeout: 2000
|
timeout: 2000
|
||||||
}
|
})
|
||||||
|
|
||||||
# rerender ui || get new collections and session data
|
# rerender ui || get new collections and session data
|
||||||
App.Setting.preferencesPost(@)
|
App.Setting.preferencesPost(@)
|
||||||
|
|
||||||
fail: (settings, details) ->
|
fail: (settings, details) ->
|
||||||
App.Event.trigger 'notify', {
|
App.Event.trigger('notify', {
|
||||||
type: 'error'
|
type: 'error'
|
||||||
msg: App.i18n.translateContent(details.error_human || details.error || 'Unable to update object!')
|
msg: App.i18n.translateContent(details.error_human || details.error || 'Unable to update object!')
|
||||||
timeout: 2000
|
timeout: 2000
|
||||||
}
|
})
|
||||||
)
|
)
|
||||||
|
|
|
@ -494,7 +494,6 @@ class App.UiElement.ticket_perform_action
|
||||||
elementRow.find('.js-setArticle').empty()
|
elementRow.find('.js-setArticle').empty()
|
||||||
|
|
||||||
name = "#{attribute.name}::article.#{articleType}"
|
name = "#{attribute.name}::article.#{articleType}"
|
||||||
console.log('meta', meta)
|
|
||||||
selection = App.UiElement.select.render(
|
selection = App.UiElement.select.render(
|
||||||
name: "#{name}::internal"
|
name: "#{name}::internal"
|
||||||
multiple: false
|
multiple: false
|
||||||
|
|
|
@ -84,8 +84,6 @@ class App.UiElement.user_permission
|
||||||
input = $(@).find('input')
|
input = $(@).find('input')
|
||||||
upcoming_state = !input.prop('checked')
|
upcoming_state = !input.prop('checked')
|
||||||
value = input.val()
|
value = input.val()
|
||||||
console.log(upcoming_state)
|
|
||||||
console.log(value)
|
|
||||||
|
|
||||||
if value is 'full' and upcoming_state is true
|
if value is 'full' and upcoming_state is true
|
||||||
$(@).closest('tr').find('input:not([value=full])').prop('checked', false)
|
$(@).closest('tr').find('input:not([value=full])').prop('checked', false)
|
||||||
|
|
|
@ -54,14 +54,14 @@ class App.TicketCreate extends App.Controller
|
||||||
@bindId = App.TicketCreateCollection.one(load)
|
@bindId = App.TicketCreateCollection.one(load)
|
||||||
|
|
||||||
# rerender view, e. g. on langauge change
|
# rerender view, e. g. on langauge change
|
||||||
@bind('ui:rerender', =>
|
@controllerBind('ui:rerender', =>
|
||||||
return if !@authenticateCheck()
|
return if !@authenticateCheck()
|
||||||
@renderQueue()
|
@renderQueue()
|
||||||
@tokanice()
|
@tokanice()
|
||||||
)
|
)
|
||||||
|
|
||||||
# listen to rerender sidebars
|
# listen to rerender sidebars
|
||||||
@bind('ui::ticket::sidebarRerender', (data) =>
|
@controllerBind('ui::ticket::sidebarRerender', (data) =>
|
||||||
return if data.taskKey isnt @taskKey
|
return if data.taskKey isnt @taskKey
|
||||||
return if !@sidebarWidget
|
return if !@sidebarWidget
|
||||||
@sidebarWidget.render(@params())
|
@sidebarWidget.render(@params())
|
||||||
|
@ -169,11 +169,11 @@ class App.TicketCreate extends App.Controller
|
||||||
show: =>
|
show: =>
|
||||||
@navupdate("#ticket/create/id/#{@id}#{@split}", type: 'menu')
|
@navupdate("#ticket/create/id/#{@id}#{@split}", type: 'menu')
|
||||||
@autosaveStart()
|
@autosaveStart()
|
||||||
@bind('ticket_create_rerender', (template) => @renderQueue(template))
|
@controllerBind('ticket_create_rerender', (template) => @renderQueue(template))
|
||||||
|
|
||||||
hide: =>
|
hide: =>
|
||||||
@autosaveStop()
|
@autosaveStop()
|
||||||
@unbind('ticket_create_rerender', (template) => @renderQueue(template))
|
@controllerUnbind('ticket_create_rerender', (template) => @renderQueue(template))
|
||||||
|
|
||||||
changed: =>
|
changed: =>
|
||||||
formCurrent = @formParam( @$('.ticket-create') )
|
formCurrent = @formParam( @$('.ticket-create') )
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerSubContent
|
class Api extends App.ControllerSubContent
|
||||||
requiredPermission: 'admin.api'
|
requiredPermission: 'admin.api'
|
||||||
header: 'API'
|
header: 'API'
|
||||||
events:
|
events:
|
||||||
|
@ -193,4 +193,4 @@ class ViewAppTokenModal extends App.ControllerModal
|
||||||
@$('.js-submit').remove()
|
@$('.js-submit').remove()
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Config.set('API', { prio: 1200, name: 'API', parent: '#system', target: '#system/api', controller: Index, permission: ['admin.api'] }, 'NavBarAdmin')
|
App.Config.set('API', { prio: 1200, name: 'API', parent: '#system', target: '#system/api', controller: Api, permission: ['admin.api'] }, 'NavBarAdmin')
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerSubContent
|
class Calendar extends App.ControllerSubContent
|
||||||
requiredPermission: 'admin.calendar'
|
requiredPermission: 'admin.calendar'
|
||||||
header: 'Calendars'
|
header: 'Calendars'
|
||||||
events:
|
events:
|
||||||
|
@ -121,4 +121,4 @@ class Index extends App.ControllerSubContent
|
||||||
container: @el.closest('.content')
|
container: @el.closest('.content')
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Config.set('Calendars', { prio: 2400, name: 'Calendars', parent: '#manage', target: '#manage/calendars', controller: Index, permission: ['admin.calendar'] }, 'NavBarAdmin')
|
App.Config.set('Calendars', { prio: 2400, name: 'Calendars', parent: '#manage', target: '#manage/calendars', controller: Calendar, permission: ['admin.calendar'] }, 'NavBarAdmin')
|
||||||
|
|
|
@ -42,7 +42,7 @@ class App.CustomerChat extends App.Controller
|
||||||
@on('layout-has-changed', @propagateLayoutChange)
|
@on('layout-has-changed', @propagateLayoutChange)
|
||||||
|
|
||||||
# update navbar on new status
|
# update navbar on new status
|
||||||
@bind('chat_status_agent', (data) =>
|
@controllerBind('chat_status_agent', (data) =>
|
||||||
if data.assets
|
if data.assets
|
||||||
App.Collection.loadAssets(data.assets)
|
App.Collection.loadAssets(data.assets)
|
||||||
@meta = data
|
@meta = data
|
||||||
|
@ -52,19 +52,19 @@ class App.CustomerChat extends App.Controller
|
||||||
)
|
)
|
||||||
|
|
||||||
# add new chat window
|
# add new chat window
|
||||||
@bind('chat_session_start', (data) =>
|
@controllerBind('chat_session_start', (data) =>
|
||||||
if data.session
|
if data.session
|
||||||
@addChat(data.session)
|
@addChat(data.session)
|
||||||
)
|
)
|
||||||
|
|
||||||
# on new login or on
|
# on new login or on
|
||||||
@bind('ws:login chat_agent_state', ->
|
@controllerBind('ws:login chat_agent_state', ->
|
||||||
App.WebSocket.send(event:'chat_status_agent')
|
App.WebSocket.send(event:'chat_status_agent')
|
||||||
)
|
)
|
||||||
App.WebSocket.send(event:'chat_status_agent')
|
App.WebSocket.send(event:'chat_status_agent')
|
||||||
|
|
||||||
# rerender view, e. g. on langauge change
|
# rerender view, e. g. on langauge change
|
||||||
@bind('ui:rerender chat:rerender', =>
|
@controllerBind('ui:rerender chat:rerender', =>
|
||||||
return if !@authenticateCheck()
|
return if !@authenticateCheck()
|
||||||
for session_id, chat of @chatWindows
|
for session_id, chat of @chatWindows
|
||||||
chat.el.remove()
|
chat.el.remove()
|
||||||
|
@ -122,8 +122,8 @@ class App.CustomerChat extends App.Controller
|
||||||
|
|
||||||
|
|
||||||
show: (params) =>
|
show: (params) =>
|
||||||
@title 'Customer Chat', true
|
@title('Customer Chat', true)
|
||||||
@navupdate '#customer_chat'
|
@navupdate('#customer_chat')
|
||||||
|
|
||||||
if params.session_id
|
if params.session_id
|
||||||
callback = (session) =>
|
callback = (session) =>
|
||||||
|
@ -433,34 +433,34 @@ class ChatWindow extends App.Controller
|
||||||
|
|
||||||
@on('layout-change', @onLayoutChange)
|
@on('layout-change', @onLayoutChange)
|
||||||
|
|
||||||
@bind('chat_session_typing', (data) =>
|
@controllerBind('chat_session_typing', (data) =>
|
||||||
return if data.session_id isnt @session.session_id
|
return if data.session_id isnt @session.session_id
|
||||||
return if data.self_written
|
return if data.self_written
|
||||||
@showWritingLoader()
|
@showWritingLoader()
|
||||||
)
|
)
|
||||||
@bind('chat_session_message', (data) =>
|
@controllerBind('chat_session_message', (data) =>
|
||||||
return if data.session_id isnt @session.session_id
|
return if data.session_id isnt @session.session_id
|
||||||
return if data.self_written
|
return if data.self_written
|
||||||
@receiveMessage(data.message.content)
|
@receiveMessage(data.message.content)
|
||||||
)
|
)
|
||||||
@bind('chat_session_notice', (data) =>
|
@controllerBind('chat_session_notice', (data) =>
|
||||||
return if data.session_id isnt @session.session_id
|
return if data.session_id isnt @session.session_id
|
||||||
return if data.self_written
|
return if data.self_written
|
||||||
@addNoticeMessage(data.message)
|
@addNoticeMessage(data.message)
|
||||||
)
|
)
|
||||||
@bind('chat_session_left', (data) =>
|
@controllerBind('chat_session_left', (data) =>
|
||||||
return if data.session_id isnt @session.session_id
|
return if data.session_id isnt @session.session_id
|
||||||
return if data.self_written
|
return if data.self_written
|
||||||
@addStatusMessage("<strong>#{data.realname}</strong> left the conversation")
|
@addStatusMessage("<strong>#{data.realname}</strong> left the conversation")
|
||||||
@goOffline()
|
@goOffline()
|
||||||
)
|
)
|
||||||
@bind('chat_session_closed', (data) =>
|
@controllerBind('chat_session_closed', (data) =>
|
||||||
return if data.session_id isnt @session.session_id
|
return if data.session_id isnt @session.session_id
|
||||||
return if data.self_written
|
return if data.self_written
|
||||||
@addStatusMessage("<strong>#{data.realname}</strong> closed the conversation")
|
@addStatusMessage("<strong>#{data.realname}</strong> closed the conversation")
|
||||||
@goOffline()
|
@goOffline()
|
||||||
)
|
)
|
||||||
@bind('chat_focus', (data) =>
|
@controllerBind('chat_focus', (data) =>
|
||||||
return if data.session_id isnt @session.session_id
|
return if data.session_id isnt @session.session_id
|
||||||
@focus()
|
@focus()
|
||||||
)
|
)
|
||||||
|
@ -572,7 +572,7 @@ class ChatWindow extends App.Controller
|
||||||
onTransitionend: (event) =>
|
onTransitionend: (event) =>
|
||||||
# chat window is done with animation - adjust scroll-bars
|
# chat window is done with animation - adjust scroll-bars
|
||||||
# of sibling chat windows
|
# of sibling chat windows
|
||||||
@trigger 'layout-has-changed'
|
@trigger('layout-has-changed')
|
||||||
|
|
||||||
if event.data and event.data.callback
|
if event.data and event.data.callback
|
||||||
event.data.callback()
|
event.data.callback()
|
||||||
|
@ -601,7 +601,7 @@ class ChatWindow extends App.Controller
|
||||||
@removeCallback(@session.session_id)
|
@removeCallback(@session.session_id)
|
||||||
|
|
||||||
release: =>
|
release: =>
|
||||||
@trigger 'closed'
|
@trigger('closed')
|
||||||
@el.remove()
|
@el.remove()
|
||||||
super
|
super
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.Controller
|
class Clues extends App.Controller
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super
|
super
|
||||||
@navupdate '#', true
|
@navupdate '#', true
|
||||||
|
@ -6,7 +6,7 @@ class Index extends App.Controller
|
||||||
|
|
||||||
clues: =>
|
clues: =>
|
||||||
new App.FirstStepsClues(
|
new App.FirstStepsClues(
|
||||||
el: @el
|
appEl: @appEl
|
||||||
onComplete: =>
|
onComplete: =>
|
||||||
App.Ajax.request(
|
App.Ajax.request(
|
||||||
id: 'preferences'
|
id: 'preferences'
|
||||||
|
@ -18,4 +18,4 @@ class Index extends App.Controller
|
||||||
@navigate '#'
|
@navigate '#'
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Config.set('clues', Index, 'Routes')
|
App.Config.set('clues', Clues, 'Routes')
|
||||||
|
|
|
@ -23,13 +23,13 @@ class App.CTI extends App.Controller
|
||||||
@meta.active = preferences.cti || false
|
@meta.active = preferences.cti || false
|
||||||
|
|
||||||
@load()
|
@load()
|
||||||
@bind('cti_list_push', (data) =>
|
@controllerBind('cti_list_push', (data) =>
|
||||||
delay = =>
|
delay = =>
|
||||||
@load()
|
@load()
|
||||||
@delay(delay, 500, 'cti_list_push_render')
|
@delay(delay, 500, 'cti_list_push_render')
|
||||||
'cti_list_push'
|
'cti_list_push'
|
||||||
)
|
)
|
||||||
@bind('cti_event', (data) =>
|
@controllerBind('cti_event', (data) =>
|
||||||
return if data.state isnt 'newCall'
|
return if data.state isnt 'newCall'
|
||||||
return if data.direction isnt 'in'
|
return if data.direction isnt 'in'
|
||||||
return if @switch() isnt true
|
return if @switch() isnt true
|
||||||
|
@ -37,7 +37,7 @@ class App.CTI extends App.Controller
|
||||||
@notify(data)
|
@notify(data)
|
||||||
'cti_event'
|
'cti_event'
|
||||||
)
|
)
|
||||||
@bind('menu:render', (data) =>
|
@controllerBind('menu:render', (data) =>
|
||||||
return if @switch() isnt true
|
return if @switch() isnt true
|
||||||
localHtml = ''
|
localHtml = ''
|
||||||
for item in @ringingCalls()
|
for item in @ringingCalls()
|
||||||
|
@ -53,26 +53,25 @@ class App.CTI extends App.Controller
|
||||||
user_id = $(e.currentTarget).data('user-id')
|
user_id = $(e.currentTarget).data('user-id')
|
||||||
if user_id
|
if user_id
|
||||||
user = App.User.find(user_id)
|
user = App.User.find(user_id)
|
||||||
console.log('user_id', user_id, user)
|
|
||||||
@newTicket(user)
|
@newTicket(user)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@bind('auth', (data) =>
|
@controllerBind('auth', (data) =>
|
||||||
@meta.counter = 0
|
@meta.counter = 0
|
||||||
)
|
)
|
||||||
@bind('cti:reload', =>
|
@controllerBind('cti:reload', =>
|
||||||
@load()
|
@load()
|
||||||
'cti_reload'
|
'cti_reload'
|
||||||
)
|
)
|
||||||
|
|
||||||
# rerender view, e. g. on langauge change
|
# rerender view, e. g. on langauge change
|
||||||
@bind('ui:rerender', =>
|
@controllerBind('ui:rerender', =>
|
||||||
@render()
|
@render()
|
||||||
'cti_rerender'
|
'cti_rerender'
|
||||||
)
|
)
|
||||||
|
|
||||||
# after a new websocket connection, load again
|
# after a new websocket connection, load again
|
||||||
@bind('spool:sent', =>
|
@controllerBind('spool:sent', =>
|
||||||
if @initSpoolSent
|
if @initSpoolSent
|
||||||
@load()
|
@load()
|
||||||
return
|
return
|
||||||
|
@ -280,7 +279,7 @@ class App.CTI extends App.Controller
|
||||||
currentPosition: =>
|
currentPosition: =>
|
||||||
@$('.main').scrollTop()
|
@$('.main').scrollTop()
|
||||||
|
|
||||||
class WidgetAvatar extends App.ObserverController
|
class WidgetAvatar extends App.ControllerObserver
|
||||||
@extend App.PopoverProvidable
|
@extend App.PopoverProvidable
|
||||||
@registerPopovers 'User'
|
@registerPopovers 'User'
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.ControllerContent
|
class CustomerTicketCreate extends App.ControllerAppContent
|
||||||
requiredPermission: 'ticket.customer'
|
requiredPermission: 'ticket.customer'
|
||||||
events:
|
events:
|
||||||
'submit form': 'submit',
|
'submit form': 'submit',
|
||||||
|
@ -211,7 +211,7 @@ class Index extends App.ControllerContent
|
||||||
return
|
return
|
||||||
@formEnable(@$('.js-submit'), 'button')
|
@formEnable(@$('.js-submit'), 'button')
|
||||||
|
|
||||||
App.Config.set('customer_ticket_new', Index, 'Routes')
|
App.Config.set('customer_ticket_new', CustomerTicketCreate, 'Routes')
|
||||||
App.Config.set('CustomerTicketNew', {
|
App.Config.set('CustomerTicketNew', {
|
||||||
prio: 8003,
|
prio: 8003,
|
||||||
parent: '#new',
|
parent: '#new',
|
||||||
|
|
|
@ -15,9 +15,10 @@ class App.Dashboard extends App.Controller
|
||||||
@render()
|
@render()
|
||||||
|
|
||||||
# rerender view, e. g. on language change
|
# rerender view, e. g. on language change
|
||||||
@bind 'ui:rerender', =>
|
@controllerBind('ui:rerender', =>
|
||||||
return if !@authenticateCheck()
|
return if !@authenticateCheck()
|
||||||
@render()
|
@render()
|
||||||
|
)
|
||||||
|
|
||||||
@mayBeClues()
|
@mayBeClues()
|
||||||
|
|
||||||
|
@ -71,12 +72,12 @@ class App.Dashboard extends App.Controller
|
||||||
|
|
||||||
# incase of being only customer, redirect to default router
|
# incase of being only customer, redirect to default router
|
||||||
if @permissionCheck('ticket.customer') && !@permissionCheck('ticket.agent')
|
if @permissionCheck('ticket.customer') && !@permissionCheck('ticket.agent')
|
||||||
@navigate '#ticket/view', true
|
@navigate '#ticket/view', { hideCurrentLocationFromHistory: true }
|
||||||
return
|
return
|
||||||
|
|
||||||
# incase of being only admin, redirect to admin interface (show no empty white content page)
|
# incase of being only admin, redirect to admin interface (show no empty white content page)
|
||||||
if !@permissionCheck('ticket.customer') && !@permissionCheck('ticket.agent') && @permissionCheck('admin')
|
if !@permissionCheck('ticket.customer') && !@permissionCheck('ticket.agent') && @permissionCheck('admin')
|
||||||
@navigate '#manage', true
|
@navigate '#manage', { hideCurrentLocationFromHistory: true }
|
||||||
return
|
return
|
||||||
|
|
||||||
# set title
|
# set title
|
||||||
|
|
|
@ -9,19 +9,19 @@ class DefaultRouter extends App.Controller
|
||||||
|
|
||||||
# check if import is active
|
# check if import is active
|
||||||
if !@Config.get('system_init_done') && @Config.get('import_mode')
|
if !@Config.get('system_init_done') && @Config.get('import_mode')
|
||||||
@navigate '#import', true
|
@navigate '#import', { hideCurrentLocationFromHistory: true }
|
||||||
return
|
return
|
||||||
|
|
||||||
# route to getting started screen
|
# route to getting started screen
|
||||||
if !@Config.get('system_init_done')
|
if !@Config.get('system_init_done')
|
||||||
@navigate '#getting_started', true
|
@navigate '#getting_started', { hideCurrentLocationFromHistory: true }
|
||||||
return
|
return
|
||||||
|
|
||||||
if @Config.get('default_controller')
|
if @Config.get('default_controller')
|
||||||
@navigate @Config.get('default_controller'), true
|
@navigate @Config.get('default_controller'), { hideCurrentLocationFromHistory: true }
|
||||||
return
|
return
|
||||||
|
|
||||||
@navigate '#dashboard', true
|
@navigate '#dashboard', { hideCurrentLocationFromHistory: true }
|
||||||
|
|
||||||
App.Config.set('', DefaultRouter, 'Routes')
|
App.Config.set('', DefaultRouter, 'Routes')
|
||||||
App.Config.set('/', DefaultRouter, 'Routes')
|
App.Config.set('/', DefaultRouter, 'Routes')
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Index extends App.Controller
|
class EmailVerify extends App.Controller
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super
|
super
|
||||||
@verifyCall()
|
@verifyCall()
|
||||||
|
@ -10,23 +10,47 @@ class Index extends App.Controller
|
||||||
url: "#{@apiPath}/users/email_verify"
|
url: "#{@apiPath}/users/email_verify"
|
||||||
data: JSON.stringify(token: @token)
|
data: JSON.stringify(token: @token)
|
||||||
processData: true
|
processData: true
|
||||||
success: (data, status, xhr) =>
|
success: @success
|
||||||
App.Auth.loginCheck()
|
error: @error
|
||||||
@navigate '#'
|
|
||||||
|
|
||||||
@notify
|
|
||||||
type: 'success'
|
|
||||||
msg: App.i18n.translateContent('Woo hoo! Your email address has been verified!')
|
|
||||||
removeAll: true
|
|
||||||
timeout: 2000
|
|
||||||
|
|
||||||
error: (data, status, xhr) =>
|
|
||||||
@navigate '#'
|
|
||||||
|
|
||||||
@notify
|
|
||||||
type: 'error'
|
|
||||||
msg: App.i18n.translateContent('Unable to verify email. Please contact your administrator.')
|
|
||||||
removeAll: true
|
|
||||||
)
|
)
|
||||||
|
|
||||||
App.Config.set('email_verify/:token', Index, 'Routes')
|
success: =>
|
||||||
|
new Success(el: @el, appEl: @appEl)
|
||||||
|
|
||||||
|
error: =>
|
||||||
|
new Fail(el: @el, appEl: @appEl)
|
||||||
|
|
||||||
|
class Success extends App.ControllerAppContent
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
@render()
|
||||||
|
|
||||||
|
# rerender view, e. g. on language change
|
||||||
|
@controllerBind('ui:rerender', =>
|
||||||
|
@render()
|
||||||
|
)
|
||||||
|
|
||||||
|
render: =>
|
||||||
|
@renderScreenSuccess(
|
||||||
|
detail: 'Woo hoo! Your email address has been verified!'
|
||||||
|
)
|
||||||
|
delay = =>
|
||||||
|
@navigate '#'
|
||||||
|
@delay(delay, 2000)
|
||||||
|
|
||||||
|
class Fail extends App.ControllerAppContent
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
@render()
|
||||||
|
|
||||||
|
# rerender view, e. g. on language change
|
||||||
|
@controllerBind('ui:rerender', =>
|
||||||
|
@render()
|
||||||
|
)
|
||||||
|
|
||||||
|
render: =>
|
||||||
|
@renderScreenError(
|
||||||
|
detail: 'Unable to verify email. Please contact your administrator.'
|
||||||
|
)
|
||||||
|
|
||||||
|
App.Config.set('email_verify/:token', EmailVerify, 'Routes')
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,112 @@
|
||||||
|
class GettingStartedAdmin extends App.ControllerWizardFullScreen
|
||||||
|
events:
|
||||||
|
'submit form': 'submit'
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
|
||||||
|
if @authenticateCheck() && !@permissionCheck('admin.wizard')
|
||||||
|
@navigate '#'
|
||||||
|
return
|
||||||
|
|
||||||
|
# set title
|
||||||
|
@title 'Create Admin'
|
||||||
|
|
||||||
|
# redirect to login if master user already exists
|
||||||
|
if @Config.get('system_init_done')
|
||||||
|
@navigate '#login'
|
||||||
|
return
|
||||||
|
|
||||||
|
@fetch()
|
||||||
|
|
||||||
|
fetch: ->
|
||||||
|
|
||||||
|
# get data
|
||||||
|
@ajax(
|
||||||
|
id: 'getting_started'
|
||||||
|
type: 'GET'
|
||||||
|
url: "#{@apiPath}/getting_started"
|
||||||
|
processData: true
|
||||||
|
success: (data, status, xhr) =>
|
||||||
|
|
||||||
|
# check if user got created right now
|
||||||
|
#if true
|
||||||
|
# @navigate '#getting_started/base', { emptyEl: true }
|
||||||
|
# return
|
||||||
|
|
||||||
|
# check if import is active
|
||||||
|
if data.import_mode == true
|
||||||
|
@navigate "#import/#{data.import_backend}", { emptyEl: true }
|
||||||
|
return
|
||||||
|
|
||||||
|
# load group collection
|
||||||
|
App.Collection.load(type: 'Group', data: data.groups)
|
||||||
|
|
||||||
|
# render page
|
||||||
|
@render()
|
||||||
|
)
|
||||||
|
|
||||||
|
render: ->
|
||||||
|
|
||||||
|
@replaceWith(App.view('getting_started/admin')())
|
||||||
|
|
||||||
|
@form = new App.ControllerForm(
|
||||||
|
el: @$('.js-admin-form')
|
||||||
|
model: App.User
|
||||||
|
screen: 'signup'
|
||||||
|
autofocus: true
|
||||||
|
)
|
||||||
|
|
||||||
|
submit: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
@formDisable(e)
|
||||||
|
@params = @formParam(e.target)
|
||||||
|
@params.role_ids = []
|
||||||
|
|
||||||
|
user = new App.User
|
||||||
|
user.load(@params)
|
||||||
|
|
||||||
|
errors = user.validate(
|
||||||
|
screen: 'signup'
|
||||||
|
)
|
||||||
|
if errors
|
||||||
|
@log 'error new', errors
|
||||||
|
|
||||||
|
# Only highlight, but don't add message. Error text breaks layout.
|
||||||
|
Object.keys(errors).forEach (key) ->
|
||||||
|
errors[key] = null
|
||||||
|
|
||||||
|
@formValidate(form: e.target, errors: errors)
|
||||||
|
@formEnable(e)
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
@formValidate(form: e.target, errors: errors)
|
||||||
|
|
||||||
|
# save user
|
||||||
|
user.save(
|
||||||
|
done: (r) =>
|
||||||
|
App.Auth.login(
|
||||||
|
data:
|
||||||
|
username: @params.email
|
||||||
|
password: @params.password
|
||||||
|
success: @relogin
|
||||||
|
error: ->
|
||||||
|
App.Event.trigger('notify', {
|
||||||
|
type: 'error'
|
||||||
|
msg: App.i18n.translateContent('Signin failed! Please contact the support team!')
|
||||||
|
timeout: 2500
|
||||||
|
})
|
||||||
|
)
|
||||||
|
@Config.set('system_init_done', true)
|
||||||
|
|
||||||
|
fail: (settings, details) =>
|
||||||
|
@formEnable(e)
|
||||||
|
@form.showAlert(details.error_human || details.error || 'Unable to create user!')
|
||||||
|
)
|
||||||
|
|
||||||
|
relogin: (data, status, xhr) =>
|
||||||
|
@log 'notice', 'relogin:success', data
|
||||||
|
App.Event.trigger('notify:removeall')
|
||||||
|
@navigate('getting_started/base', { emptyEl: true })
|
||||||
|
|
||||||
|
App.Config.set('getting_started/admin', GettingStartedAdmin, 'Routes')
|
|
@ -0,0 +1,89 @@
|
||||||
|
class GettingStartedAgent extends App.ControllerWizardFullScreen
|
||||||
|
events:
|
||||||
|
'submit form': 'submit'
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
@authenticateCheckRedirect()
|
||||||
|
|
||||||
|
# set title
|
||||||
|
@title 'Invite Agents'
|
||||||
|
@fetch()
|
||||||
|
|
||||||
|
fetch: ->
|
||||||
|
|
||||||
|
# get data
|
||||||
|
@ajax(
|
||||||
|
id: 'getting_started'
|
||||||
|
type: 'GET'
|
||||||
|
url: "#{@apiPath}/getting_started"
|
||||||
|
processData: true
|
||||||
|
success: (data, status, xhr) =>
|
||||||
|
|
||||||
|
# check if import is active
|
||||||
|
if data.import_mode == true
|
||||||
|
@navigate "#import/#{data.import_backend}", { emptyEl: true }
|
||||||
|
return
|
||||||
|
|
||||||
|
# load group collection
|
||||||
|
App.Collection.load(type: 'Group', data: data.groups)
|
||||||
|
|
||||||
|
# render page
|
||||||
|
@render()
|
||||||
|
)
|
||||||
|
|
||||||
|
render: ->
|
||||||
|
|
||||||
|
@replaceWith App.view('getting_started/agent')()
|
||||||
|
|
||||||
|
@form = new App.ControllerForm(
|
||||||
|
el: @$('.js-agent-form')
|
||||||
|
model: App.User
|
||||||
|
screen: 'invite_agent'
|
||||||
|
autofocus: true
|
||||||
|
)
|
||||||
|
|
||||||
|
submit: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
@formDisable(e)
|
||||||
|
@params = @formParam(e.target)
|
||||||
|
@params.role_ids = []
|
||||||
|
|
||||||
|
# set invite flag
|
||||||
|
@params.invite = true
|
||||||
|
|
||||||
|
# find agent role
|
||||||
|
role = App.Role.findByAttribute('name', 'Agent')
|
||||||
|
if role
|
||||||
|
@params.role_ids = role.id
|
||||||
|
|
||||||
|
user = new App.User
|
||||||
|
user.load(@params)
|
||||||
|
|
||||||
|
errors = user.validate(
|
||||||
|
screen: 'invite_agent'
|
||||||
|
)
|
||||||
|
if errors
|
||||||
|
@log 'error new', errors
|
||||||
|
@formValidate(form: e.target, errors: errors)
|
||||||
|
@formEnable(e)
|
||||||
|
return false
|
||||||
|
|
||||||
|
# save user
|
||||||
|
user.save(
|
||||||
|
done: (r) =>
|
||||||
|
App.Event.trigger('notify', {
|
||||||
|
type: 'success'
|
||||||
|
msg: App.i18n.translateContent('Invitation sent!')
|
||||||
|
timeout: 3500
|
||||||
|
})
|
||||||
|
|
||||||
|
# rerender page
|
||||||
|
@render()
|
||||||
|
|
||||||
|
fail: (settings, details) =>
|
||||||
|
@formEnable(e)
|
||||||
|
@form.showAlert(details.error_human || 'Can\'t create user!')
|
||||||
|
)
|
||||||
|
|
||||||
|
App.Config.set('getting_started/agents', GettingStartedAgent, 'Routes')
|
|
@ -0,0 +1,65 @@
|
||||||
|
class GettingStartedAutoWizard extends App.ControllerWizardFullScreen
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
|
||||||
|
# if already logged in, got to #
|
||||||
|
if @authenticateCheck() && !@permissionCheck('admin.wizard')
|
||||||
|
@navigate '#'
|
||||||
|
return
|
||||||
|
|
||||||
|
# redirect to login if master user already exists
|
||||||
|
if @Config.get('system_init_done')
|
||||||
|
@navigate '#login'
|
||||||
|
return
|
||||||
|
|
||||||
|
# set title
|
||||||
|
@title 'Auto Wizard'
|
||||||
|
@renderSplash()
|
||||||
|
@fetch()
|
||||||
|
|
||||||
|
fetch: ->
|
||||||
|
|
||||||
|
url = "#{@apiPath}/getting_started/auto_wizard"
|
||||||
|
if @token
|
||||||
|
url += "/#{@token}"
|
||||||
|
|
||||||
|
# get data
|
||||||
|
@ajax(
|
||||||
|
id: 'auto_wizard'
|
||||||
|
type: 'GET'
|
||||||
|
url: url
|
||||||
|
processData: true
|
||||||
|
success: (data, status, xhr) =>
|
||||||
|
|
||||||
|
# check if auto wizard enabled
|
||||||
|
if data.auto_wizard is false
|
||||||
|
@redirectToLogin()
|
||||||
|
return
|
||||||
|
|
||||||
|
# auto wizard setup was successful
|
||||||
|
if data.auto_wizard_success is true
|
||||||
|
@delay(@redirectToLogin, 800)
|
||||||
|
return
|
||||||
|
|
||||||
|
if data.auto_wizard_success is false
|
||||||
|
if data.message
|
||||||
|
@renderFailed(data)
|
||||||
|
else
|
||||||
|
@renderToken()
|
||||||
|
return
|
||||||
|
|
||||||
|
# redirect to login if master user already exists
|
||||||
|
@redirectToLogin()
|
||||||
|
)
|
||||||
|
|
||||||
|
renderFailed: (data) ->
|
||||||
|
@replaceWith App.view('getting_started/auto_wizard_failed')(data)
|
||||||
|
|
||||||
|
renderSplash: ->
|
||||||
|
@replaceWith App.view('getting_started/auto_wizard_splash')()
|
||||||
|
|
||||||
|
renderToken: ->
|
||||||
|
@replaceWith App.view('getting_started/auto_wizard_enabled')()
|
||||||
|
|
||||||
|
App.Config.set('getting_started/auto_wizard', GettingStartedAutoWizard, 'Routes')
|
||||||
|
App.Config.set('getting_started/auto_wizard/:token', GettingStartedAutoWizard, 'Routes')
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue