')
+ @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()
diff --git a/app/assets/javascripts/app/controllers/_application_controller/observer.coffee b/app/assets/javascripts/app/controllers/_application_controller/observer.coffee
new file mode 100644
index 000000000..293c02528
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/_application_controller/observer.coffee
@@ -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)
diff --git a/app/assets/javascripts/app/controllers/_application_controller/observer_action_row.coffee b/app/assets/javascripts/app/controllers/_application_controller/observer_action_row.coffee
new file mode 100644
index 000000000..a93e1ad30
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/_application_controller/observer_action_row.coffee
@@ -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)
+ )
diff --git a/app/assets/javascripts/app/controllers/_application_controller/permanent.coffee b/app/assets/javascripts/app/controllers/_application_controller/permanent.coffee
new file mode 100644
index 000000000..20349bbe8
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/_application_controller/permanent.coffee
@@ -0,0 +1,5 @@
+class App.ControllerPermanent extends App.Controller
+ constructor: ->
+ if @requiredPermission
+ @permissionCheckRedirect(@requiredPermission, true)
+ super
\ No newline at end of file
diff --git a/app/assets/javascripts/app/controllers/_application_controller_reorder_modal.coffee b/app/assets/javascripts/app/controllers/_application_controller/reorder_modal.coffee
similarity index 100%
rename from app/assets/javascripts/app/controllers/_application_controller_reorder_modal.coffee
rename to app/assets/javascripts/app/controllers/_application_controller/reorder_modal.coffee
diff --git a/app/assets/javascripts/app/controllers/_application_controller/sub_content.coffee b/app/assets/javascripts/app/controllers/_application_controller/sub_content.coffee
new file mode 100644
index 000000000..c297a9c83
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/_application_controller/sub_content.coffee
@@ -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()
\ No newline at end of file
diff --git a/app/assets/javascripts/app/controllers/_application_controller_table.coffee b/app/assets/javascripts/app/controllers/_application_controller/table.coffee
similarity index 100%
rename from app/assets/javascripts/app/controllers/_application_controller_table.coffee
rename to app/assets/javascripts/app/controllers/_application_controller/table.coffee
diff --git a/app/assets/javascripts/app/controllers/_application_controller/tabs.coffee b/app/assets/javascripts/app/controllers/_application_controller/tabs.coffee
new file mode 100644
index 000000000..c60d95bcf
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/_application_controller/tabs.coffee
@@ -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("
")
+ 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)
diff --git a/app/assets/javascripts/app/controllers/_application_controller/wizard_modal.coffee b/app/assets/javascripts/app/controllers/_application_controller/wizard_modal.coffee
new file mode 100644
index 000000000..846f77c42
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/_application_controller/wizard_modal.coffee
@@ -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
+
diff --git a/app/assets/javascripts/app/controllers/_application_controller/wizard_modal_full_screen.coffee b/app/assets/javascripts/app/controllers/_application_controller/wizard_modal_full_screen.coffee
new file mode 100644
index 000000000..e06bf7b4e
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/_application_controller/wizard_modal_full_screen.coffee
@@ -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 }
diff --git a/app/assets/javascripts/app/controllers/_application_controller_generic.coffee b/app/assets/javascripts/app/controllers/_application_controller_generic.coffee
deleted file mode 100644
index 341005798..000000000
--- a/app/assets/javascripts/app/controllers/_application_controller_generic.coffee
+++ /dev/null
@@ -1,1545 +0,0 @@
-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!')
- )
-
-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!')
- )
-
-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
- )
-
-class App.ControllerGenericDescription extends App.ControllerModal
- buttonClose: true
- buttonCancel: false
- buttonSubmit: 'Close'
- head: 'Description'
-
- content: =>
- marked(App.i18n.translateContent(@description))
-
- onSubmit: =>
- @close()
-
-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)
-
-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()
-
-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()
-
-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
-
-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("
")
- 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)
-
-class App.ControllerNavSidbar extends App.Controller
- constructor: (params) ->
- super
-
- if @authenticateRequired
- @authenticateCheckRedirect()
-
- @render(true)
-
- @bind('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('
')
- @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()
-
-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
- "
##{ ticket.number }"
- 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
- "
##{ ticket.number }"
- 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
-
-class App.ActionRow extends App.Controller
- constructor: ->
- super
- @render()
-
- render: ->
- @html App.view('generic/actions')(
- items: @items
- type: @type
- )
-
- for item in @items
- do (item) =>
- @$('[data-type="' + item.name + '"]').on(
- 'click'
- (e) ->
- e.preventDefault()
- item.callback()
- )
-
-class App.Sidebar extends App.Controller
- elements:
- '.tabsSidebar-tab': 'tabs'
- '.sidebar': 'sidebars'
-
- events:
- 'click .tabsSidebar-tab': 'toggleTab'
- 'click .tabsSidebar-close': 'toggleSidebar'
- 'click .sidebar-header .js-headline': 'toggleDropdown'
-
- constructor: ->
- super
- @render()
-
- # get active tab by name
- if @name
- name = @name
-
- # get active tab last state
- if !name && @sidebarState
- name = @sidebarState.active
-
- # get active tab by first tab
- if !name
- name = @tabs.first().data('tab')
-
- # activate first tab
- @toggleTabAction(name)
-
- render: =>
- itemsLocal = []
- for item in @items
- itemLocal = item.sidebarItem()
- if itemLocal
- itemsLocal.push itemLocal
-
- # container
- localEl = $(App.view('generic/sidebar_tabs')(
- items: itemsLocal
- scrollbarWidth: App.Utils.getScrollBarWidth()
- dir: App.i18n.dir()
- ))
-
- # init sidebar badge
- for item in itemsLocal
- el = localEl.find('.tabsSidebar-tab[data-tab="' + item.name + '"]')
- if item.badgeCallback
- item.badgeCallback(el)
- else
- @badgeRender(el, item)
-
- # init sidebar content
- for item in itemsLocal
- if item.sidebarCallback
- el = localEl.filter('.sidebar[data-tab="' + item.name + '"]')
- item.sidebarCallback(el.find('.sidebar-content'))
- if !_.isEmpty(item.sidebarActions)
- new App.ActionRow(
- el: el.find('.js-actions')
- items: item.sidebarActions
- type: 'small'
- )
-
- @html localEl
-
- badgeRender: (el, item) =>
- @badgeEl = el
- @badgeRenderLocal(item)
-
- badgeRenderLocal: (item) =>
- @badgeEl.html(App.view('generic/sidebar_tabs_item')(icon: item.badgeIcon))
-
- toggleDropdown: (e) ->
- e.stopPropagation()
- $(e.currentTarget).next('.js-actions').find('.dropdown-toggle').dropdown('toggle')
-
- toggleSidebar: =>
- @el.parent().find('.tabsSidebar-sidebarSpacer').toggleClass('is-closed')
- @el.parent().find('.tabsSidebar').toggleClass('is-closed')
- #@el.parent().next('.attributeBar').toggleClass('is-closed')
-
- showSidebar: ->
- @el.parent().find('.tabsSidebar-sidebarSpacer').removeClass('is-closed')
- @el.parent().find('.tabsSidebar').removeClass('is-closed')
- #@el.parent().next('.attributeBar').addClass('is-closed')
-
- toggleTab: (e) =>
-
- # get selected tab
- name = $(e.target).closest('.tabsSidebar-tab').data('tab')
-
- if name
-
- # if current tab is selected again, toggle side bar
- if name is @currentTab
- @toggleSidebar()
-
- # toggle content tab
- else
- @toggleTabAction(name)
-
- toggleTabAction: (name) ->
- return if !name
-
- # remember sidebarState for outsite
- if @sidebarState
- @sidebarState.active = name
-
- # remove active state
- @tabs.removeClass('active')
-
- # add active state
- @$('.tabsSidebar-tab[data-tab=' + name + ']').addClass('active')
-
- # hide all content tabs
- @sidebars.addClass('hide')
-
- # show active tab content
- tabContent = @$('.sidebar[data-tab=' + name + ']')
- tabContent.removeClass('hide')
-
- # remember current tab
- @currentTab = name
-
- # show sidebar if not shown
- @showSidebar()
-
-class App.WizardModal extends App.Controller
- className: 'modal fade'
-
- constructor: ->
- super
-
- # rerender view, e. g. on langauge change
- @bind('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
-
-class App.WizardFullScreen extends App.WizardModal
- className: 'getstarted fit'
-
- constructor: ->
- super
- $('.content').addClass('hide')
- $('#content').removeClass('hide')
-
-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
- @bind('ui:rerender', =>
- @queue.push ['renderAll']
- @uIRunner()
- )
-
- # render on login
- @bind('auth:login', =>
- @queue.push ['renderAll']
- @uIRunner()
- )
-
- # reset current tasks on logout
- @bind('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
-
-class App.ObserverController 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
- @bind('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)
-
-class App.ObserverActionRow extends App.ObserverController
- 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)
- )
-
-class App.Import extends App.ControllerModal
- buttonClose: true
- buttonCancel: true
- buttonSubmit: 'Import'
- autoFocusOnFirstInput: false
- head: 'Import'
- large: true
- templateDirectory: 'generic/object_import'
- baseUrl: '/api/v1/text_modules'
-
- content: =>
-
- # show start dialog
- content = $(App.view("#{@templateDirectory}/index")(
- head: 'Import'
- import_example_url: "#{@baseUrl}/import_example"
- deleteOption: @deleteOption
- ))
-
- # check if data is processing...
- if @data
- result = App.view("#{@templateDirectory}/result")(
- @data
- )
- content.find('.js-error').html(result)
- if result
- content.find('.js-error').removeClass('hide')
- else
- content.find('.js-error').addClass('hide')
- content
-
- onSubmit: (e) =>
- params = new FormData($(e.currentTarget).closest('form').get(0))
- params.set('try', true)
- if _.isEmpty(params.get('data'))
- params.delete('data')
- @formDisable(e)
- @ajax(
- id: 'csv_import'
- type: 'POST'
- url: "#{@baseUrl}/import"
- processData: false
- contentType: false
- cache: false
- data: params
- success: (data, status, xhr) =>
- if data.result is 'success'
- new App.ImportTryResult(
- container: @el.closest('.content')
- result: data
- params: params
- templateDirectory: @templateDirectory
- baseUrl: @baseUrl
- )
- @close()
- return
- @data = data
- @update()
- @formEnable(e)
- error: (data) =>
- details = data.responseJSON || {}
- @notify
- type: 'error'
- msg: App.i18n.translateContent(details.error_human || details.error || 'Unable to import!')
- timeout: 6000
- @formEnable(e)
- )
-
-class App.ImportTryResult extends App.ControllerModal
- buttonClose: true
- buttonCancel: true
- buttonSubmit: 'Yes, start real import.'
- autoFocusOnFirstInput: false
- head: 'Import'
- large: true
- templateDirectory: 'generic/object_import/'
- baseUrl: '/api/v1/text_modules'
-
- content: =>
-
- # show start dialog
- content = $(App.view("#{@templateDirectory}/import_try")(
- head: 'Import'
- import_example_url: "#{@baseUrl}/import"
- result: @result
- ))
-
- # check if data is processing...
- if @data
- result = App.view("#{@templateDirectory}/result")(
- @data
- )
- content.find('.js-error').html(result)
- if result
- content.find('.js-error').removeClass('hide')
- else
- content.find('.js-error').addClass('hide')
-
- content
-
- onSubmit: (e) =>
- @params.set('try', false)
- @formDisable(e)
- @ajax(
- id: 'csv_import'
- type: 'POST'
- url: "#{@baseUrl}/import"
- processData: false
- contentType: false
- cache: false
- data: @params
- success: (data, status, xhr) =>
- if data.result is 'success'
- new App.ImportResult(
- container: @el.closest('.content')
- result: data
- params: @params
- templateDirectory: @templateDirectory
- baseUrl: @baseUrl
- )
- @close()
- return
- @data = data
- @update()
- @formEnable(e)
- error: (data) =>
- details = data.responseJSON || {}
- @notify
- type: 'error'
- msg: App.i18n.translateContent(details.error_human || details.error || 'Unable to import!')
- timeout: 6000
- @formEnable(e)
- )
-
-class App.ImportResult extends App.ControllerModal
- buttonClose: true
- buttonCancel: true
- buttonSubmit: 'Close'
- autoFocusOnFirstInput: false
- head: 'Import'
- large: true
- templateDirectory: 'generic/object_import/'
-
- content: =>
-
- content = $(App.view("#{@templateDirectory}/imported")(
- head: 'Imported'
- result: @result
- ))
- content
-
- onSubmit: (e) =>
- @close()
diff --git a/app/assets/javascripts/app/controllers/_channel/chat.coffee b/app/assets/javascripts/app/controllers/_channel/chat.coffee
index 8bd48d2fd..cbea22b48 100644
--- a/app/assets/javascripts/app/controllers/_channel/chat.coffee
+++ b/app/assets/javascripts/app/controllers/_channel/chat.coffee
@@ -1,4 +1,4 @@
-class App.ChannelChat extends App.ControllerSubContent
+class ChannelChat extends App.ControllerSubContent
requiredPermission: 'admin.channel_chat'
header: 'Chat'
events:
@@ -353,7 +353,7 @@ class App.ChannelChat extends App.ControllerSubContent
@code.each (i, 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
events:
diff --git a/app/assets/javascripts/app/controllers/_channel/email.coffee b/app/assets/javascripts/app/controllers/_channel/email.coffee
index a592a6bfb..55bcdd69f 100644
--- a/app/assets/javascripts/app/controllers/_channel/email.coffee
+++ b/app/assets/javascripts/app/controllers/_channel/email.coffee
@@ -1,4 +1,4 @@
-class App.ChannelEmail extends App.ControllerTabs
+class ChannelEmail extends App.ControllerTabs
requiredPermission: 'admin.channel_email'
header: 'Email'
constructor: ->
@@ -10,17 +10,17 @@ class App.ChannelEmail extends App.ControllerTabs
{
name: 'Accounts',
target: 'c-account',
- controller: App.ChannelEmailAccountOverview,
+ controller: ChannelEmailAccountOverview,
},
{
name: 'Filter',
target: 'c-filter',
- controller: App.ChannelEmailFilter,
+ controller: ChannelEmailFilter,
},
{
name: 'Signatures',
target: 'c-signature',
- controller: App.ChannelEmailSignature,
+ controller: ChannelEmailSignature,
},
{
name: 'Settings',
@@ -32,7 +32,7 @@ class App.ChannelEmail extends App.ControllerTabs
@render()
-class App.ChannelEmailFilter extends App.Controller
+class ChannelEmailFilter extends App.Controller
events:
'click [data-type=new]': 'new'
@@ -79,7 +79,7 @@ class App.ChannelEmailFilter extends App.Controller
callback: @load
)
-class App.ChannelEmailSignature extends App.Controller
+class ChannelEmailSignature extends App.Controller
events:
'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) =>
e.preventDefault()
- new App.ChannelEmailSignatureEdit(
+ new ChannelEmailSignatureEdit(
container: @el.closest('.content')
)
edit: (id, e) =>
e.preventDefault()
item = App.Signature.find(id)
- new App.ChannelEmailSignatureEdit(
+ new ChannelEmailSignatureEdit(
object: item
container: @el.closest('.content')
)
-class App.ChannelEmailSignatureEdit extends App.ControllerModal
+class ChannelEmailSignatureEdit extends App.ControllerModal
buttonClose: true
buttonCancel: true
buttonSubmit: true
@@ -174,7 +174,7 @@ class App.ChannelEmailSignatureEdit extends App.ControllerModal
@form.showAlert(details.error_human || details.error || 'Unable to create object!')
)
-class App.ChannelEmailAccountOverview extends App.Controller
+class ChannelEmailAccountOverview extends App.Controller
events:
'click .js-channelNew': 'wizard'
'click .js-channelDelete': 'delete'
@@ -248,7 +248,7 @@ class App.ChannelEmailAccountOverview extends App.Controller
wizard: (e) =>
e.preventDefault()
- new App.ChannelEmailAccountWizard(
+ new ChannelEmailAccountWizard(
container: @el.closest('.content')
callback: @load
channelDriver: @channelDriver
@@ -259,7 +259,7 @@ class App.ChannelEmailAccountOverview extends App.Controller
id = $(e.target).closest('.action').data('id')
channel = App.Channel.find(id)
slide = 'js-inbound'
- new App.ChannelEmailAccountWizard(
+ new ChannelEmailAccountWizard(
container: @el.closest('.content')
slide: slide
channel: channel
@@ -272,7 +272,7 @@ class App.ChannelEmailAccountOverview extends App.Controller
id = $(e.target).closest('.action').data('id')
channel = App.Channel.find(id)
slide = 'js-outbound'
- new App.ChannelEmailAccountWizard(
+ new ChannelEmailAccountWizard(
container: @el.closest('.content')
slide: slide
channel: channel
@@ -328,7 +328,7 @@ class App.ChannelEmailAccountOverview extends App.Controller
e.preventDefault()
id = $(e.target).closest('.action').data('id')
item = App.Channel.find(id)
- new App.ChannelEmailEdit(
+ new ChannelEmailEdit(
container: @el.closest('.content')
item: item
callback: @load
@@ -374,7 +374,7 @@ class App.ChannelEmailAccountOverview extends App.Controller
id = $(e.target).closest('.action').data('id')
channel = App.Channel.find(id)
slide = 'js-outbound'
- new App.ChannelEmailNotificationWizard(
+ new ChannelEmailNotificationWizard(
container: @el.closest('.content')
channel: channel
callback: @load
@@ -391,7 +391,8 @@ class App.ChannelEmailAccountOverview extends App.Controller
id = $(e.target).closest('.action').data('id')
@navigate "#channels/microsoft365/#{id}"
-class App.ChannelEmailEdit extends App.ControllerModal
+
+class ChannelEmailEdit extends App.ControllerModal
buttonClose: true
buttonCancel: 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.')
)
-class App.ChannelEmailAccountWizard extends App.WizardModal
+class ChannelEmailAccountWizard extends App.ControllerWizardModal
elements:
'.modal-body': 'body'
events:
@@ -896,7 +897,7 @@ class App.ChannelEmailAccountWizard extends App.WizardModal
e.preventDefault()
@el.modal('hide')
-class App.ChannelEmailNotificationWizard extends App.WizardModal
+class ChannelEmailNotificationWizard extends App.ControllerWizardModal
elements:
'.modal-body': 'body'
events:
@@ -1030,4 +1031,4 @@ class App.ChannelEmailNotificationWizard extends App.WizardModal
@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')
diff --git a/app/assets/javascripts/app/controllers/_channel/facebook.coffee b/app/assets/javascripts/app/controllers/_channel/facebook.coffee
index 72291b24b..e73f6d964 100644
--- a/app/assets/javascripts/app/controllers/_channel/facebook.coffee
+++ b/app/assets/javascripts/app/controllers/_channel/facebook.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class ChannelFacebook extends App.ControllerSubContent
requiredPermission: 'admin.channel_facebook'
header: 'Facebook'
events:
@@ -254,4 +254,4 @@ class AccountEdit extends App.ControllerModal
@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')
diff --git a/app/assets/javascripts/app/controllers/_channel/form.coffee b/app/assets/javascripts/app/controllers/_channel/form.coffee
index 10394d8d3..d7b1e880b 100644
--- a/app/assets/javascripts/app/controllers/_channel/form.coffee
+++ b/app/assets/javascripts/app/controllers/_channel/form.coffee
@@ -1,5 +1,5 @@
# coffeelint: disable=no_unnecessary_double_quotes
-class App.ChannelForm extends App.ControllerSubContent
+class ChannelForm extends App.ControllerSubContent
requiredPermission: 'admin.channel_formular'
header: 'Form'
events:
@@ -88,4 +88,4 @@ class App.ChannelForm extends App.ControllerSubContent
value = @paramsSetting.find('[name=group_id]').val()
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')
diff --git a/app/assets/javascripts/app/controllers/_channel/sms.coffee b/app/assets/javascripts/app/controllers/_channel/sms.coffee
index 13091c844..332b872b0 100644
--- a/app/assets/javascripts/app/controllers/_channel/sms.coffee
+++ b/app/assets/javascripts/app/controllers/_channel/sms.coffee
@@ -1,4 +1,4 @@
-class App.ChannelSms extends App.ControllerTabs
+class ChannelSms extends App.ControllerTabs
requiredPermission: 'admin.channel_sms'
header: 'SMS'
constructor: ->
@@ -9,13 +9,13 @@ class App.ChannelSms extends App.ControllerTabs
{
name: 'Accounts',
target: 'c-account',
- controller: App.ChannelSmsAccountOverview,
+ controller: ChannelSmsAccountOverview,
},
]
@render()
-class App.ChannelSmsAccountOverview extends App.Controller
+class ChannelSmsAccountOverview extends App.Controller
events:
'click .js-channelEdit': 'change'
'click .js-channelDelete': 'delete'
@@ -76,7 +76,7 @@ class App.ChannelSmsAccountOverview extends App.Controller
channel = new App.Channel(active: true)
else
channel = App.Channel.find(id)
- new App.ChannelSmsAccount(
+ new ChannelSmsAccount(
container: @el.closest('.content')
channel: channel
callback: @load
@@ -127,7 +127,7 @@ class App.ChannelSmsAccountOverview extends App.Controller
e.preventDefault()
id = $(e.target).closest('.action').data('id')
channel = App.Channel.find(id)
- new App.ChannelSmsNotification(
+ new ChannelSmsNotification(
container: @el.closest('.content')
channel: channel
callback: @load
@@ -135,7 +135,7 @@ class App.ChannelSmsAccountOverview extends App.Controller
config: @config
)
-class App.ChannelSmsAccount extends App.ControllerModal
+class ChannelSmsAccount extends App.ControllerModal
head: 'SMS Account'
buttonCancel: true
centerButtons: [
@@ -272,7 +272,7 @@ class App.ChannelSmsAccount extends App.ControllerModal
container: @el.closest('.content')
)
-class App.ChannelSmsNotification extends App.ControllerModal
+class ChannelSmsNotification extends App.ControllerModal
head: 'SMS Notification'
buttonCancel: true
centerButtons: [
@@ -439,4 +439,4 @@ class TestModal extends App.ControllerModal
.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')
diff --git a/app/assets/javascripts/app/controllers/_channel/telegram.coffee b/app/assets/javascripts/app/controllers/_channel/telegram.coffee
index 7b60054af..3591c551a 100644
--- a/app/assets/javascripts/app/controllers/_channel/telegram.coffee
+++ b/app/assets/javascripts/app/controllers/_channel/telegram.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class ChannelTelegram extends App.ControllerSubContent
requiredPermission: 'admin.channel_telegram'
events:
'click .js-new': 'new'
@@ -201,4 +201,4 @@ class BotEdit extends App.ControllerModal
@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')
diff --git a/app/assets/javascripts/app/controllers/_channel/twitter.coffee b/app/assets/javascripts/app/controllers/_channel/twitter.coffee
index 1bcfc0a86..381f339ff 100644
--- a/app/assets/javascripts/app/controllers/_channel/twitter.coffee
+++ b/app/assets/javascripts/app/controllers/_channel/twitter.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class ChannelTwitter extends App.ControllerSubContent
requiredPermission: 'admin.channel_twitter'
events:
'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.')
)
-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')
diff --git a/app/assets/javascripts/app/controllers/_channel/web.coffee b/app/assets/javascripts/app/controllers/_channel/web.coffee
index 6e5915855..7e3614bc8 100644
--- a/app/assets/javascripts/app/controllers/_channel/web.coffee
+++ b/app/assets/javascripts/app/controllers/_channel/web.coffee
@@ -1,4 +1,4 @@
-class App.ChannelWeb extends App.ControllerTabs
+class ChannelWeb extends App.ControllerTabs
requiredPermission: 'admin.channel_web'
header: 'Web'
constructor: ->
@@ -16,4 +16,4 @@ class App.ChannelWeb extends App.ControllerTabs
@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')
diff --git a/app/assets/javascripts/app/controllers/_dashboard/activity_stream.coffee b/app/assets/javascripts/app/controllers/_dashboard/activity_stream.coffee
index a1df4842b..d0a521fc3 100644
--- a/app/assets/javascripts/app/controllers/_dashboard/activity_stream.coffee
+++ b/app/assets/javascripts/app/controllers/_dashboard/activity_stream.coffee
@@ -13,7 +13,7 @@ class App.DashboardActivityStream extends App.CollectionController
@fetch()
# bind to rebuild view event
- @bind('activity_stream_rebuild', @load)
+ @controllerBind('activity_stream_rebuild', @load)
fetch: =>
diff --git a/app/assets/javascripts/app/controllers/_dashboard/first_steps_clues.coffee b/app/assets/javascripts/app/controllers/_dashboard/first_steps_clues.coffee
index 4b211e422..a09f8175e 100644
--- a/app/assets/javascripts/app/controllers/_dashboard/first_steps_clues.coffee
+++ b/app/assets/javascripts/app/controllers/_dashboard/first_steps_clues.coffee
@@ -54,8 +54,9 @@ class App.FirstStepsClues extends App.Controller
constructor: (params) ->
- $('#app').append('
')
- params.el = $('#app .js-modal--clue')
+ el = $('
')
+ params.appEl.append(el)
+ params.el = el
super params
@@ -69,7 +70,7 @@ class App.FirstStepsClues extends App.Controller
@position = 0
@render()
- @bind('ui:rerender', =>
+ @controllerBind('ui:rerender', =>
@render()
'clues'
)
@@ -106,7 +107,7 @@ class App.FirstStepsClues extends App.Controller
cleanUp: (callback) ->
@hideWindow =>
clue = @clues[@position]
- container = $("#app #{clue.container}")
+ container = @appEl.find(clue.container)
container.removeClass('selected-clue')
# undo click perform by doing it again
@@ -128,7 +129,7 @@ class App.FirstStepsClues extends App.Controller
showClue: =>
clue = @clues[@position]
- container = $("#app #{clue.container}")
+ container = @appEl.find(clue.container)
container.addClass('selected-clue')
if clue.actions
@@ -324,7 +325,7 @@ class App.FirstStepsClues extends App.Controller
when 'hover'
# disable active navbar elements
- $('#app .navigation .is-active').removeClass('is-active')
+ @appEl.find('.navigation .is-active').removeClass('is-active')
if type is 'show'
target.addClass('is-hovered')
diff --git a/app/assets/javascripts/app/controllers/_dashboard/stats.coffee b/app/assets/javascripts/app/controllers/_dashboard/stats.coffee
index d13708c92..ee23a1737 100644
--- a/app/assets/javascripts/app/controllers/_dashboard/stats.coffee
+++ b/app/assets/javascripts/app/controllers/_dashboard/stats.coffee
@@ -1,10 +1,10 @@
class App.DashboardStats extends App.Controller
constructor: ->
super
- @load()
- @bind('dashboard_stats_rebuild', @load)
+ @setupStatsWidgets()
+ @controllerBind('dashboard_stats_rebuild', @setupStatsWidgets)
- load: =>
+ setupStatsWidgets: =>
@setupStatsWidget('Stats', 'stats', @el)
setupStatsWidget: (config, event, el) ->
@@ -20,11 +20,11 @@ class App.DashboardStats extends App.Controller
if @permissionCheck(widget.permission)
try
new widget.controller(
- el: el
+ parentEl: @el
+ className: widget.className
)
@$('.js-stat-help').tooltip()
catch e
@log 'error', "statsWidgets #{widget}:", e
-
App.Event.trigger(event + ':ready')
diff --git a/app/assets/javascripts/app/controllers/_dashboard/stats/_base.coffee b/app/assets/javascripts/app/controllers/_dashboard/stats/_base.coffee
new file mode 100644
index 000000000..5beb6fcc6
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/_dashboard/stats/_base.coffee
@@ -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 = $("
")
+ 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()
diff --git a/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_channel_distribution.coffee b/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_channel_distribution.coffee
index aea977636..86a14226f 100644
--- a/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_channel_distribution.coffee
+++ b/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_channel_distribution.coffee
@@ -1,15 +1,4 @@
-class Stats extends App.Controller
- constructor: ->
- super
- @load()
-
- load: =>
- stats_store = App.StatsStore.first()
- if stats_store
- @render(stats_store.data)
- else
- @render()
-
+class Stats extends App.ControllerDashboardStatsBase
render: (data = {}) ->
if !data.StatsTicketChannelDistribution
data.StatsTicketChannelDistribution =
@@ -44,4 +33,4 @@ class Stats extends App.Controller
else
@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')
diff --git a/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_escalation.coffee b/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_escalation.coffee
index 15560c9a3..6cec35679 100644
--- a/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_escalation.coffee
+++ b/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_escalation.coffee
@@ -1,15 +1,4 @@
-class Stats extends App.Controller
- constructor: ->
- super
- @load()
-
- load: =>
- stats_store = App.StatsStore.first()
- if stats_store
- @render(stats_store.data)
- else
- @render()
-
+class Stats extends App.ControllerDashboardStatsBase
render: (data = {}) ->
if !data.StatsTicketEscalation
data.StatsTicketEscalation =
@@ -26,4 +15,4 @@ class Stats extends App.Controller
else
@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')
diff --git a/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_in_process.coffee b/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_in_process.coffee
index 457792b2f..3d820da3a 100644
--- a/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_in_process.coffee
+++ b/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_in_process.coffee
@@ -1,20 +1,10 @@
-class Stats extends App.Controller
- constructor: ->
- super
- @load()
-
- load: =>
- stats_store = App.StatsStore.first()
- if stats_store
- @render(stats_store.data)
- else
- @render()
-
+class Stats extends App.ControllerDashboardStatsBase
render: (data = {}) ->
if !data.StatsTicketInProcess
data.StatsTicketInProcess =
state: 'supergood'
percent: 0
+ in_process: 0
average_per_agent: 0
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
@el.append(content)
-
-App.Config.set('ticket_in_process', {controller: Stats, permission: 'ticket.agent', prio: 500 }, 'Stats')
+App.Config.set('ticket_in_process', { controller: Stats, permission: 'ticket.agent', prio: 500, className: 'ticket_in_process' }, 'Stats')
diff --git a/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_load_measure.coffee b/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_load_measure.coffee
index b54649ab2..8e83f09f3 100644
--- a/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_load_measure.coffee
+++ b/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_load_measure.coffee
@@ -1,15 +1,4 @@
-class Stats extends App.Controller
- constructor: ->
- super
- @load()
-
- load: =>
- stats_store = App.StatsStore.first()
- if stats_store
- @render(stats_store.data)
- else
- @render()
-
+class Stats extends App.ControllerDashboardStatsBase
render: (data = {}) ->
if !data.StatsTicketLoadMeasure
data.StatsTicketLoadMeasure =
@@ -28,4 +17,4 @@ class Stats extends App.Controller
else
@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')
diff --git a/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_reopen.coffee b/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_reopen.coffee
index 17a26a421..b1c2abf28 100644
--- a/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_reopen.coffee
+++ b/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_reopen.coffee
@@ -1,15 +1,4 @@
-class Stats extends App.Controller
- constructor: ->
- super
- @load()
-
- load: =>
- stats_store = App.StatsStore.first()
- if stats_store
- @render(stats_store.data)
- else
- @render()
-
+class Stats extends App.ControllerDashboardStatsBase
render: (data = {}) ->
if !data.StatsTicketReopen
data.StatsTicketReopen =
@@ -25,4 +14,4 @@ class Stats extends App.Controller
else
@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')
diff --git a/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_waiting_time.coffee b/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_waiting_time.coffee
index 0ab1d0269..832e682bc 100644
--- a/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_waiting_time.coffee
+++ b/app/assets/javascripts/app/controllers/_dashboard/stats/ticket_waiting_time.coffee
@@ -1,15 +1,4 @@
-class Stats extends App.Controller
- constructor: ->
- super
- @load()
-
- load: =>
- stats_store = App.StatsStore.first()
- if stats_store
- @render(stats_store.data)
- else
- @render()
-
+class Stats extends App.ControllerDashboardStatsBase
render: (data = {}) ->
if !data.StatsTicketWaitingTime
data.StatsTicketWaitingTime =
@@ -75,4 +64,4 @@ class Stats extends App.Controller
ctx.closePath()
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')
diff --git a/app/assets/javascripts/app/controllers/_integration/check_mk.coffee b/app/assets/javascripts/app/controllers/_integration/check_mk.coffee
index 3079b129d..847f6bd70 100644
--- a/app/assets/javascripts/app/controllers/_integration/check_mk.coffee
+++ b/app/assets/javascripts/app/controllers/_integration/check_mk.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerIntegrationBase
+class CheckMk extends App.ControllerIntegrationBase
featureIntegration: 'check_mk_integration'
featureName: 'Checkmk'
featureConfig: 'check_mk_config'
@@ -55,7 +55,7 @@ App.Config.set(
name: 'Checkmk'
target: '#system/integration/check_mk'
description: 'An open source monitoring tool.'
- controller: Index
+ controller: CheckMk
state: State
permission: ['admin.integration.check_mk']
}
diff --git a/app/assets/javascripts/app/controllers/_integration/clearbit.coffee b/app/assets/javascripts/app/controllers/_integration/clearbit.coffee
index e6009affc..58624e4a8 100644
--- a/app/assets/javascripts/app/controllers/_integration/clearbit.coffee
+++ b/app/assets/javascripts/app/controllers/_integration/clearbit.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerIntegrationBase
+class Clearbit extends App.ControllerIntegrationBase
featureIntegration: 'clearbit_integration'
featureName: 'Clearbit'
featureConfig: 'clearbit_config'
@@ -155,7 +155,7 @@ App.Config.set(
name: 'Clearbit'
target: '#system/integration/clearbit'
description: 'A powerful service to get more information about your customers.'
- controller: Index
+ controller: Clearbit
state: State
permission: ['admin.integration.clearbit']
}
diff --git a/app/assets/javascripts/app/controllers/_integration/cti.coffee b/app/assets/javascripts/app/controllers/_integration/cti.coffee
index 4068b9480..ca2e3038f 100644
--- a/app/assets/javascripts/app/controllers/_integration/cti.coffee
+++ b/app/assets/javascripts/app/controllers/_integration/cti.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerIntegrationBase
+class Cti extends App.ControllerIntegrationBase
featureIntegration: 'cti_integration'
featureName: 'CTI (generic)'
featureConfig: 'cti_config'
@@ -234,7 +234,7 @@ App.Config.set(
name: 'CTI (generic)'
target: '#system/integration/cti'
description: 'Generic API to integrate VoIP service provider with realtime push.'
- controller: Index
+ controller: Cti
state: State
}
'NavBarIntegrations'
diff --git a/app/assets/javascripts/app/controllers/_integration/exchange.coffee b/app/assets/javascripts/app/controllers/_integration/exchange.coffee
index e69976c98..2a2922232 100644
--- a/app/assets/javascripts/app/controllers/_integration/exchange.coffee
+++ b/app/assets/javascripts/app/controllers/_integration/exchange.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerIntegrationBase
+class Exchange extends App.ControllerIntegrationBase
featureIntegration: 'exchange_integration'
featureName: 'Exchange'
featureConfig: 'exchange_config'
@@ -166,7 +166,7 @@ class State
@current: ->
App.Setting.get('exchange_integration')
-class ConnectionWizard extends App.WizardModal
+class ConnectionWizard extends App.ControllerWizardModal
wizardConfig: {}
slideMethod:
'js-folders': 'foldersShow'
@@ -557,7 +557,7 @@ App.Config.set(
name: 'Exchange'
target: '#system/integration/exchange'
description: 'Exchange integration for contacts management.'
- controller: Index
+ controller: Exchange
state: State
permission: ['admin.integration.exchange']
}
diff --git a/app/assets/javascripts/app/controllers/_integration/icinga.coffee b/app/assets/javascripts/app/controllers/_integration/icinga.coffee
index 6788680df..eefc9ca0d 100644
--- a/app/assets/javascripts/app/controllers/_integration/icinga.coffee
+++ b/app/assets/javascripts/app/controllers/_integration/icinga.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerIntegrationBase
+class Icinga extends App.ControllerIntegrationBase
featureIntegration: 'icinga_integration'
featureName: 'Icinga'
featureConfig: 'icinga_config'
@@ -24,7 +24,7 @@ App.Config.set(
name: 'Icinga'
target: '#system/integration/icinga'
description: 'An open source monitoring tool.'
- controller: Index
+ controller: Icinga
state: State
permission: ['admin.integration.icinga']
}
diff --git a/app/assets/javascripts/app/controllers/_integration/idoit.coffee b/app/assets/javascripts/app/controllers/_integration/idoit.coffee
index d94d96503..a902b1ba7 100644
--- a/app/assets/javascripts/app/controllers/_integration/idoit.coffee
+++ b/app/assets/javascripts/app/controllers/_integration/idoit.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerIntegrationBase
+class Idoit extends App.ControllerIntegrationBase
featureIntegration: 'idoit_integration'
featureName: 'i-doit'
featureConfig: 'idoit_config'
@@ -58,7 +58,7 @@ class Form extends App.Controller
)
success: (data, status, xhr) =>
if data.result is 'failed'
- new App.ControllerErrorModal(
+ new App.ErrorModal(
message: data.message
container: @el.closest('.content')
)
@@ -87,7 +87,7 @@ App.Config.set(
name: 'i-doit'
target: '#system/integration/idoit'
description: 'CMDB to document complex relations of your network components.'
- controller: Index
+ controller: Idoit
state: State
}
'NavBarIntegrations'
diff --git a/app/assets/javascripts/app/controllers/_integration/ldap.coffee b/app/assets/javascripts/app/controllers/_integration/ldap.coffee
index 2ca2d69de..b47da749c 100644
--- a/app/assets/javascripts/app/controllers/_integration/ldap.coffee
+++ b/app/assets/javascripts/app/controllers/_integration/ldap.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerIntegrationBase
+class Ldap extends App.ControllerIntegrationBase
featureIntegration: 'ldap_integration'
featureName: 'LDAP'
featureConfig: 'ldap_config'
@@ -71,6 +71,7 @@ class Form extends App.Controller
group_role_map = {}
for source, dests of @config.group_role_map
group_role_map[source] = dests.map((dest) ->
+ return '?' if !App.Role.exists(dest)
App.Role.find(dest).displayName()
).join ', '
@@ -135,8 +136,9 @@ class Form extends App.Controller
if !job.result.roles
job.result.roles = {}
for role_id, statistic of job.result.role_ids
- role = App.Role.find(role_id)
- job.result.roles[role.displayName()] = statistic
+ if App.Role.exists(role_id)
+ role = App.Role.find(role_id)
+ job.result.roles[role.displayName()] = statistic
el = $(App.view('integration/ldap_last_import')(job: job))
@lastImport.html(el)
@@ -167,9 +169,7 @@ class State
@current: ->
App.Setting.get('ldap_integration')
-class ConnectionWizard extends App.WizardModal
- className: 'modal fade modal--large'
-
+class ConnectionWizard extends App.ControllerWizardModal
wizardConfig: {}
slideMethod:
'js-bind': 'bindShow'
@@ -562,8 +562,9 @@ class ConnectionWizard extends App.WizardModal
if !job.result.roles
job.result.roles = {}
for role_id, statistic of job.result.role_ids
- role = App.Role.find(role_id)
- job.result.roles[role.displayName()] = statistic
+ if App.Role.find(role_id)
+ role = App.Role.find(role_id)
+ job.result.roles[role.displayName()] = statistic
@showSlide('js-try')
el = $(App.view('integration/ldap_summary')(job: job))
@el.find('.js-summary').html(el)
@@ -574,7 +575,7 @@ App.Config.set(
name: 'LDAP'
target: '#system/integration/ldap'
description: 'LDAP integration for user management.'
- controller: Index
+ controller: Ldap
state: State
permission: ['admin.integration.ldap']
}
diff --git a/app/assets/javascripts/app/controllers/_integration/monit.coffee b/app/assets/javascripts/app/controllers/_integration/monit.coffee
index 208c6d507..5647483ce 100644
--- a/app/assets/javascripts/app/controllers/_integration/monit.coffee
+++ b/app/assets/javascripts/app/controllers/_integration/monit.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerIntegrationBase
+class Monit extends App.ControllerIntegrationBase
featureIntegration: 'monit_integration'
featureName: 'Monit'
featureConfig: 'monit_config'
@@ -24,7 +24,7 @@ App.Config.set(
name: 'Monit'
target: '#system/integration/monit'
description: 'An open source monitoring tool.'
- controller: Index
+ controller: Monit
state: State
permission: ['admin.integration.monit']
}
diff --git a/app/assets/javascripts/app/controllers/_integration/nagios.coffee b/app/assets/javascripts/app/controllers/_integration/nagios.coffee
index 4ddcf7331..d061ccdd2 100644
--- a/app/assets/javascripts/app/controllers/_integration/nagios.coffee
+++ b/app/assets/javascripts/app/controllers/_integration/nagios.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerIntegrationBase
+class Nagios extends App.ControllerIntegrationBase
featureIntegration: 'nagios_integration'
featureName: 'Nagios'
featureConfig: 'nagios_config'
@@ -24,7 +24,7 @@ App.Config.set(
name: 'Nagios'
target: '#system/integration/nagios'
description: 'An open source monitoring tool.'
- controller: Index
+ controller: Nagios
state: State
}
'NavBarIntegrations'
diff --git a/app/assets/javascripts/app/controllers/_integration/placetel.coffee b/app/assets/javascripts/app/controllers/_integration/placetel.coffee
index f82d0c045..8289af1ad 100644
--- a/app/assets/javascripts/app/controllers/_integration/placetel.coffee
+++ b/app/assets/javascripts/app/controllers/_integration/placetel.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerIntegrationBase
+class Placetel extends App.ControllerIntegrationBase
featureIntegration: 'placetel_integration'
featureName: 'Placetel'
featureConfig: 'placetel_config'
@@ -188,7 +188,7 @@ App.Config.set(
name: 'Placetel'
target: '#system/integration/placetel'
description: 'VoIP service provider with realtime push.'
- controller: Index
+ controller: Placetel
state: State
}
'NavBarIntegrations'
diff --git a/app/assets/javascripts/app/controllers/_integration/sipgate_io.coffee b/app/assets/javascripts/app/controllers/_integration/sipgate_io.coffee
index 9f502dbaa..8c7ee0a2d 100644
--- a/app/assets/javascripts/app/controllers/_integration/sipgate_io.coffee
+++ b/app/assets/javascripts/app/controllers/_integration/sipgate_io.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerIntegrationBase
+class SipgateIo extends App.ControllerIntegrationBase
featureIntegration: 'sipgate_integration'
featureName: 'sipgate.io'
featureConfig: 'sipgate_config'
@@ -188,7 +188,7 @@ App.Config.set(
name: 'sipgate.io'
target: '#system/integration/sipgate'
description: 'VoIP service provider with realtime push.'
- controller: Index
+ controller: SipgateIo
state: State
}
'NavBarIntegrations'
diff --git a/app/assets/javascripts/app/controllers/_integration/slack.coffee b/app/assets/javascripts/app/controllers/_integration/slack.coffee
index 9ab9476b5..599b26c5f 100644
--- a/app/assets/javascripts/app/controllers/_integration/slack.coffee
+++ b/app/assets/javascripts/app/controllers/_integration/slack.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerIntegrationBase
+class Slack extends App.ControllerIntegrationBase
featureIntegration: 'slack_integration'
featureName: 'Slack'
featureConfig: 'slack_config'
@@ -85,7 +85,7 @@ App.Config.set(
target: '#system/integration/slack'
description: 'A team communication tool for the 21st century. Compatible with tools like %s.'
descriptionSubstitute: 'Mattermost, RocketChat'
- controller: Index
+ controller: Slack
state: State
}
'NavBarIntegrations'
diff --git a/app/assets/javascripts/app/controllers/_integration/smime.coffee b/app/assets/javascripts/app/controllers/_integration/smime.coffee
index b4bc5561d..0fc120970 100644
--- a/app/assets/javascripts/app/controllers/_integration/smime.coffee
+++ b/app/assets/javascripts/app/controllers/_integration/smime.coffee
@@ -99,11 +99,9 @@ class Certificate extends App.ControllerModal
cache: false
data: params
success: (data, status, xhr) =>
- console.log('success')
@close()
@callback()
error: (data) =>
- console.log('error')
@close()
details = data.responseJSON || {}
@notify
diff --git a/app/assets/javascripts/app/controllers/widget/app_config_update.coffee b/app/assets/javascripts/app/controllers/_plugin/app_config_update.coffee
similarity index 57%
rename from app/assets/javascripts/app/controllers/widget/app_config_update.coffee
rename to app/assets/javascripts/app/controllers/_plugin/app_config_update.coffee
index 5a0f48ed3..96d9a65b7 100644
--- a/app/assets/javascripts/app/controllers/widget/app_config_update.coffee
+++ b/app/assets/javascripts/app/controllers/_plugin/app_config_update.coffee
@@ -1,7 +1,5 @@
-class Widget extends App.Controller
+class AppConfigUpdate
constructor: ->
- super
-
App.Event.bind(
'config_update'
(data) ->
@@ -9,4 +7,7 @@ class Widget extends App.Controller
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')
diff --git a/app/assets/javascripts/app/controllers/widget/default_locale.coffee b/app/assets/javascripts/app/controllers/_plugin/default_locale.coffee
similarity index 83%
rename from app/assets/javascripts/app/controllers/widget/default_locale.coffee
rename to app/assets/javascripts/app/controllers/_plugin/default_locale.coffee
index db4437c30..98099c2ed 100644
--- a/app/assets/javascripts/app/controllers/widget/default_locale.coffee
+++ b/app/assets/javascripts/app/controllers/_plugin/default_locale.coffee
@@ -16,8 +16,8 @@ class DefaultLocale extends App.Controller
processData: true
)
- App.Event.bind('auth:login', (session) =>
+ @controllerBind('auth:login', (session) =>
@delay(check, 3500, 'default_locale')
)
-App.Config.set('default_locale', DefaultLocale, 'Widgets')
+App.Config.set('default_locale', DefaultLocale, 'Plugins')
diff --git a/app/assets/javascripts/app/controllers/widget/default_timezone.coffee b/app/assets/javascripts/app/controllers/_plugin/default_timezone.coffee
similarity index 89%
rename from app/assets/javascripts/app/controllers/widget/default_timezone.coffee
rename to app/assets/javascripts/app/controllers/_plugin/default_timezone.coffee
index a85b327c1..0f25ad6d6 100644
--- a/app/assets/javascripts/app/controllers/widget/default_timezone.coffee
+++ b/app/assets/javascripts/app/controllers/_plugin/default_timezone.coffee
@@ -26,11 +26,11 @@ class DefaultTimezone extends App.Controller
# processData: true
#)
- App.Event.bind('auth:login', (session) =>
+ @controllerBind('auth:login', (session) =>
@delay(check, 8500, 'default_timezone')
)
updateSetting: (timezone) ->
App.Setting.set('timezone_default', timezone)
-App.Config.set('default_timezone', DefaultTimezone, 'Widgets')
+App.Config.set('default_timezone', DefaultTimezone, 'Plugins')
diff --git a/app/assets/javascripts/app/controllers/widget/dev_banner.coffee b/app/assets/javascripts/app/controllers/_plugin/dev_banner.coffee
similarity index 91%
rename from app/assets/javascripts/app/controllers/widget/dev_banner.coffee
rename to app/assets/javascripts/app/controllers/_plugin/dev_banner.coffee
index 28d534391..5be8a5739 100644
--- a/app/assets/javascripts/app/controllers/widget/dev_banner.coffee
+++ b/app/assets/javascripts/app/controllers/_plugin/dev_banner.coffee
@@ -1,4 +1,4 @@
-class Widget
+class DevBanner
constructor: ->
return if !App.Config.get('developer_mode')
return if App.Log.config('banner') is false
@@ -17,4 +17,4 @@ class Widget
"""
console.log(banner)
-App.Config.set('dev_banner', Widget, 'Widgets')
+App.Config.set('dev_banner', DevBanner, 'Plugins')
diff --git a/app/assets/javascripts/app/controllers/widget/electron_events.coffee b/app/assets/javascripts/app/controllers/_plugin/electron_events.coffee
similarity index 88%
rename from app/assets/javascripts/app/controllers/widget/electron_events.coffee
rename to app/assets/javascripts/app/controllers/_plugin/electron_events.coffee
index f79309ed9..03da56b6e 100644
--- a/app/assets/javascripts/app/controllers/widget/electron_events.coffee
+++ b/app/assets/javascripts/app/controllers/_plugin/electron_events.coffee
@@ -1,18 +1,19 @@
-class Widget
+class ElectronEvents extends App.Controller
constructor: ->
return if !window.require
electron = window.require('electron')
return if !electron
remote = electron.remote
ipc = electron.ipcRenderer
+ super
- App.Event.bind('window-title-set', (arg) ->
+ @controllerBind('window-title-set', (arg) ->
ipc.send('window-title-set', arg)
)
- App.Event.bind('online_notification_counter', (e) ->
+ @controllerBind('online_notification_counter', (e) ->
setBadge(e)
)
- ipc.on('global-shortcut', (e, arg) ->
+ ipc.off('global-shortcut').on('global-shortcut', (e, arg) ->
App.Event.trigger('global-shortcut', arg)
)
@@ -91,4 +92,4 @@ class Widget
else if process.platform is 'darwin'
setBadgeOSX(content)
-App.Config.set('aaa_electron_events', Widget, 'Navigations')
+App.Config.set('aaa_electron_events', ElectronEvents, 'Plugins')
diff --git a/app/assets/javascripts/app/controllers/widget/global_search.coffee b/app/assets/javascripts/app/controllers/_plugin/global_search.coffee
similarity index 76%
rename from app/assets/javascripts/app/controllers/widget/global_search.coffee
rename to app/assets/javascripts/app/controllers/_plugin/global_search.coffee
index be2e88935..655d39661 100644
--- a/app/assets/javascripts/app/controllers/widget/global_search.coffee
+++ b/app/assets/javascripts/app/controllers/_plugin/global_search.coffee
@@ -1,12 +1,13 @@
-class App.GlobalSearchWidget extends Spine.Module
+class App.GlobalSearchWidget extends App.Controller
shiftHeld = false
constructor: ->
- $('body').on('mousedown', (e) =>
+ super
+ $('body').off('mousedown.globalsearch').on('mousedown.globalsearch', (e) =>
@shiftHeldToogle(e)
true
)
- App.Event.bind('global:search:set', (data) =>
+ @controllerBind('global:search:set', (data) =>
item = data[0]
attribute = data[1]
item = item.replace('"', '')
@@ -36,4 +37,4 @@ class App.GlobalSearchWidget extends Spine.Module
@search: (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')
diff --git a/app/assets/javascripts/app/controllers/widget/hello_banner.coffee b/app/assets/javascripts/app/controllers/_plugin/hello_banner.coffee
similarity index 88%
rename from app/assets/javascripts/app/controllers/widget/hello_banner.coffee
rename to app/assets/javascripts/app/controllers/_plugin/hello_banner.coffee
index 9c0d9e8fa..d95720445 100644
--- a/app/assets/javascripts/app/controllers/widget/hello_banner.coffee
+++ b/app/assets/javascripts/app/controllers/_plugin/hello_banner.coffee
@@ -1,4 +1,4 @@
-class Widget
+class HelloBanner
constructor: ->
return if App.Config.get('developer_mode')
banner = """
@@ -17,4 +17,4 @@ class Widget
"""
console.log(banner, 'text-decoration: underline;', 'text-decoration: none;')
-App.Config.set('hello_banner', Widget, 'Widgets')
+App.Config.set('hello_banner', HelloBanner, 'Plugins')
diff --git a/app/assets/javascripts/app/controllers/widget/keyboard_shortcuts.coffee b/app/assets/javascripts/app/controllers/_plugin/keyboard_shortcuts.coffee
similarity index 98%
rename from app/assets/javascripts/app/controllers/widget/keyboard_shortcuts.coffee
rename to app/assets/javascripts/app/controllers/_plugin/keyboard_shortcuts.coffee
index 868f303e7..fa3d487a9 100644
--- a/app/assets/javascripts/app/controllers/widget/keyboard_shortcuts.coffee
+++ b/app/assets/javascripts/app/controllers/_plugin/keyboard_shortcuts.coffee
@@ -8,7 +8,7 @@ class App.KeyboardShortcutModal extends App.ControllerModal
constructor: ->
super
- @bind('keyboard_shortcuts_close', @close)
+ @controllerBind('keyboard_shortcuts_close', @close)
content: ->
App.view('keyboard_shortcuts')(
@@ -25,10 +25,11 @@ class App.KeyboardShortcutModal extends App.ControllerModal
return if window.location.hash isnt '#keyboard_shortcuts'
window.history.back()
-class App.KeyboardShortcutWidget extends Spine.Module
+class App.KeyboardShortcutWidget extends App.Controller
@include App.LogInclude
constructor: ->
+ super
@observerKeys()
@lastKey = undefined
@@ -38,6 +39,7 @@ class App.KeyboardShortcutWidget extends Spine.Module
)
observerKeys: =>
+ $(document).unbind('keydown.shortcuts')
navigationHotkeys = App.Browser.hotkeys()
areas = App.Config.get('keyboard_shortcuts')
@@ -54,7 +56,7 @@ class App.KeyboardShortcutWidget extends Spine.Module
modifier += shortcut.key
if shortcut.callback
@log 'debug', 'bind for', modifier
- $(document).bind('keydown', modifier, (e) =>
+ $(document).bind('keydown.shortcuts', modifier, (e) =>
e.preventDefault()
if @lastKey && @lastKey.modifier is modifier && @lastKey.time + 5500 > new Date().getTime()
@lastKey.count += 1
@@ -67,7 +69,7 @@ class App.KeyboardShortcutWidget extends Spine.Module
shortcut.callback(shortcut, @lastKey, modifier)
)
- App.Event.bind('global-shortcut', (e) ->
+ @controllerBind('global-shortcut', (e) ->
for area in areas
for item in area.content
for shortcut in item.shortcuts
@@ -75,7 +77,7 @@ class App.KeyboardShortcutWidget extends Spine.Module
shortcut.callback(shortcut)
)
-App.Config.set('keyboard_shortcuts', App.KeyboardShortcutWidget, 'Widgets')
+App.Config.set('keyboard_shortcuts', App.KeyboardShortcutWidget, 'Plugins')
App.Config.set(
'keyboard_shortcuts',
[
diff --git a/app/assets/javascripts/app/controllers/widget/maintenance.coffee b/app/assets/javascripts/app/controllers/_plugin/maintenance.coffee
similarity index 96%
rename from app/assets/javascripts/app/controllers/widget/maintenance.coffee
rename to app/assets/javascripts/app/controllers/_plugin/maintenance.coffee
index c8f0ca0fa..62f2ef9dd 100644
--- a/app/assets/javascripts/app/controllers/widget/maintenance.coffee
+++ b/app/assets/javascripts/app/controllers/_plugin/maintenance.coffee
@@ -1,9 +1,8 @@
-class Widget extends App.Controller
+class Maintenance extends App.Controller
serverRestarted: false
constructor: ->
super
-
- App.Event.bind(
+ @controllerBind(
'maintenance'
(data) =>
if data.type is 'message'
@@ -18,7 +17,6 @@ class Widget extends App.Controller
@maintanaceRestartAuto(data)
if data.type is 'restart_manual'
@maintanaceRestartManual(data)
- 'maintenance'
)
showMessage: (message = {}) =>
@@ -129,4 +127,4 @@ class Widget extends App.Controller
timeout ?= 1000
@delay(delay, timeout)
-App.Config.set('maintenance', Widget, 'Widgets')
+App.Config.set('maintenance', Maintenance, 'Plugins')
diff --git a/app/assets/javascripts/app/controllers/navigation.coffee b/app/assets/javascripts/app/controllers/_plugin/navigation.coffee
similarity index 93%
rename from app/assets/javascripts/app/controllers/navigation.coffee
rename to app/assets/javascripts/app/controllers/_plugin/navigation.coffee
index 7626cf799..157710a05 100644
--- a/app/assets/javascripts/app/controllers/navigation.coffee
+++ b/app/assets/javascripts/app/controllers/_plugin/navigation.coffee
@@ -1,9 +1,7 @@
-class App.Navigation extends App.ControllerWidgetPermanent
+class Navigation extends App.Controller
@extend App.PopoverProvidable
@registerAllPopovers()
- className: 'navigation vertical'
-
elements:
'#global-search': 'searchInput'
'.search': 'searchContainer'
@@ -33,36 +31,37 @@ class App.Navigation extends App.ControllerWidgetPermanent
)
# rerender view, e. g. on langauge change
- @bind 'ui:rerender', =>
+ @controllerBind('ui:rerender', =>
@renderMenu()
@renderPersonal()
+ )
# rerender menu
- @bind 'menu:render', =>
+ @controllerBind('menu:render', =>
@renderMenu()
+ )
# rerender menu
- @bind 'personal:render', =>
+ @controllerBind('personal:render', =>
@renderPersonal()
+ )
# update selected item
- @bind 'navupdate', (params) =>
+ @controllerBind('navupdate', (params) =>
@update(params)
-
- # rebuild nav bar with given user data
- @bind 'auth', (user) =>
- @render()
+ )
# fetch new recent viewed after collection change
- @bind 'RecentView::changed', =>
+ @controllerBind('RecentView::changed', =>
@delay(
=> @fetchRecentView()
1000
'recent-view-changed'
)
+ )
# bell on / bell off
- @bind 'bell', (data) =>
+ @controllerBind('bell', (data) =>
if data is 'on'
@$('.bell').addClass('show')
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
@$('.bell').removeClass('show')
+ )
release: =>
if @notificationWidget
@@ -187,13 +187,27 @@ class App.Navigation extends App.ControllerWidgetPermanent
@renderPopovers()
render: ->
-
user = App.Session.get()
- @html App.view('navigation')(
- user: user
- )
+ if _.isEmpty(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()
@@ -204,7 +218,7 @@ class App.Navigation extends App.ControllerWidgetPermanent
if @notificationWidget
@notificationWidget.remove()
@notificationWidget = new App.OnlineNotificationWidget()
- $('#app').append @notificationWidget.el
+ @appEl.append @notificationWidget.el
searchFocus: (e) =>
@clearDelay('emptyAndCloseDelayed')
@@ -490,6 +504,7 @@ class App.Navigation extends App.ControllerWidgetPermanent
App.RecentView.fetchFull(load, clear: true)
toggleNotifications: (e) ->
+ console.log('toggleNotifications', @notificationWidget)
e.stopPropagation()
@notificationWidget.toggle()
@@ -503,4 +518,4 @@ class App.Navigation extends App.ControllerWidgetPermanent
return
@navigate('#search')
-App.Config.set('navigation', App.Navigation, 'Navigations')
+App.Config.set('aaa_navigation', Navigation, 'Plugins')
diff --git a/app/assets/javascripts/app/controllers/widget/notify.coffee b/app/assets/javascripts/app/controllers/_plugin/notify.coffee
similarity index 83%
rename from app/assets/javascripts/app/controllers/widget/notify.coffee
rename to app/assets/javascripts/app/controllers/_plugin/notify.coffee
index 9228940e6..b275f13e2 100644
--- a/app/assets/javascripts/app/controllers/widget/notify.coffee
+++ b/app/assets/javascripts/app/controllers/_plugin/notify.coffee
@@ -1,4 +1,4 @@
-class App.Notify extends App.ControllerWidgetPermanent
+class App.Notify extends App.Controller
desktopNotify: {}
desktopNotifyCounter: 0
@@ -8,14 +8,14 @@ class App.Notify extends App.ControllerWidgetPermanent
constructor: ->
super
- @bind 'notify', (data) =>
+ @controllerBind('notify', (data) =>
@render(data)
-
- @bind 'notify:removeall', =>
+ )
+ @controllerBind('notify:removeall', =>
@log 'notify:removeall', @
@destroyAll()
-
- @bind 'notifyDesktop', (data) =>
+ )
+ @controllerBind('notifyDesktop', (data) =>
return if !window.Notification
if !data['icon']
@@ -48,13 +48,14 @@ class App.Notify extends App.ControllerWidgetPermanent
-> notification.close()
data.timeout || timeout
)
+ )
# request desktop notification after login
- @bind 'auth', (data) ->
+ @controllerBind('auth', (data) ->
if !_.isEmpty(data)
return if !window.Notification
window.Notification.requestPermission()
-
+ )
$(window).focus(
=>
for counter, notification of @desktopNotify
@@ -63,6 +64,9 @@ class App.Notify extends App.ControllerWidgetPermanent
render: (data) ->
+ if !$('#notify').get(0)
+ $('body').append('
')
+
# map noty naming
if data['type'] is 'info'
data['type'] = 'information'
@@ -73,7 +77,8 @@ class App.Notify extends App.ControllerWidgetPermanent
$.noty.closeAll()
if data.link
data.msg = '
' + data.msg + ''
- $('#notify').noty
+
+ $('#notify').noty(
text: data.msg
type: data.type
template: App.view('notify')
@@ -83,6 +88,7 @@ class App.Notify extends App.ControllerWidgetPermanent
close: 'animated fadeOutDown'
timeout: data.timeout || 3800
closeWith: ['click']
+ )
destroy: (e) ->
e.preventDefault()
@@ -90,4 +96,4 @@ class App.Notify extends App.ControllerWidgetPermanent
destroyAll: ->
$.noty.closeAll()
-App.Config.set('notify', App.Notify, 'Widgets')
+App.Config.set('notify', App.Notify, 'Plugins')
diff --git a/app/assets/javascripts/app/controllers/widget/remote_task.coffee b/app/assets/javascripts/app/controllers/_plugin/remote_task.coffee
similarity index 72%
rename from app/assets/javascripts/app/controllers/widget/remote_task.coffee
rename to app/assets/javascripts/app/controllers/_plugin/remote_task.coffee
index 62368517e..8470aef15 100644
--- a/app/assets/javascripts/app/controllers/widget/remote_task.coffee
+++ b/app/assets/javascripts/app/controllers/_plugin/remote_task.coffee
@@ -1,4 +1,4 @@
-class Widget extends App.Controller
+class RemoteTask extends App.Controller
serverRestarted: false
constructor: ->
super
@@ -12,4 +12,4 @@ class Widget extends App.Controller
'remote_task'
)
-App.Config.set('remote_task', Widget, 'Widgets')
+App.Config.set('remote_task', RemoteTask, 'Plugins')
diff --git a/app/assets/javascripts/app/controllers/widget/session_taken_over.coffee b/app/assets/javascripts/app/controllers/_plugin/session_taken_over.coffee
similarity index 86%
rename from app/assets/javascripts/app/controllers/widget/session_taken_over.coffee
rename to app/assets/javascripts/app/controllers/_plugin/session_taken_over.coffee
index a66e22720..7e2a0a8ea 100644
--- a/app/assets/javascripts/app/controllers/widget/session_taken_over.coffee
+++ b/app/assets/javascripts/app/controllers/_plugin/session_taken_over.coffee
@@ -1,12 +1,9 @@
-class Widget extends App.Controller
+class SessionTakeOver extends App.Controller
constructor: ->
super
- @bind()
-
- bind: ->
# only do takeover check after spool messages are finished
- App.Event.bind(
+ @controllerBind(
'spool:sent'
=>
@spoolSent = true
@@ -22,11 +19,10 @@ class Widget extends App.Controller
data:
taskbar_id: App.TaskManager.TaskbarId()
)
- 'maintenance'
)
# session take over message
- App.Event.bind(
+ @controllerBind(
'session:takeover'
(data) =>
@@ -48,7 +44,6 @@ class Widget extends App.Controller
forceReload: true
)
@disconnectClient()
- 'maintenance'
)
-App.Config.set('session_taken_over', Widget, 'Widgets')
+App.Config.set('session_taken_over', SessionTakeOver, 'Plugins')
diff --git a/app/assets/javascripts/app/controllers/widget/switch_back_to_user.coffee b/app/assets/javascripts/app/controllers/_plugin/switch_back_to_user.coffee
similarity index 70%
rename from app/assets/javascripts/app/controllers/widget/switch_back_to_user.coffee
rename to app/assets/javascripts/app/controllers/_plugin/switch_back_to_user.coffee
index b5b026afd..e32fe07eb 100644
--- a/app/assets/javascripts/app/controllers/widget/switch_back_to_user.coffee
+++ b/app/assets/javascripts/app/controllers/_plugin/switch_back_to_user.coffee
@@ -1,20 +1,24 @@
-class Widget extends App.ControllerWidgetOnDemand
+class SwitchBackToUser extends App.Controller
className: 'switchBackToUser'
+
constructor: ->
super
# start widget
- @bind 'app:ready', =>
+ @controllerBind('app:ready', =>
@render()
+ )
# e.g. if language has changed
- @bind 'ui:rerender', =>
+ @controllerBind('ui:rerender', =>
@render()
+ )
# remove widget
- @bind 'auth:logout', =>
+ @controllerBind('auth:logout', =>
App.Config.set('switch_back_to_possible', false)
@render()
+ )
render: (user) ->
@@ -47,4 +51,14 @@ class Widget extends App.ControllerWidgetOnDemand
800
)
-App.Config.set('switch_back_to_user', Widget, 'Widgets')
+ element: =>
+ $("##{@key}")
+
+ html: (raw) =>
+
+ # check if parent exists
+ if !$("##{@key}").get(0)
+ $('#app').before("
")
+ $("##{@key}").html raw
+
+App.Config.set('switch_back_to_user', SwitchBackToUser, 'Plugins')
diff --git a/app/assets/javascripts/app/controllers/widget/translation_inline.coffee b/app/assets/javascripts/app/controllers/_plugin/translation_inline.coffee
similarity index 94%
rename from app/assets/javascripts/app/controllers/widget/translation_inline.coffee
rename to app/assets/javascripts/app/controllers/_plugin/translation_inline.coffee
index b80fb772e..cb5505bca 100644
--- a/app/assets/javascripts/app/controllers/widget/translation_inline.coffee
+++ b/app/assets/javascripts/app/controllers/_plugin/translation_inline.coffee
@@ -1,9 +1,9 @@
-class Widget extends App.Controller
+class TranslationInline extends App.Controller
constructor: ->
super
@rebind()
- App.Event.bind('auth', => @rebind())
- App.Event.bind('i18n:inline_translation', => @toogle())
+ @controllerBind('auth', => @rebind())
+ @controllerBind('i18n:inline_translation', => @toogle())
rebind: =>
$(document).off('keydown.translation')
@@ -130,4 +130,4 @@ class Widget extends App.Controller
# rerender controllers
App.Event.trigger('ui:rerender')
-App.Config.set('translation_inline', Widget, 'Widgets')
+App.Config.set('translation_inline', TranslationInline, 'Plugins')
diff --git a/app/assets/javascripts/app/controllers/widget/translation_support.coffee b/app/assets/javascripts/app/controllers/_plugin/translation_support.coffee
similarity index 89%
rename from app/assets/javascripts/app/controllers/widget/translation_support.coffee
rename to app/assets/javascripts/app/controllers/_plugin/translation_support.coffee
index 6ee5318e9..189a4e96f 100644
--- a/app/assets/javascripts/app/controllers/widget/translation_support.coffee
+++ b/app/assets/javascripts/app/controllers/_plugin/translation_support.coffee
@@ -24,13 +24,14 @@ class TranslationSupport extends App.Controller
# show message
new Modal(percent: percent)
- @bind 'i18n:language:change', =>
+ @controllerBind('i18n:language:change', =>
@delay(check, 2500, 'translation_support')
-
- @bind 'auth:login', =>
+ )
+ @controllerBind('auth:login', =>
@delay(check, 2500, 'translation_support')
+ )
-App.Config.set( 'translaton_support', TranslationSupport, 'Widgets' )
+App.Config.set( 'translaton_support', TranslationSupport, 'Plugins' )
class Modal extends App.ControllerModal
buttonClose: true
diff --git a/app/assets/javascripts/app/controllers/_plugin/user_signup_check.coffee b/app/assets/javascripts/app/controllers/_plugin/user_signup_check.coffee
new file mode 100644
index 000000000..359840909
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/_plugin/user_signup_check.coffee
@@ -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 += '
'
+ 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')
diff --git a/app/assets/javascripts/app/controllers/_profile/avatar.coffee b/app/assets/javascripts/app/controllers/_profile/avatar.coffee
index 3fc76751d..d176bbca2 100644
--- a/app/assets/javascripts/app/controllers/_profile/avatar.coffee
+++ b/app/assets/javascripts/app/controllers/_profile/avatar.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class ProfileAvatar extends App.ControllerSubContent
requiredPermission: 'user_preferences.avatar'
header: 'Avatar'
elements:
@@ -145,7 +145,7 @@ class Index extends App.ControllerSubContent
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
buttonClose: true
diff --git a/app/assets/javascripts/app/controllers/_profile/calendar_subscriptions.coffee b/app/assets/javascripts/app/controllers/_profile/calendar_subscriptions.coffee
index d45545391..e38b75a37 100644
--- a/app/assets/javascripts/app/controllers/_profile/calendar_subscriptions.coffee
+++ b/app/assets/javascripts/app/controllers/_profile/calendar_subscriptions.coffee
@@ -1,4 +1,4 @@
-class CalendarSubscriptions extends App.ControllerSubContent
+class ProfileCalendarSubscriptions extends App.ControllerSubContent
requiredPermission: 'user_preferences.calendar+ticket.agent'
header: 'Calendar'
elements:
@@ -90,4 +90,4 @@ class CalendarSubscriptions extends App.ControllerSubContent
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')
diff --git a/app/assets/javascripts/app/controllers/_profile/devices.coffee b/app/assets/javascripts/app/controllers/_profile/devices.coffee
index bbe33021c..f4bbd4c78 100644
--- a/app/assets/javascripts/app/controllers/_profile/devices.coffee
+++ b/app/assets/javascripts/app/controllers/_profile/devices.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class ProfileDevices extends App.ControllerSubContent
requiredPermission: 'user_preferences.device'
header: 'Devices'
events:
@@ -55,4 +55,4 @@ class Index extends App.ControllerSubContent
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')
diff --git a/app/assets/javascripts/app/controllers/_profile/language.coffee b/app/assets/javascripts/app/controllers/_profile/language.coffee
index efb22a23c..53458863c 100644
--- a/app/assets/javascripts/app/controllers/_profile/language.coffee
+++ b/app/assets/javascripts/app/controllers/_profile/language.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class ProfileLanguage extends App.ControllerSubContent
requiredPermission: 'user_preferences.language'
header: 'Language'
events:
@@ -19,7 +19,7 @@ class Index extends App.ControllerSubContent
]
@form = new App.ControllerForm(
- el: html.find('.language_item')
+ el: html.find('.js-language')
model: { configure_attributes: configure_attributes }
autofocus: false
)
@@ -69,4 +69,4 @@ class Index extends App.ControllerSubContent
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')
diff --git a/app/assets/javascripts/app/controllers/_profile/linked_accounts.coffee b/app/assets/javascripts/app/controllers/_profile/linked_accounts.coffee
index f3556ff27..11d48a27d 100644
--- a/app/assets/javascripts/app/controllers/_profile/linked_accounts.coffee
+++ b/app/assets/javascripts/app/controllers/_profile/linked_accounts.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class ProfileLinkedAccounts extends App.ControllerSubContent
requiredPermission: 'user_preferences.linked_accounts'
header: 'Linked Accounts'
events:
@@ -59,7 +59,7 @@ class Index extends App.ControllerSubContent
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', {
facebook:
url: '/auth/facebook'
diff --git a/app/assets/javascripts/app/controllers/_profile/notification.coffee b/app/assets/javascripts/app/controllers/_profile/notification.coffee
index b0c71aa99..03cf17993 100644
--- a/app/assets/javascripts/app/controllers/_profile/notification.coffee
+++ b/app/assets/javascripts/app/controllers/_profile/notification.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class ProfileNotification extends App.ControllerSubContent
requiredPermission: 'user_preferences.notifications+ticket.agent'
header: 'Notifications'
events:
@@ -192,4 +192,4 @@ class Index extends App.ControllerSubContent
return if !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')
diff --git a/app/assets/javascripts/app/controllers/_profile/out_of_office.coffee b/app/assets/javascripts/app/controllers/_profile/out_of_office.coffee
index 8f796f715..79c6c37dc 100644
--- a/app/assets/javascripts/app/controllers/_profile/out_of_office.coffee
+++ b/app/assets/javascripts/app/controllers/_profile/out_of_office.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class ProfileOutOfOffice extends App.ControllerSubContent
requiredPermission: 'user_preferences.out_of_office+ticket.agent'
header: 'Out of Office'
events:
@@ -161,4 +161,4 @@ class Index extends App.ControllerSubContent
msg: App.i18n.translateContent(message)
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')
diff --git a/app/assets/javascripts/app/controllers/_profile/password.coffee b/app/assets/javascripts/app/controllers/_profile/password.coffee
index 5d60c79f6..e19a79ed5 100644
--- a/app/assets/javascripts/app/controllers/_profile/password.coffee
+++ b/app/assets/javascripts/app/controllers/_profile/password.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class ProfilePassword extends App.ControllerSubContent
requiredPermission: 'user_preferences.password'
header: 'Password'
events:
@@ -78,4 +78,4 @@ class Index extends App.ControllerSubContent
removeAll: true
@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')
diff --git a/app/assets/javascripts/app/controllers/_profile/token_access.coffee b/app/assets/javascripts/app/controllers/_profile/token_access.coffee
index 1ef5635ae..294b9f73e 100644
--- a/app/assets/javascripts/app/controllers/_profile/token_access.coffee
+++ b/app/assets/javascripts/app/controllers/_profile/token_access.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class ProfileTokenAccess extends App.ControllerSubContent
requiredPermission: 'user_preferences.access_token'
header: 'Token Access'
events:
@@ -144,4 +144,4 @@ class Create extends App.ControllerModal
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')
diff --git a/app/assets/javascripts/app/controllers/_settings/form.coffee b/app/assets/javascripts/app/controllers/_settings/form.coffee
index b3e9b0b57..895363a16 100644
--- a/app/assets/javascripts/app/controllers/_settings/form.coffee
+++ b/app/assets/javascripts/app/controllers/_settings/form.coffee
@@ -76,19 +76,19 @@ class App.SettingsForm extends App.Controller
ui.formEnable(e)
count -= 1
if count == 0
- App.Event.trigger 'notify', {
+ App.Event.trigger('notify', {
type: 'success'
msg: App.i18n.translateContent('Update successful!')
timeout: 2000
- }
+ })
# rerender ui || get new collections and session data
App.Setting.preferencesPost(@)
fail: (settings, details) ->
- App.Event.trigger 'notify', {
+ App.Event.trigger('notify', {
type: 'error'
msg: App.i18n.translateContent(details.error_human || details.error || 'Unable to update object!')
timeout: 2000
- }
+ })
)
diff --git a/app/assets/javascripts/app/controllers/_ui_element/ticket_perform_action.coffee b/app/assets/javascripts/app/controllers/_ui_element/ticket_perform_action.coffee
index 9536a56fd..42b80571b 100644
--- a/app/assets/javascripts/app/controllers/_ui_element/ticket_perform_action.coffee
+++ b/app/assets/javascripts/app/controllers/_ui_element/ticket_perform_action.coffee
@@ -494,7 +494,6 @@ class App.UiElement.ticket_perform_action
elementRow.find('.js-setArticle').empty()
name = "#{attribute.name}::article.#{articleType}"
- console.log('meta', meta)
selection = App.UiElement.select.render(
name: "#{name}::internal"
multiple: false
diff --git a/app/assets/javascripts/app/controllers/_ui_element/user_permission.coffee b/app/assets/javascripts/app/controllers/_ui_element/user_permission.coffee
index eecfe4e67..1f952812b 100644
--- a/app/assets/javascripts/app/controllers/_ui_element/user_permission.coffee
+++ b/app/assets/javascripts/app/controllers/_ui_element/user_permission.coffee
@@ -84,8 +84,6 @@ class App.UiElement.user_permission
input = $(@).find('input')
upcoming_state = !input.prop('checked')
value = input.val()
- console.log(upcoming_state)
- console.log(value)
if value is 'full' and upcoming_state is true
$(@).closest('tr').find('input:not([value=full])').prop('checked', false)
diff --git a/app/assets/javascripts/app/controllers/agent_ticket_create.coffee b/app/assets/javascripts/app/controllers/agent_ticket_create.coffee
index 44774e636..890282624 100644
--- a/app/assets/javascripts/app/controllers/agent_ticket_create.coffee
+++ b/app/assets/javascripts/app/controllers/agent_ticket_create.coffee
@@ -54,14 +54,14 @@ class App.TicketCreate extends App.Controller
@bindId = App.TicketCreateCollection.one(load)
# rerender view, e. g. on langauge change
- @bind('ui:rerender', =>
+ @controllerBind('ui:rerender', =>
return if !@authenticateCheck()
@renderQueue()
@tokanice()
)
# listen to rerender sidebars
- @bind('ui::ticket::sidebarRerender', (data) =>
+ @controllerBind('ui::ticket::sidebarRerender', (data) =>
return if data.taskKey isnt @taskKey
return if !@sidebarWidget
@sidebarWidget.render(@params())
@@ -169,11 +169,11 @@ class App.TicketCreate extends App.Controller
show: =>
@navupdate("#ticket/create/id/#{@id}#{@split}", type: 'menu')
@autosaveStart()
- @bind('ticket_create_rerender', (template) => @renderQueue(template))
+ @controllerBind('ticket_create_rerender', (template) => @renderQueue(template))
hide: =>
@autosaveStop()
- @unbind('ticket_create_rerender', (template) => @renderQueue(template))
+ @controllerUnbind('ticket_create_rerender', (template) => @renderQueue(template))
changed: =>
formCurrent = @formParam( @$('.ticket-create') )
diff --git a/app/assets/javascripts/app/controllers/api.coffee b/app/assets/javascripts/app/controllers/api.coffee
index 0a325e3a5..af23fa0c5 100644
--- a/app/assets/javascripts/app/controllers/api.coffee
+++ b/app/assets/javascripts/app/controllers/api.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class Api extends App.ControllerSubContent
requiredPermission: 'admin.api'
header: 'API'
events:
@@ -193,4 +193,4 @@ class ViewAppTokenModal extends App.ControllerModal
@$('.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')
diff --git a/app/assets/javascripts/app/controllers/calendar.coffee b/app/assets/javascripts/app/controllers/calendar.coffee
index 0b7007afa..50c7975c5 100644
--- a/app/assets/javascripts/app/controllers/calendar.coffee
+++ b/app/assets/javascripts/app/controllers/calendar.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class Calendar extends App.ControllerSubContent
requiredPermission: 'admin.calendar'
header: 'Calendars'
events:
@@ -121,4 +121,4 @@ class Index extends App.ControllerSubContent
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')
diff --git a/app/assets/javascripts/app/controllers/chat.coffee b/app/assets/javascripts/app/controllers/chat.coffee
index 54be8cfa7..da4a38a16 100644
--- a/app/assets/javascripts/app/controllers/chat.coffee
+++ b/app/assets/javascripts/app/controllers/chat.coffee
@@ -42,7 +42,7 @@ class App.CustomerChat extends App.Controller
@on('layout-has-changed', @propagateLayoutChange)
# update navbar on new status
- @bind('chat_status_agent', (data) =>
+ @controllerBind('chat_status_agent', (data) =>
if data.assets
App.Collection.loadAssets(data.assets)
@meta = data
@@ -52,19 +52,19 @@ class App.CustomerChat extends App.Controller
)
# add new chat window
- @bind('chat_session_start', (data) =>
+ @controllerBind('chat_session_start', (data) =>
if data.session
@addChat(data.session)
)
# 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')
# rerender view, e. g. on langauge change
- @bind('ui:rerender chat:rerender', =>
+ @controllerBind('ui:rerender chat:rerender', =>
return if !@authenticateCheck()
for session_id, chat of @chatWindows
chat.el.remove()
@@ -122,8 +122,8 @@ class App.CustomerChat extends App.Controller
show: (params) =>
- @title 'Customer Chat', true
- @navupdate '#customer_chat'
+ @title('Customer Chat', true)
+ @navupdate('#customer_chat')
if params.session_id
callback = (session) =>
@@ -433,34 +433,34 @@ class ChatWindow extends App.Controller
@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.self_written
@showWritingLoader()
)
- @bind('chat_session_message', (data) =>
+ @controllerBind('chat_session_message', (data) =>
return if data.session_id isnt @session.session_id
return if data.self_written
@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.self_written
@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.self_written
@addStatusMessage("
#{data.realname} left the conversation")
@goOffline()
)
- @bind('chat_session_closed', (data) =>
+ @controllerBind('chat_session_closed', (data) =>
return if data.session_id isnt @session.session_id
return if data.self_written
@addStatusMessage("
#{data.realname} closed the conversation")
@goOffline()
)
- @bind('chat_focus', (data) =>
+ @controllerBind('chat_focus', (data) =>
return if data.session_id isnt @session.session_id
@focus()
)
@@ -572,7 +572,7 @@ class ChatWindow extends App.Controller
onTransitionend: (event) =>
# chat window is done with animation - adjust scroll-bars
# of sibling chat windows
- @trigger 'layout-has-changed'
+ @trigger('layout-has-changed')
if event.data and event.data.callback
event.data.callback()
@@ -601,7 +601,7 @@ class ChatWindow extends App.Controller
@removeCallback(@session.session_id)
release: =>
- @trigger 'closed'
+ @trigger('closed')
@el.remove()
super
diff --git a/app/assets/javascripts/app/controllers/clues.coffee b/app/assets/javascripts/app/controllers/clues.coffee
index 81037e9f0..d30eff91a 100644
--- a/app/assets/javascripts/app/controllers/clues.coffee
+++ b/app/assets/javascripts/app/controllers/clues.coffee
@@ -1,4 +1,4 @@
-class Index extends App.Controller
+class Clues extends App.Controller
constructor: ->
super
@navupdate '#', true
@@ -6,7 +6,7 @@ class Index extends App.Controller
clues: =>
new App.FirstStepsClues(
- el: @el
+ appEl: @appEl
onComplete: =>
App.Ajax.request(
id: 'preferences'
@@ -18,4 +18,4 @@ class Index extends App.Controller
@navigate '#'
)
-App.Config.set('clues', Index, 'Routes')
+App.Config.set('clues', Clues, 'Routes')
diff --git a/app/assets/javascripts/app/controllers/cti.coffee b/app/assets/javascripts/app/controllers/cti.coffee
index 58ee2ae46..743f92ce5 100644
--- a/app/assets/javascripts/app/controllers/cti.coffee
+++ b/app/assets/javascripts/app/controllers/cti.coffee
@@ -23,13 +23,13 @@ class App.CTI extends App.Controller
@meta.active = preferences.cti || false
@load()
- @bind('cti_list_push', (data) =>
+ @controllerBind('cti_list_push', (data) =>
delay = =>
@load()
@delay(delay, 500, 'cti_list_push_render')
'cti_list_push'
)
- @bind('cti_event', (data) =>
+ @controllerBind('cti_event', (data) =>
return if data.state isnt 'newCall'
return if data.direction isnt 'in'
return if @switch() isnt true
@@ -37,7 +37,7 @@ class App.CTI extends App.Controller
@notify(data)
'cti_event'
)
- @bind('menu:render', (data) =>
+ @controllerBind('menu:render', (data) =>
return if @switch() isnt true
localHtml = ''
for item in @ringingCalls()
@@ -53,26 +53,25 @@ class App.CTI extends App.Controller
user_id = $(e.currentTarget).data('user-id')
if user_id
user = App.User.find(user_id)
- console.log('user_id', user_id, user)
@newTicket(user)
)
)
- @bind('auth', (data) =>
+ @controllerBind('auth', (data) =>
@meta.counter = 0
)
- @bind('cti:reload', =>
+ @controllerBind('cti:reload', =>
@load()
'cti_reload'
)
# rerender view, e. g. on langauge change
- @bind('ui:rerender', =>
+ @controllerBind('ui:rerender', =>
@render()
'cti_rerender'
)
# after a new websocket connection, load again
- @bind('spool:sent', =>
+ @controllerBind('spool:sent', =>
if @initSpoolSent
@load()
return
@@ -280,7 +279,7 @@ class App.CTI extends App.Controller
currentPosition: =>
@$('.main').scrollTop()
-class WidgetAvatar extends App.ObserverController
+class WidgetAvatar extends App.ControllerObserver
@extend App.PopoverProvidable
@registerPopovers 'User'
diff --git a/app/assets/javascripts/app/controllers/customer_ticket_create.coffee b/app/assets/javascripts/app/controllers/customer_ticket_create.coffee
index b7be104c8..f7f7d5e76 100644
--- a/app/assets/javascripts/app/controllers/customer_ticket_create.coffee
+++ b/app/assets/javascripts/app/controllers/customer_ticket_create.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerContent
+class CustomerTicketCreate extends App.ControllerAppContent
requiredPermission: 'ticket.customer'
events:
'submit form': 'submit',
@@ -211,7 +211,7 @@ class Index extends App.ControllerContent
return
@formEnable(@$('.js-submit'), 'button')
-App.Config.set('customer_ticket_new', Index, 'Routes')
+App.Config.set('customer_ticket_new', CustomerTicketCreate, 'Routes')
App.Config.set('CustomerTicketNew', {
prio: 8003,
parent: '#new',
diff --git a/app/assets/javascripts/app/controllers/dashboard.coffee b/app/assets/javascripts/app/controllers/dashboard.coffee
index 5a8de62e5..bc7ef4f14 100644
--- a/app/assets/javascripts/app/controllers/dashboard.coffee
+++ b/app/assets/javascripts/app/controllers/dashboard.coffee
@@ -15,9 +15,10 @@ class App.Dashboard extends App.Controller
@render()
# rerender view, e. g. on language change
- @bind 'ui:rerender', =>
+ @controllerBind('ui:rerender', =>
return if !@authenticateCheck()
@render()
+ )
@mayBeClues()
@@ -71,12 +72,12 @@ class App.Dashboard extends App.Controller
# incase of being only customer, redirect to default router
if @permissionCheck('ticket.customer') && !@permissionCheck('ticket.agent')
- @navigate '#ticket/view', true
+ @navigate '#ticket/view', { hideCurrentLocationFromHistory: true }
return
# incase of being only admin, redirect to admin interface (show no empty white content page)
if !@permissionCheck('ticket.customer') && !@permissionCheck('ticket.agent') && @permissionCheck('admin')
- @navigate '#manage', true
+ @navigate '#manage', { hideCurrentLocationFromHistory: true }
return
# set title
diff --git a/app/assets/javascripts/app/controllers/default_route.coffee b/app/assets/javascripts/app/controllers/default_route.coffee
index b7a5e551b..4a09aa0aa 100644
--- a/app/assets/javascripts/app/controllers/default_route.coffee
+++ b/app/assets/javascripts/app/controllers/default_route.coffee
@@ -9,19 +9,19 @@ class DefaultRouter extends App.Controller
# check if import is active
if !@Config.get('system_init_done') && @Config.get('import_mode')
- @navigate '#import', true
+ @navigate '#import', { hideCurrentLocationFromHistory: true }
return
# route to getting started screen
if !@Config.get('system_init_done')
- @navigate '#getting_started', true
+ @navigate '#getting_started', { hideCurrentLocationFromHistory: true }
return
if @Config.get('default_controller')
- @navigate @Config.get('default_controller'), true
+ @navigate @Config.get('default_controller'), { hideCurrentLocationFromHistory: true }
return
- @navigate '#dashboard', true
+ @navigate '#dashboard', { hideCurrentLocationFromHistory: true }
App.Config.set('', DefaultRouter, 'Routes')
App.Config.set('/', DefaultRouter, 'Routes')
diff --git a/app/assets/javascripts/app/controllers/email_verify.coffee b/app/assets/javascripts/app/controllers/email_verify.coffee
index ae0c5b7d4..106c2442f 100644
--- a/app/assets/javascripts/app/controllers/email_verify.coffee
+++ b/app/assets/javascripts/app/controllers/email_verify.coffee
@@ -1,4 +1,4 @@
-class Index extends App.Controller
+class EmailVerify extends App.Controller
constructor: ->
super
@verifyCall()
@@ -10,23 +10,47 @@ class Index extends App.Controller
url: "#{@apiPath}/users/email_verify"
data: JSON.stringify(token: @token)
processData: true
- success: (data, status, xhr) =>
- App.Auth.loginCheck()
- @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
+ success: @success
+ error: @error
)
-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')
diff --git a/app/assets/javascripts/app/controllers/getting_started.coffee b/app/assets/javascripts/app/controllers/getting_started.coffee
index 2f8fde786..4c0142079 100644
--- a/app/assets/javascripts/app/controllers/getting_started.coffee
+++ b/app/assets/javascripts/app/controllers/getting_started.coffee
@@ -1,4 +1,4 @@
-class Index extends App.WizardFullScreen
+class GettingStarted extends App.ControllerWizardFullScreen
constructor: ->
super
@@ -21,9 +21,6 @@ class Index extends App.WizardFullScreen
@fetch()
- release: =>
- @el.removeClass('fit getstarted')
-
fetch: ->
# get data
@@ -51,1039 +48,9 @@ class Index extends App.WizardFullScreen
)
render: ->
- @html App.view('getting_started/intro')()
+ @replaceWith App.view('getting_started/intro')()
renderAutoWizard: ->
- @html App.view('getting_started/auto_wizard_enabled')()
+ @replaceWith App.view('getting_started/auto_wizard_enabled')()
-App.Config.set('getting_started', Index, 'Routes')
-
-class AutoWizard extends App.WizardFullScreen
- 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()
-
- release: =>
- @el.removeClass('fit getstarted')
-
- 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
- @navigate '#'
- return
-
- # auto wizard setup was successful
- if data.auto_wizard_success is true
-
- # login check / get session user
- delay = =>
- App.Auth.loginCheck()
- @navigate '#'
- @delay(delay, 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
- @navigate '#login'
- )
-
- renderFailed: (data) ->
- @html App.view('getting_started/auto_wizard_failed')(data)
-
- renderSplash: ->
- @html App.view('getting_started/auto_wizard_splash')()
-
- renderToken: ->
- @html App.view('getting_started/auto_wizard_enabled')()
-
-App.Config.set('getting_started/auto_wizard', AutoWizard, 'Routes')
-App.Config.set('getting_started/auto_wizard/:token', AutoWizard, 'Routes')
-
-class Admin extends App.WizardFullScreen
- 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()
-
- release: =>
- @el.removeClass('fit getstarted')
-
- 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'
- # return
-
- # check if import is active
- if data.import_mode == true
- @navigate "#import/#{data.import_backend}"
- return
-
- # load group collection
- App.Collection.load(type: 'Group', data: data.groups)
-
- # render page
- @render()
- )
-
- render: ->
-
- @html 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'
-
-App.Config.set('getting_started/admin', Admin, 'Routes')
-
-class Base extends App.WizardFullScreen
- elements:
- '.logo-preview': 'logoPreview'
-
- events:
- 'submit form': 'submit'
- 'change .js-upload': 'onLogoPick'
-
- constructor: ->
- super
-
- # redirect if we are not admin
- if !@permissionCheck('admin.wizard')
- @navigate '#'
- return
-
- # set title
- @title 'Configure Base'
-
- @fetch()
-
- release: =>
- @el.removeClass('fit getstarted')
-
- 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}"
- return
-
- # import config options
- if data.config
- for key, value of data.config
- App.Config.set(key, value)
-
- # render page
- @render()
- )
-
- render: ->
-
- fqdn = App.Config.get('fqdn')
- http_type = App.Config.get('http_type')
- if !fqdn || fqdn is 'zammad.example.com'
- url = window.location.origin
- else
- url = "#{http_type}://#{fqdn}"
-
- organization = App.Config.get('organization')
- @html App.view('getting_started/base')(
- url: url
- logoUrl: @logoUrl()
- organization: organization
- )
- @$('input, select').first().focus()
-
- onLogoPick: (event) =>
- reader = new FileReader()
-
- reader.onload = (e) =>
- @logoPreview.attr('src', e.target.result)
-
- file = event.target.files[0]
-
- @hideAlerts()
-
- # if no file is given, about in file upload was used
- if !file
- return
-
- maxSiteInMb = 8
- if file.size && file.size > 1024 * 1024 * maxSiteInMb
- @showAlert( 'logo', App.i18n.translateInline('File too big, max. %s MB allowed.', maxSiteInMb ))
- @logoPreview.attr('src', '')
- return
-
- reader.readAsDataURL(file)
-
- submit: (e) =>
- e.preventDefault()
- @hideAlerts()
- @disable(e)
-
- @params = @formParam(e.target)
- @params.logo = @logoPreview.attr('src')
- @params.locale_default = App.i18n.detectBrowserLocale()
- @params.timezone_default = App.i18n.detectBrowserTimezone()
-
- store = (logoResizeDataUrl) =>
- @params.logo_resize = logoResizeDataUrl
- @ajax(
- id: 'getting_started_base'
- type: 'POST'
- url: "#{@apiPath}/getting_started/base"
- data: JSON.stringify(@params)
- processData: true
- success: (data, status, xhr) =>
- if data.result is 'ok'
- for key, value of data.settings
- App.Config.set(key, value)
- if App.Config.get('system_online_service')
- @navigate 'getting_started/channel/email_pre_configured'
- else
- @navigate 'getting_started/email_notification'
- else
- for key, value of data.messages
- @showAlert(key, value)
- @enable(e)
- fail: =>
- @enable(e)
- )
-
- # add resized image
- App.ImageService.resizeForApp(@params.logo, @logoPreview.width(), @logoPreview.height(), store)
-
- hideAlerts: =>
- @$('.form-group').removeClass('has-error')
- @$('.alert').addClass('hide')
-
- showAlert: (field, message) =>
- @$("[name=#{field}]").closest('.form-group').addClass('has-error')
- @$("[name=#{field}]").closest('.form-group').find('.alert').removeClass('hide').text( App.i18n.translateInline( message ) )
-
-App.Config.set('getting_started/base', Base, 'Routes')
-
-class EmailNotification extends App.WizardFullScreen
- events:
- 'change .js-outbound [name=adapter]': 'toggleOutboundAdapter'
- 'submit .js-outbound': 'submit'
-
- constructor: ->
- super
-
- # redirect if we are not admin
- if !@permissionCheck('admin.wizard')
- @navigate '#'
- return
-
- # set title
- @title 'Email Notifications'
-
- @channelDriver =
- email:
- inbound: {}
- outbound: {}
-
- @fetch()
-
- release: =>
- @el.removeClass('fit getstarted')
-
- 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}"
- return
-
- @channelDriver = data.channel_driver
-
- # render page
- @render()
- )
-
- render: ->
- @html App.view('getting_started/email_notification')()
- configureAttributesOutbound = [
- { name: 'adapter', display: 'Send Mails via', tag: 'select', multiple: false, null: false, options: @channelDriver.email.outbound },
- ]
- new App.ControllerForm(
- el: @$('.base-outbound-type')
- model:
- configure_attributes: configureAttributesOutbound
- className: ''
- params:
- adapter: 'sendmail'
- )
- @toggleOutboundAdapter()
-
- toggleOutboundAdapter: =>
-
- # show used backend
- @el.find('.base-outbound-settings').html('')
- adapter = @$('.js-outbound [name=adapter]').val()
- if adapter is 'smtp'
- configureAttributesOutbound = [
- { name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, autofocus: true },
- { name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, autocomplete: 'off' },
- { name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: true, autocapitalize: false, autocomplete: 'off', single: true },
- { name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 6, null: true, autocapitalize: false },
- ]
- @form = new App.ControllerForm(
- el: @$('.base-outbound-settings')
- model:
- configure_attributes: configureAttributesOutbound
- className: ''
- )
-
- submit: (e) =>
- e.preventDefault()
-
- # get params
- params = @formParam(e.target)
- params['email'] = 'me@localhost'
- @disable(e)
-
- @showSlide('js-test')
-
- @ajax(
- id: 'email_notification'
- type: 'POST'
- url: "#{@apiPath}/channels_email_notification"
- data: JSON.stringify(params)
- processData: true
- success: (data, status, xhr) =>
- if data.result is 'ok'
- for key, value of data.settings
- App.Config.set(key, value)
- if App.Config.get('system_online_service')
- @navigate 'getting_started/channel/email_pre_configured'
- else
- @navigate 'getting_started/channel'
- else
- @showSlide('js-outbound')
- @showAlert('js-outbound', data.message_human || data.message )
- @showInvalidField('js-outbound', data.invalid_field)
- @enable(e)
-
- fail: =>
- @showSlide('js-outbound')
- @showAlert('js-outbound', data.message_human || data.message )
- @showInvalidField('js-outbound', data.invalid_field)
- @enable(e)
- )
-
-App.Config.set('getting_started/email_notification', EmailNotification, 'Routes')
-
-class Channel extends App.WizardFullScreen
- constructor: ->
- super
-
- # redirect if we are not admin
- if !@permissionCheck('admin.wizard')
- @navigate '#'
- return
-
- # set title
- @title 'Connect Channels'
-
- @adapters = [
- {
- name: 'Email'
- class: 'email'
- link: '#getting_started/channel/email'
- },
- ]
-
- @fetch()
-
- release: =>
- @el.removeClass('fit getstarted')
-
- 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}"
- return
-
- # render page
- @render()
- )
-
- render: ->
- @html App.view('getting_started/channel')(
- adapters: @adapters
- )
-
-App.Config.set('getting_started/channel', Channel, 'Routes')
-
-class ChannelEmailPreConfigured extends App.WizardFullScreen
- constructor: ->
- super
-
- # redirect if we are not admin
- if !@permissionCheck('admin.wizard')
- @navigate '#'
- return
-
- # set title
- @title 'Connect Channels'
-
- @fetch()
-
- release: =>
- @el.removeClass('fit getstarted')
-
- 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}"
- return
-
- # render page
- @render(data)
- )
-
- render: (data) ->
- @html App.view('getting_started/email_pre_configured')(
- data
- )
-
-App.Config.set('getting_started/channel/email_pre_configured', ChannelEmailPreConfigured, 'Routes')
-
-class ChannelEmail extends App.WizardFullScreen
- events:
- 'submit .js-intro': 'probeBasedOnIntro'
- 'submit .js-inbound': 'probeInbound'
- 'change .js-outbound [name=adapter]': 'toggleOutboundAdapter'
- 'submit .js-outbound': 'probleOutbound'
- 'click .js-goToSlide': 'goToSlide'
-
- constructor: ->
- super
-
- # redirect if we are not admin
- if !@permissionCheck('admin.wizard')
- @navigate '#'
- return
-
- # set title
- @title 'Email Account'
-
- # store account settings
- @account =
- inbound: {}
- outbound: {}
- meta: {}
-
- @channelDriver =
- email:
- inbound: {}
- outbound: {}
-
- @fetch()
-
- release: =>
- @el.removeClass('fit getstarted')
-
- 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}"
- return
-
- @channelDriver = data.channel_driver
-
- # render page
- @render()
- )
-
- render: ->
-
- @html App.view('getting_started/email')()
- @showSlide('js-intro')
-
- # outbound
- configureAttributesOutbound = [
- { name: 'adapter', display: 'Send Mails via', tag: 'select', multiple: false, null: false, options: @channelDriver.email.outbound },
- ]
- new App.ControllerForm(
- el: @$('.base-outbound-type')
- model:
- configure_attributes: configureAttributesOutbound
- className: ''
- params:
- adapter: @account.outbound.adapter || 'smtp'
- )
- @toggleOutboundAdapter()
-
- # inbound
- configureAttributesInbound = [
- { name: 'adapter', display: 'Type', tag: 'select', multiple: false, null: false, options: @channelDriver.email.inbound },
- { name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false },
- { name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, autocomplete: 'off', },
- { name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: false, autocapitalize: false, autocomplete: 'off', single: true },
- { name: 'options::ssl', display: 'SSL/STARTTLS', tag: 'boolean', null: true, options: { true: 'yes', false: 'no' }, default: true, translate: true, item_class: 'formGroup--halfSize' },
- { name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 6, null: true, autocapitalize: false, default: '993', item_class: 'formGroup--halfSize' },
- { name: 'options::folder', display: 'Folder', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, item_class: 'formGroup--halfSize' },
- { name: 'options::keep_on_server', display: 'Keep messages on server', tag: 'boolean', null: true, options: { true: 'yes', false: 'no' }, translate: true, default: false, item_class: 'formGroup--halfSize' },
- ]
-
- showHideFolder = (params, attribute, attributes, classname, form, ui) ->
- return if !params
- if params.adapter is 'imap'
- ui.show('options::folder')
- ui.show('options::keep_on_server')
- return
- ui.hide('options::folder')
- ui.hide('options::keep_on_server')
-
- handlePort = (params, attribute, attributes, classname, form, ui) ->
- return if !params
- return if !params.options
- currentPort = @$('.base-inbound-settings [name="options::port"]').val()
- if params.options.ssl is true
- if !currentPort
- @$('.base-inbound-settings [name="options::port"]').val('993')
- return
- if params.options.ssl is false
- if !currentPort || currentPort is '993'
- @$('.base-inbound-settings [name="options::port"]').val('143')
- return
-
- new App.ControllerForm(
- el: @$('.base-inbound-settings')
- model:
- configure_attributes: configureAttributesInbound
- className: ''
- params: @account.inbound
- handlers: [
- showHideFolder,
- handlePort,
- ]
- )
-
- toggleOutboundAdapter: =>
-
- # fill user / password based on intro info
- channel_used = { options: {} }
- if @account['meta']
- channel_used['options']['user'] = @account['meta']['email']
- channel_used['options']['password'] = @account['meta']['password']
- channel_used['options']['folder'] = @account['meta']['folder']
- channel_used['options']['keep_on_server'] = @account['meta']['keep_on_server']
-
- # show used backend
- @$('.base-outbound-settings').html('')
- adapter = @$('.js-outbound [name=adapter]').val()
- if adapter is 'smtp'
- configureAttributesOutbound = [
- { name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, autofocus: true },
- { name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, autocomplete: 'off', },
- { name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: true, autocapitalize: false, autocomplete: 'off', single: true },
- { name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 6, null: true, autocapitalize: false },
- ]
- @form = new App.ControllerForm(
- el: @$('.base-outbound-settings')
- model:
- configure_attributes: configureAttributesOutbound
- className: ''
- params: @account.outbound
- )
-
- probeBasedOnIntro: (e) =>
- e.preventDefault()
- params = @formParam(e.target)
-
- # remember account settings
- @account.meta = params
-
- @disable(e)
- @$('.js-probe .js-email').text(params.email)
- @showSlide('js-probe')
-
- @ajax(
- id: 'email_probe'
- type: 'POST'
- url: "#{@apiPath}/channels_email_probe"
- data: JSON.stringify(params)
- processData: true
- success: (data, status, xhr) =>
- if data.result is 'ok'
- if data.setting
- for key, value of data.setting
- @account[key] = value
-
- if data.content_messages && data.content_messages > 0 && (!@account['inbound']['options'] || @account['inbound']['options']['keep_on_server'] isnt true)
- @probeInboundMessagesFound(data, true)
- @probeInboundArchive(data)
- else
- @verify(@account)
-
- else if data.result is 'duplicate'
- @showSlide('js-intro')
- @showAlert('js-intro', 'Account already exists!' )
- else
- @showSlide('js-inbound')
- @showAlert('js-inbound', 'Unable to detect your server settings. Manual configuration needed.' )
- @$('.js-inbound [name="options::user"]').val( @account['meta']['email'] )
- @$('.js-inbound [name="options::password"]').val( @account['meta']['password'] )
-
- @enable(e)
- fail: =>
- @enable(e)
- @showSlide('js-intro')
- )
-
- probeInbound: (e) =>
- e.preventDefault()
-
- # get params
- params = @formParam(e.target)
- @disable(e)
-
- @showSlide('js-test')
-
- @ajax(
- id: 'email_inbound'
- type: 'POST'
- url: "#{@apiPath}/channels_email_inbound"
- data: JSON.stringify(params)
- processData: true
- success: (data, status, xhr) =>
- if data.result is 'ok'
-
- # remember account settings
- @account.inbound = params
-
- if data.content_messages && data.content_messages > 0 && (!@account['inbound']['options'] || @account['inbound']['options']['keep_on_server'] isnt true)
- @probeInboundMessagesFound(data, true)
- @probeInboundArchive(data)
- else
- @showSlide('js-outbound')
-
- # fill user / password based on inbound settings
- if !@channel
- if @account['inbound']['options']
- @$('.js-outbound [name="options::host"]').val( @account['inbound']['options']['host'] )
- @$('.js-outbound [name="options::user"]').val( @account['inbound']['options']['user'] )
- @$('.js-outbound [name="options::password"]').val( @account['inbound']['options']['password'] )
- else
- @$('.js-outbound [name="options::user"]').val( @account['meta']['email'] )
- @$('.js-outbound [name="options::password"]').val( @account['meta']['password'] )
-
- else
- @showSlide('js-inbound')
- @showAlert('js-inbound', data.message_human || data.message )
- @showInvalidField('js-inbound', data.invalid_field)
- @enable(e)
- fail: =>
- @showSlide('js-inbound')
- @showAlert('js-inbound', data.message_human || data.message )
- @showInvalidField('js-inbound', data.invalid_field)
- @enable(e)
- )
-
- probeInboundMessagesFound: (data, verify) =>
- message = App.i18n.translateContent('We have already found %s email(s) in your mailbox. Zammad will move it all from your mailbox into Zammad.', data.content_messages)
- @$('.js-inbound-acknowledge .js-messageFound').html(message)
-
- if !verify
- @$('.js-inbound-acknowledge .js-back').attr('data-slide', 'js-inbound')
- @$('.js-inbound-acknowledge .js-next').unbind('click.verify')
- else
- @$('.js-inbound-acknowledge .js-back').attr('data-slide', 'js-intro')
- @$('.js-inbound-acknowledge .js-next').attr('data-slide', '')
- @$('.js-inbound-acknowledge .js-next').unbind('click.verify').bind('click.verify', (e) =>
- e.preventDefault()
- @verify(@account)
- )
- @showSlide('js-inbound-acknowledge')
-
- probeInboundArchive: (data) =>
- if data.archive_possible isnt true
- @$('.js-archiveMessage').addClass('hide')
- return
-
- @$('.js-archiveMessage').removeClass('hide')
- message = App.i18n.translateContent('In addition, we have found emails in your mailbox that are older than %s weeks. You can import such emails as an "archive", which means that no notifications are sent and the tickets have the status "closed". However, you can find them in Zammad anytime using the search function.', data.archive_week_range)
- @$('.js-inbound-acknowledge .js-archiveMessageCount').html(message)
-
- configureAttributesAcknowledge = [
- {
- name: 'archive'
- tag: 'boolean'
- null: true
- default: no
- options: {
- true: 'archive'
- false: 'regular'
- }
- translate: true
- },
- ]
-
- new App.ControllerForm(
- elReplace: @$('.js-importTypeSelect'),
- model:
- configure_attributes: configureAttributesAcknowledge
- className: ''
- noFieldset: true
- )
- @$('.js-importTypeSelect select[name=archive]').on('change', (e) =>
- value = $(e.target).val()
- @account.inbound ||= {}
- @account.inbound.options ||= {}
- if value is 'true'
- @account.inbound.options.archive = true
- @account.inbound.options.archive_before = (new Date()).toISOString()
- else
- delete @account.inbound.options.archive
- delete @account.inbound.options.archive_before
- )
- @$('.js-importTypeSelect select[name=archive]').trigger('change')
-
- probleOutbound: (e) =>
- e.preventDefault()
-
- # get params
- params = @formParam(e.target)
- params['email'] = @account['meta']['email']
- @disable(e)
-
- @showSlide('js-test')
-
- @ajax(
- id: 'email_outbound'
- type: 'POST'
- url: "#{@apiPath}/channels_email_outbound"
- data: JSON.stringify(params)
- processData: true
- success: (data, status, xhr) =>
- if data.result is 'ok'
-
- # remember account settings
- @account.outbound = params
-
- @verify(@account)
- else
- @showSlide('js-outbound')
- @showAlert('js-outbound', data.message_human || data.message)
- @showInvalidField('js-outbound', data.invalid_field)
- @enable(e)
- fail: =>
- @showSlide('js-outbound')
- @showAlert('js-outbound', data.message_human || data.message)
- @showInvalidField('js-outbound', data.invalid_field)
- @enable(e)
- )
-
- verify: (account, count = 0) =>
- @showSlide('js-verify')
-
- @ajax(
- id: 'email_verify'
- type: 'POST'
- url: "#{@apiPath}/channels_email_verify"
- data: JSON.stringify(account)
- processData: true
- success: (data, status, xhr) =>
- if data.result is 'ok'
- @navigate 'getting_started/agents'
- else
- if data.source is 'inbound' || data.source is 'outbound'
- @showSlide("js-#{data.source}")
- @showAlert("js-#{data.source}", data.message_human || data.message)
- @showInvalidField("js-#{data.source}", data.invalid_field)
- else
- if count is 2
- @showAlert('js-verify', data.message_human || data.message)
- @delay(
- =>
- @showSlide('js-intro')
- @showAlert('js-intro', 'Unable to verify sending and receiving. Please check your settings.' )
-
- 2300
- )
- else
- if data.subject && @account
- @account.subject = data.subject
- @verify( @account, count + 1 )
- fail: =>
- @showSlide('js-intro')
- @showAlert('js-intro', 'Unable to verify sending and receiving. Please check your settings.')
- )
-
-App.Config.set('getting_started/channel/email', ChannelEmail, 'Routes')
-
-class Agent extends App.WizardFullScreen
- events:
- 'submit form': 'submit'
-
- constructor: ->
- super
- @authenticateCheckRedirect()
-
- # set title
- @title 'Invite Agents'
- @fetch()
-
- release: =>
- @el.removeClass('fit getstarted')
-
- 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}"
- return
-
- # load group collection
- App.Collection.load(type: 'Group', data: data.groups)
-
- # render page
- @render()
- )
-
- render: ->
-
- @html 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', Agent, 'Routes')
-
-class Channel extends App.WizardFullScreen
- constructor: ->
- super
- @authenticateCheckRedirect()
-
- # set title
- @title 'Setup Finished'
- @render()
-
- release: =>
- @el.removeClass('fit getstarted')
-
- render: ->
- @html App.view('getting_started/finish')()
- @delay(
- => @$('.wizard-slide').addClass('hide')
- 2300
- )
- @delay(
- => @navigate '#'
- 4300
- )
-
-App.Config.set('getting_started/finish', Channel, 'Routes')
+App.Config.set('getting_started', GettingStarted, 'Routes')
diff --git a/app/assets/javascripts/app/controllers/getting_started/admin.coffee b/app/assets/javascripts/app/controllers/getting_started/admin.coffee
new file mode 100644
index 000000000..2dfc7ed60
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/getting_started/admin.coffee
@@ -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')
diff --git a/app/assets/javascripts/app/controllers/getting_started/agent.coffee b/app/assets/javascripts/app/controllers/getting_started/agent.coffee
new file mode 100644
index 000000000..6a1bb932c
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/getting_started/agent.coffee
@@ -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')
diff --git a/app/assets/javascripts/app/controllers/getting_started/auto_wizard.coffee b/app/assets/javascripts/app/controllers/getting_started/auto_wizard.coffee
new file mode 100644
index 000000000..12c79f317
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/getting_started/auto_wizard.coffee
@@ -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')
diff --git a/app/assets/javascripts/app/controllers/getting_started/base.coffee b/app/assets/javascripts/app/controllers/getting_started/base.coffee
new file mode 100644
index 000000000..2f1b79a6a
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/getting_started/base.coffee
@@ -0,0 +1,130 @@
+class GettingStartedBase extends App.ControllerWizardFullScreen
+ elements:
+ '.logo-preview': 'logoPreview'
+
+ events:
+ 'submit form': 'submit'
+ 'change .js-upload': 'onLogoPick'
+
+ constructor: ->
+ super
+
+ # redirect if we are not admin
+ if !@permissionCheck('admin.wizard')
+ @navigate '#'
+ return
+
+ # set title
+ @title 'Configure Base'
+
+ @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
+
+ # import config options
+ if data.config
+ for key, value of data.config
+ App.Config.set(key, value)
+
+ # render page
+ @render()
+ )
+
+ render: ->
+
+ fqdn = App.Config.get('fqdn')
+ http_type = App.Config.get('http_type')
+ if !fqdn || fqdn is 'zammad.example.com'
+ url = window.location.origin
+ else
+ url = "#{http_type}://#{fqdn}"
+
+ organization = App.Config.get('organization')
+ @replaceWith App.view('getting_started/base')(
+ url: url
+ logoUrl: @logoUrl()
+ organization: organization
+ )
+ @$('input, select').first().focus()
+
+ onLogoPick: (event) =>
+ reader = new FileReader()
+
+ reader.onload = (e) =>
+ @logoPreview.attr('src', e.target.result)
+
+ file = event.target.files[0]
+
+ @hideAlerts()
+
+ # if no file is given, about in file upload was used
+ if !file
+ return
+
+ maxSiteInMb = 8
+ if file.size && file.size > 1024 * 1024 * maxSiteInMb
+ @showAlert( 'logo', App.i18n.translateInline('File too big, max. %s MB allowed.', maxSiteInMb ))
+ @logoPreview.attr('src', '')
+ return
+
+ reader.readAsDataURL(file)
+
+ submit: (e) =>
+ e.preventDefault()
+ @hideAlerts()
+ @disable(e)
+
+ @params = @formParam(e.target)
+ @params.logo = @logoPreview.attr('src')
+ @params.locale_default = App.i18n.detectBrowserLocale()
+ @params.timezone_default = App.i18n.detectBrowserTimezone()
+
+ store = (logoResizeDataUrl) =>
+ @params.logo_resize = logoResizeDataUrl
+ @ajax(
+ id: 'getting_started_base'
+ type: 'POST'
+ url: "#{@apiPath}/getting_started/base"
+ data: JSON.stringify(@params)
+ processData: true
+ success: (data, status, xhr) =>
+ if data.result is 'ok'
+ for key, value of data.settings
+ App.Config.set(key, value)
+ if App.Config.get('system_online_service')
+ @navigate 'getting_started/channel/email_pre_configured', { emptyEl: true }
+ else
+ @navigate 'getting_started/email_notification', { emptyEl: true }
+ else
+ for key, value of data.messages
+ @showAlert(key, value)
+ @enable(e)
+ fail: =>
+ @enable(e)
+ )
+
+ # add resized image
+ App.ImageService.resizeForApp(@params.logo, @logoPreview.width(), @logoPreview.height(), store)
+
+ hideAlerts: =>
+ @$('.form-group').removeClass('has-error')
+ @$('.alert').addClass('hide')
+
+ showAlert: (field, message) =>
+ @$("[name=#{field}]").closest('.form-group').addClass('has-error')
+ @$("[name=#{field}]").closest('.form-group').find('.alert').removeClass('hide').text( App.i18n.translateInline( message ) )
+
+App.Config.set('getting_started/base', GettingStartedBase, 'Routes')
diff --git a/app/assets/javascripts/app/controllers/getting_started/channel.coffee b/app/assets/javascripts/app/controllers/getting_started/channel.coffee
new file mode 100644
index 000000000..71535e9fb
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/getting_started/channel.coffee
@@ -0,0 +1,47 @@
+class GettingStartedChannel extends App.ControllerWizardFullScreen
+ constructor: ->
+ super
+
+ # redirect if we are not admin
+ if !@permissionCheck('admin.wizard')
+ @navigate '#'
+ return
+
+ # set title
+ @title 'Connect Channels'
+
+ @adapters = [
+ {
+ name: 'Email'
+ class: 'email'
+ link: '#getting_started/channel/email'
+ },
+ ]
+
+ @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
+
+ # render page
+ @render()
+ )
+
+ render: ->
+ @replaceWith App.view('getting_started/channel')(
+ adapters: @adapters
+ )
+
+App.Config.set('getting_started/channel', GettingStartedChannel, 'Routes')
diff --git a/app/assets/javascripts/app/controllers/getting_started/channel_email.coffee b/app/assets/javascripts/app/controllers/getting_started/channel_email.coffee
new file mode 100644
index 000000000..d698b64b4
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/getting_started/channel_email.coffee
@@ -0,0 +1,370 @@
+class GettingStartedChannelEmail extends App.ControllerWizardFullScreen
+ events:
+ 'submit .js-intro': 'probeBasedOnIntro'
+ 'submit .js-inbound': 'probeInbound'
+ 'change .js-outbound [name=adapter]': 'toggleOutboundAdapter'
+ 'submit .js-outbound': 'probleOutbound'
+ 'click .js-goToSlide': 'goToSlide'
+
+ constructor: ->
+ super
+
+ # redirect if we are not admin
+ if !@permissionCheck('admin.wizard')
+ @navigate '#'
+ return
+
+ # set title
+ @title 'Email Account'
+
+ # store account settings
+ @account =
+ inbound: {}
+ outbound: {}
+ meta: {}
+
+ @channelDriver =
+ email:
+ inbound: {}
+ outbound: {}
+
+ @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
+
+ @channelDriver = data.channel_driver
+
+ # render page
+ @render()
+ )
+
+ render: ->
+
+ @replaceWith App.view('getting_started/email')()
+ @showSlide('js-intro')
+
+ # outbound
+ configureAttributesOutbound = [
+ { name: 'adapter', display: 'Send Mails via', tag: 'select', multiple: false, null: false, options: @channelDriver.email.outbound },
+ ]
+ new App.ControllerForm(
+ el: @$('.base-outbound-type')
+ model:
+ configure_attributes: configureAttributesOutbound
+ className: ''
+ params:
+ adapter: @account.outbound.adapter || 'smtp'
+ )
+ @toggleOutboundAdapter()
+
+ # inbound
+ configureAttributesInbound = [
+ { name: 'adapter', display: 'Type', tag: 'select', multiple: false, null: false, options: @channelDriver.email.inbound },
+ { name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false },
+ { name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, autocomplete: 'off', },
+ { name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: false, autocapitalize: false, autocomplete: 'off', single: true },
+ { name: 'options::ssl', display: 'SSL/STARTTLS', tag: 'boolean', null: true, options: { true: 'yes', false: 'no' }, default: true, translate: true, item_class: 'formGroup--halfSize' },
+ { name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 6, null: true, autocapitalize: false, default: '993', item_class: 'formGroup--halfSize' },
+ { name: 'options::folder', display: 'Folder', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, item_class: 'formGroup--halfSize' },
+ { name: 'options::keep_on_server', display: 'Keep messages on server', tag: 'boolean', null: true, options: { true: 'yes', false: 'no' }, translate: true, default: false, item_class: 'formGroup--halfSize' },
+ ]
+
+ showHideFolder = (params, attribute, attributes, classname, form, ui) ->
+ return if !params
+ if params.adapter is 'imap'
+ ui.show('options::folder')
+ ui.show('options::keep_on_server')
+ return
+ ui.hide('options::folder')
+ ui.hide('options::keep_on_server')
+
+ handlePort = (params, attribute, attributes, classname, form, ui) ->
+ return if !params
+ return if !params.options
+ currentPort = @$('.base-inbound-settings [name="options::port"]').val()
+ if params.options.ssl is true
+ if !currentPort
+ @$('.base-inbound-settings [name="options::port"]').val('993')
+ return
+ if params.options.ssl is false
+ if !currentPort || currentPort is '993'
+ @$('.base-inbound-settings [name="options::port"]').val('143')
+ return
+
+ new App.ControllerForm(
+ el: @$('.base-inbound-settings')
+ model:
+ configure_attributes: configureAttributesInbound
+ className: ''
+ params: @account.inbound
+ handlers: [
+ showHideFolder,
+ handlePort,
+ ]
+ )
+
+ toggleOutboundAdapter: =>
+
+ # fill user / password based on intro info
+ channel_used = { options: {} }
+ if @account['meta']
+ channel_used['options']['user'] = @account['meta']['email']
+ channel_used['options']['password'] = @account['meta']['password']
+ channel_used['options']['folder'] = @account['meta']['folder']
+ channel_used['options']['keep_on_server'] = @account['meta']['keep_on_server']
+
+ # show used backend
+ @$('.base-outbound-settings').html('')
+ adapter = @$('.js-outbound [name=adapter]').val()
+ if adapter is 'smtp'
+ configureAttributesOutbound = [
+ { name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, autofocus: true },
+ { name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, autocomplete: 'off', },
+ { name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: true, autocapitalize: false, autocomplete: 'off', single: true },
+ { name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 6, null: true, autocapitalize: false },
+ ]
+ @form = new App.ControllerForm(
+ el: @$('.base-outbound-settings')
+ model:
+ configure_attributes: configureAttributesOutbound
+ className: ''
+ params: @account.outbound
+ )
+
+ probeBasedOnIntro: (e) =>
+ e.preventDefault()
+ params = @formParam(e.target)
+
+ # remember account settings
+ @account.meta = params
+
+ @disable(e)
+ @$('.js-probe .js-email').text(params.email)
+ @showSlide('js-probe')
+
+ @ajax(
+ id: 'email_probe'
+ type: 'POST'
+ url: "#{@apiPath}/channels_email_probe"
+ data: JSON.stringify(params)
+ processData: true
+ success: (data, status, xhr) =>
+ if data.result is 'ok'
+ if data.setting
+ for key, value of data.setting
+ @account[key] = value
+
+ if data.content_messages && data.content_messages > 0 && (!@account['inbound']['options'] || @account['inbound']['options']['keep_on_server'] isnt true)
+ @probeInboundMessagesFound(data, true)
+ @probeInboundArchive(data)
+ else
+ @verify(@account)
+
+ else if data.result is 'duplicate'
+ @showSlide('js-intro')
+ @showAlert('js-intro', 'Account already exists!' )
+ else
+ @showSlide('js-inbound')
+ @showAlert('js-inbound', 'Unable to detect your server settings. Manual configuration needed.' )
+ @$('.js-inbound [name="options::user"]').val( @account['meta']['email'] )
+ @$('.js-inbound [name="options::password"]').val( @account['meta']['password'] )
+
+ @enable(e)
+ fail: =>
+ @enable(e)
+ @showSlide('js-intro')
+ )
+
+ probeInbound: (e) =>
+ e.preventDefault()
+
+ # get params
+ params = @formParam(e.target)
+ @disable(e)
+
+ @showSlide('js-test')
+
+ @ajax(
+ id: 'email_inbound'
+ type: 'POST'
+ url: "#{@apiPath}/channels_email_inbound"
+ data: JSON.stringify(params)
+ processData: true
+ success: (data, status, xhr) =>
+ if data.result is 'ok'
+
+ # remember account settings
+ @account.inbound = params
+
+ if data.content_messages && data.content_messages > 0 && (!@account['inbound']['options'] || @account['inbound']['options']['keep_on_server'] isnt true)
+ @probeInboundMessagesFound(data, true)
+ @probeInboundArchive(data)
+ else
+ @showSlide('js-outbound')
+
+ # fill user / password based on inbound settings
+ if !@channel
+ if @account['inbound']['options']
+ @$('.js-outbound [name="options::host"]').val( @account['inbound']['options']['host'] )
+ @$('.js-outbound [name="options::user"]').val( @account['inbound']['options']['user'] )
+ @$('.js-outbound [name="options::password"]').val( @account['inbound']['options']['password'] )
+ else
+ @$('.js-outbound [name="options::user"]').val( @account['meta']['email'] )
+ @$('.js-outbound [name="options::password"]').val( @account['meta']['password'] )
+
+ else
+ @showSlide('js-inbound')
+ @showAlert('js-inbound', data.message_human || data.message )
+ @showInvalidField('js-inbound', data.invalid_field)
+ @enable(e)
+ fail: =>
+ @showSlide('js-inbound')
+ @showAlert('js-inbound', data.message_human || data.message )
+ @showInvalidField('js-inbound', data.invalid_field)
+ @enable(e)
+ )
+
+ probeInboundMessagesFound: (data, verify) =>
+ message = App.i18n.translateContent('We have already found %s email(s) in your mailbox. Zammad will move it all from your mailbox into Zammad.', data.content_messages)
+ @$('.js-inbound-acknowledge .js-messageFound').html(message)
+
+ if !verify
+ @$('.js-inbound-acknowledge .js-back').attr('data-slide', 'js-inbound')
+ @$('.js-inbound-acknowledge .js-next').unbind('click.verify')
+ else
+ @$('.js-inbound-acknowledge .js-back').attr('data-slide', 'js-intro')
+ @$('.js-inbound-acknowledge .js-next').attr('data-slide', '')
+ @$('.js-inbound-acknowledge .js-next').unbind('click.verify').bind('click.verify', (e) =>
+ e.preventDefault()
+ @verify(@account)
+ )
+ @showSlide('js-inbound-acknowledge')
+
+ probeInboundArchive: (data) =>
+ if data.archive_possible isnt true
+ @$('.js-archiveMessage').addClass('hide')
+ return
+
+ @$('.js-archiveMessage').removeClass('hide')
+ message = App.i18n.translateContent('In addition, we have found emails in your mailbox that are older than %s weeks. You can import such emails as an "archive", which means that no notifications are sent and the tickets have the status "closed". However, you can find them in Zammad anytime using the search function.', data.archive_week_range)
+ @$('.js-inbound-acknowledge .js-archiveMessageCount').html(message)
+
+ configureAttributesAcknowledge = [
+ {
+ name: 'archive'
+ tag: 'boolean'
+ null: true
+ default: no
+ options: {
+ true: 'archive'
+ false: 'regular'
+ }
+ translate: true
+ },
+ ]
+
+ new App.ControllerForm(
+ elReplace: @$('.js-importTypeSelect'),
+ model:
+ configure_attributes: configureAttributesAcknowledge
+ className: ''
+ noFieldset: true
+ )
+ @$('.js-importTypeSelect select[name=archive]').on('change', (e) =>
+ value = $(e.target).val()
+ @account.inbound ||= {}
+ @account.inbound.options ||= {}
+ if value is 'true'
+ @account.inbound.options.archive = true
+ @account.inbound.options.archive_before = (new Date()).toISOString()
+ else
+ delete @account.inbound.options.archive
+ delete @account.inbound.options.archive_before
+ )
+ @$('.js-importTypeSelect select[name=archive]').trigger('change')
+
+ probleOutbound: (e) =>
+ e.preventDefault()
+
+ # get params
+ params = @formParam(e.target)
+ params['email'] = @account['meta']['email']
+ @disable(e)
+
+ @showSlide('js-test')
+
+ @ajax(
+ id: 'email_outbound'
+ type: 'POST'
+ url: "#{@apiPath}/channels_email_outbound"
+ data: JSON.stringify(params)
+ processData: true
+ success: (data, status, xhr) =>
+ if data.result is 'ok'
+
+ # remember account settings
+ @account.outbound = params
+
+ @verify(@account)
+ else
+ @showSlide('js-outbound')
+ @showAlert('js-outbound', data.message_human || data.message)
+ @showInvalidField('js-outbound', data.invalid_field)
+ @enable(e)
+ fail: =>
+ @showSlide('js-outbound')
+ @showAlert('js-outbound', data.message_human || data.message)
+ @showInvalidField('js-outbound', data.invalid_field)
+ @enable(e)
+ )
+
+ verify: (account, count = 0) =>
+ @showSlide('js-verify')
+
+ @ajax(
+ id: 'email_verify'
+ type: 'POST'
+ url: "#{@apiPath}/channels_email_verify"
+ data: JSON.stringify(account)
+ processData: true
+ success: (data, status, xhr) =>
+ if data.result is 'ok'
+ @navigate 'getting_started/agents', { emptyEl: true }
+ else
+ if data.source is 'inbound' || data.source is 'outbound'
+ @showSlide("js-#{data.source}")
+ @showAlert("js-#{data.source}", data.message_human || data.message)
+ @showInvalidField("js-#{data.source}", data.invalid_field)
+ else
+ if count is 2
+ @showAlert('js-verify', data.message_human || data.message)
+ @delay(
+ =>
+ @showSlide('js-intro')
+ @showAlert('js-intro', 'Unable to verify sending and receiving. Please check your settings.' )
+
+ 2300
+ )
+ else
+ if data.subject && @account
+ @account.subject = data.subject
+ @verify( @account, count + 1 )
+ fail: =>
+ @showSlide('js-intro')
+ @showAlert('js-intro', 'Unable to verify sending and receiving. Please check your settings.')
+ )
+
+App.Config.set('getting_started/channel/email', GettingStartedChannelEmail, 'Routes')
diff --git a/app/assets/javascripts/app/controllers/getting_started/channel_email_pre_configured.coffee b/app/assets/javascripts/app/controllers/getting_started/channel_email_pre_configured.coffee
new file mode 100644
index 000000000..83d0e6bea
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/getting_started/channel_email_pre_configured.coffee
@@ -0,0 +1,39 @@
+class GettingStartedChannelEmailPreConfigured extends App.ControllerWizardFullScreen
+ constructor: ->
+ super
+
+ # redirect if we are not admin
+ if !@permissionCheck('admin.wizard')
+ @navigate '#'
+ return
+
+ # set title
+ @title 'Connect Channels'
+
+ @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
+
+ # render page
+ @render(data)
+ )
+
+ render: (data) ->
+ @replaceWith App.view('getting_started/email_pre_configured')(
+ data
+ )
+
+App.Config.set('getting_started/channel/email_pre_configured', GettingStartedChannelEmailPreConfigured, 'Routes')
diff --git a/app/assets/javascripts/app/controllers/getting_started/email_notification.coffee b/app/assets/javascripts/app/controllers/getting_started/email_notification.coffee
new file mode 100644
index 000000000..c9b38fc42
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/getting_started/email_notification.coffee
@@ -0,0 +1,116 @@
+class GettingStartedEmailNotification extends App.ControllerWizardFullScreen
+ events:
+ 'change .js-outbound [name=adapter]': 'toggleOutboundAdapter'
+ 'submit .js-outbound': 'submit'
+
+ constructor: ->
+ super
+
+ # redirect if we are not admin
+ if !@permissionCheck('admin.wizard')
+ @navigate '#'
+ return
+
+ # set title
+ @title 'Email Notifications'
+
+ @channelDriver =
+ email:
+ inbound: {}
+ outbound: {}
+
+ @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
+
+ @channelDriver = data.channel_driver
+
+ # render page
+ @render()
+ )
+
+ render: =>
+ @replaceWith App.view('getting_started/email_notification')()
+ configureAttributesOutbound = [
+ { name: 'adapter', display: 'Send Mails via', tag: 'select', multiple: false, null: false, options: @channelDriver.email.outbound },
+ ]
+ new App.ControllerForm(
+ el: @$('.base-outbound-type')
+ model:
+ configure_attributes: configureAttributesOutbound
+ className: ''
+ params:
+ adapter: 'sendmail'
+ )
+ @toggleOutboundAdapter()
+
+ toggleOutboundAdapter: =>
+
+ # show used backend
+ @el.find('.base-outbound-settings').html('')
+ adapter = @$('.js-outbound [name=adapter]').val()
+ if adapter is 'smtp'
+ configureAttributesOutbound = [
+ { name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, autofocus: true },
+ { name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, autocomplete: 'off' },
+ { name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: true, autocapitalize: false, autocomplete: 'off', single: true },
+ { name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 6, null: true, autocapitalize: false },
+ ]
+ @form = new App.ControllerForm(
+ el: @$('.base-outbound-settings')
+ model:
+ configure_attributes: configureAttributesOutbound
+ className: ''
+ )
+
+ submit: (e) =>
+ e.preventDefault()
+
+ # get params
+ params = @formParam(e.target)
+ params['email'] = 'me@localhost'
+ @disable(e)
+
+ @showSlide('js-test')
+
+ @ajax(
+ id: 'email_notification'
+ type: 'POST'
+ url: "#{@apiPath}/channels_email_notification"
+ data: JSON.stringify(params)
+ processData: true
+ success: (data, status, xhr) =>
+ if data.result is 'ok'
+ for key, value of data.settings
+ App.Config.set(key, value)
+ if App.Config.get('system_online_service')
+ @navigate 'getting_started/channel/email_pre_configured', { emptyEl: true }
+ else
+ @navigate 'getting_started/channel', { emptyEl: true }
+ else
+ @showSlide('js-outbound')
+ @showAlert('js-outbound', data.message_human || data.message )
+ @showInvalidField('js-outbound', data.invalid_field)
+ @enable(e)
+
+ fail: =>
+ @showSlide('js-outbound')
+ @showAlert('js-outbound', data.message_human || data.message )
+ @showInvalidField('js-outbound', data.invalid_field)
+ @enable(e)
+ )
+
+App.Config.set('getting_started/email_notification', GettingStartedEmailNotification, 'Routes')
diff --git a/app/assets/javascripts/app/controllers/getting_started/finish.coffee b/app/assets/javascripts/app/controllers/getting_started/finish.coffee
new file mode 100644
index 000000000..8c8c8ad4a
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/getting_started/finish.coffee
@@ -0,0 +1,22 @@
+class GettingStartedFinish extends App.ControllerWizardFullScreen
+ constructor: ->
+ super
+ @authenticateCheckRedirect()
+
+ # set title
+ @title 'Setup Finished'
+ @render()
+
+ render: ->
+ @replaceWith App.view('getting_started/finish')()
+ @delay(
+ => @$('.setup.wizard').addClass('hide')
+ 2300
+ )
+ @delay(
+ =>
+ @redirectToLogin()
+ 4300
+ )
+
+App.Config.set('getting_started/finish', GettingStartedFinish, 'Routes')
diff --git a/app/assets/javascripts/app/controllers/groups.coffee b/app/assets/javascripts/app/controllers/group.coffee
similarity index 89%
rename from app/assets/javascripts/app/controllers/groups.coffee
rename to app/assets/javascripts/app/controllers/group.coffee
index 74e5f3708..c7e294fb1 100644
--- a/app/assets/javascripts/app/controllers/groups.coffee
+++ b/app/assets/javascripts/app/controllers/group.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class Group extends App.ControllerSubContent
requiredPermission: 'admin.group'
header: 'Groups'
constructor: ->
@@ -34,4 +34,4 @@ class Index extends App.ControllerSubContent
@genericController.paginate( @page || 1 )
-App.Config.set('Group', { prio: 1500, name: 'Groups', parent: '#manage', target: '#manage/groups', controller: Index, permission: ['admin.group'] }, 'NavBarAdmin')
+App.Config.set('Group', { prio: 1500, name: 'Groups', parent: '#manage', target: '#manage/groups', controller: Group, permission: ['admin.group'] }, 'NavBarAdmin')
diff --git a/app/assets/javascripts/app/controllers/import.coffee b/app/assets/javascripts/app/controllers/import.coffee
index 4bc8cdeda..32dec67d1 100644
--- a/app/assets/javascripts/app/controllers/import.coffee
+++ b/app/assets/javascripts/app/controllers/import.coffee
@@ -1,12 +1,7 @@
-class Import extends App.ControllerContent
- className: 'getstarted fit'
-
+class Import extends App.ControllerWizardFullScreen
constructor: ->
super
-
- # set title
@title 'Import'
-
@fetch()
fetch: ->
@@ -25,7 +20,7 @@ class Import extends App.ControllerContent
return
if data.import_mode == true
- @navigate '#import/' + data.import_backend
+ @navigate '#import/' + data.import_backend, { emptyEl: true }
return
# render page
@@ -36,7 +31,7 @@ class Import extends App.ControllerContent
items = App.Config.get('ImportPlugins')
- @html App.view('import/index')(
+ @replaceWith App.view('import/index')(
items: items
)
diff --git a/app/assets/javascripts/app/controllers/import_otrs.coffee b/app/assets/javascripts/app/controllers/import_otrs.coffee
index 446ff037a..e60dce3f6 100644
--- a/app/assets/javascripts/app/controllers/import_otrs.coffee
+++ b/app/assets/javascripts/app/controllers/import_otrs.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerContent
+class ImportOtrs extends App.ControllerWizardFullScreen
className: 'getstarted fit'
elements:
'.input-feedback': 'urlStatus'
@@ -38,7 +38,7 @@ class Index extends App.ControllerContent
# check if import is active
if data.import_mode == true && data.import_backend != 'otrs'
- @navigate "#import/#{data.import_backend}"
+ @navigate "#import/#{data.import_backend}", { emptyEl: true }
return
# render page
@@ -50,7 +50,7 @@ class Index extends App.ControllerContent
)
render: ->
- @html App.view('import/otrs')()
+ @replaceWith App.view('import/otrs')()
startDownload: (e) =>
@$('.js-otrs-link').removeClass('hide')
@@ -170,7 +170,7 @@ class Index extends App.ControllerContent
@delay(@updateMigration, 6500)
)
-App.Config.set('import/otrs', Index, 'Routes')
+App.Config.set('import/otrs', ImportOtrs, 'Routes')
App.Config.set('otrs', {
title: 'OTRS'
name: 'OTRS'
diff --git a/app/assets/javascripts/app/controllers/import_zendesk.coffee b/app/assets/javascripts/app/controllers/import_zendesk.coffee
index c49004230..221bf88fe 100644
--- a/app/assets/javascripts/app/controllers/import_zendesk.coffee
+++ b/app/assets/javascripts/app/controllers/import_zendesk.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerContent
+class ImportZendesk extends App.ControllerWizardFullScreen
className: 'getstarted fit'
elements:
'.input-feedback': 'urlStatus'
@@ -44,7 +44,7 @@ class Index extends App.ControllerContent
# check if import is active
if data.import_mode == true && data.import_backend != 'zendesk'
- @navigate "#import/#{data.import_backend}"
+ @navigate "#import/#{data.import_backend}", { emptyEl: true }
return
# render page
@@ -56,7 +56,7 @@ class Index extends App.ControllerContent
)
render: ->
- @html App.view('import/zendesk')()
+ @replaceWith App.view('import/zendesk')()
updateUrl: (e) =>
@urlStatus.attr('data-state', 'loading')
@@ -189,7 +189,7 @@ class Index extends App.ControllerContent
@delay(@updateMigration, 5000)
)
-App.Config.set('import/zendesk', Index, 'Routes')
+App.Config.set('import/zendesk', ImportZendesk, 'Routes')
App.Config.set('zendesk', {
title: 'Zendesk'
name: 'Zendesk'
diff --git a/app/assets/javascripts/app/controllers/integrations.coffee b/app/assets/javascripts/app/controllers/integrations.coffee
index 996e6de51..c4c32f3af 100644
--- a/app/assets/javascripts/app/controllers/integrations.coffee
+++ b/app/assets/javascripts/app/controllers/integrations.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class Integrations extends App.ControllerSubContent
requiredPermission: 'admin.integration'
header: 'Integrations'
constructor: ->
@@ -64,4 +64,4 @@ class Index extends App.ControllerSubContent
if @subscribeId
App.Setting.unsubscribe(@subscribeId)
-App.Config.set('Integration', { prio: 1000, name: 'Integrations', parent: '#system', target: '#system/integration', controller: Index, permission: ['admin.integration'] }, 'NavBarAdmin')
+App.Config.set('Integration', { prio: 1000, name: 'Integrations', parent: '#system', target: '#system/integration', controller: Integrations, permission: ['admin.integration'] }, 'NavBarAdmin')
diff --git a/app/assets/javascripts/app/controllers/job.coffee b/app/assets/javascripts/app/controllers/job.coffee
index 49c379820..0962d1da8 100644
--- a/app/assets/javascripts/app/controllers/job.coffee
+++ b/app/assets/javascripts/app/controllers/job.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class Job extends App.ControllerSubContent
requiredPermission: 'admin.scheduler'
header: 'Scheduler'
constructor: ->
@@ -35,4 +35,4 @@ class Index extends App.ControllerSubContent
@genericController.paginate( @page || 1 )
-App.Config.set('Job', { prio: 3400, name: 'Scheduler', parent: '#manage', target: '#manage/job', controller: Index, permission: ['admin.scheduler'] }, 'NavBarAdmin')
+App.Config.set('Job', { prio: 3400, name: 'Scheduler', parent: '#manage', target: '#manage/job', controller: Job, permission: ['admin.scheduler'] }, 'NavBarAdmin')
diff --git a/app/assets/javascripts/app/controllers/karma.coffee b/app/assets/javascripts/app/controllers/karma.coffee
index 8a65c9ab4..94fa91b77 100644
--- a/app/assets/javascripts/app/controllers/karma.coffee
+++ b/app/assets/javascripts/app/controllers/karma.coffee
@@ -1,4 +1,4 @@
-class KarmaContent extends App.ControllerContent
+class KarmaContent extends App.Controller
constructor: ->
new Karma()
@@ -15,7 +15,7 @@ class Karma extends App.ControllerModal
@load()
# rerender view, e. g. on langauge change
- @bind('ui:rerender', =>
+ @controllerBind('ui:rerender', =>
@update()
'karma'
)
diff --git a/app/assets/javascripts/app/controllers/keyboard_shortcuts.coffee b/app/assets/javascripts/app/controllers/keyboard_shortcuts.coffee
index 53d6b295d..84e8b617d 100644
--- a/app/assets/javascripts/app/controllers/keyboard_shortcuts.coffee
+++ b/app/assets/javascripts/app/controllers/keyboard_shortcuts.coffee
@@ -1,6 +1,6 @@
-class Index
+class KeyboardShortcuts
constructor: ->
new App.KeyboardShortcutModal()
-App.Config.set('keyboard_shortcuts', Index, 'Routes')
+App.Config.set('keyboard_shortcuts', KeyboardShortcuts, 'Routes')
App.Config.set('KeyboardShortcuts', { prio: 1700, parent: '#current_user', name: 'Keyboard Shortcuts', translate: true, target: '#keyboard_shortcuts', permission: ['admin', 'ticket.agent'] }, 'NavBarRight')
diff --git a/app/assets/javascripts/app/controllers/knowledge_base/agent_controller.coffee b/app/assets/javascripts/app/controllers/knowledge_base/agent_controller.coffee
index e516936f4..c8d9bca31 100644
--- a/app/assets/javascripts/app/controllers/knowledge_base/agent_controller.coffee
+++ b/app/assets/javascripts/app/controllers/knowledge_base/agent_controller.coffee
@@ -9,7 +9,7 @@ class App.KnowledgeBaseAgentController extends App.Controller
constructor: (params) ->
super
- @bind 'config_update_local', (data) => @configUpdated(data)
+ @controllerBind('config_update_local', (data) => @configUpdated(data))
if @permissionCheck('knowledge_base.*') and App.Config.get('kb_active')
@updateNavMenu()
@@ -36,7 +36,7 @@ class App.KnowledgeBaseAgentController extends App.Controller
@fetchAndRender()
- @bind('ui:rerender',
+ @controllerBind('ui:rerender',
=>
@render(true)
@contentController?.url = null
@@ -44,13 +44,13 @@ class App.KnowledgeBaseAgentController extends App.Controller
@show(@lastParams)
)
- @bind 'kb_data_changed', (pushed_data) =>
+ @controllerBind('kb_data_changed', (pushed_data) =>
key = "kb_pull_#{pushed_data.class}_#{pushed_data.id}"
App.Delay.set( =>
@loadChange(pushed_data)
, 1000, key, 'kb_data_changed_loading')
-
+ )
@listenTo App.KnowledgeBase, 'kb_data_change_loaded', =>
return if !@displayingError
@@ -139,7 +139,7 @@ class App.KnowledgeBaseAgentController extends App.Controller
return
if @loaded && @rendered && @lastParams && !params.knowledge_base_id && @contentController && @kb_locale()?
- @navigate @lastParams.match[0] , true
+ @navigate @lastParams.match[0] , { hideCurrentLocationFromHistory: true }
return
if @contentController && @contentController.url is params.match[0]
@@ -162,7 +162,7 @@ class App.KnowledgeBaseAgentController extends App.Controller
@renderControllers(params)
else
if (kb = App.KnowledgeBase.all()[0])
- @navigate kb.uiUrl(App.KnowledgeBaseLocale.detect(kb)), true
+ @navigate kb.uiUrl(App.KnowledgeBaseLocale.detect(kb)), { hideCurrentLocationFromHistory: true }
else
@renderScreenErrorInContent('No Knowledge Base created')
else
diff --git a/app/assets/javascripts/app/controllers/knowledge_base/navigation.coffee b/app/assets/javascripts/app/controllers/knowledge_base/navigation.coffee
index ae995dd44..2825db9e9 100644
--- a/app/assets/javascripts/app/controllers/knowledge_base/navigation.coffee
+++ b/app/assets/javascripts/app/controllers/knowledge_base/navigation.coffee
@@ -11,7 +11,7 @@ class App.KnowledgeBaseNavigation extends App.Controller
super
@render()
- @bind 'knowledge_base::navigation::rerender', => @needsUpdate()
+ @controllerBind('knowledge_base::navigation::rerender', => @needsUpdate())
@listenTo App.KnowledgeBase, 'kb_data_change_loaded', =>
@needsUpdate()
diff --git a/app/assets/javascripts/app/controllers/knowledge_base/sidebar.coffee b/app/assets/javascripts/app/controllers/knowledge_base/sidebar.coffee
index 222af68a3..9543adc76 100644
--- a/app/assets/javascripts/app/controllers/knowledge_base/sidebar.coffee
+++ b/app/assets/javascripts/app/controllers/knowledge_base/sidebar.coffee
@@ -8,7 +8,7 @@ class App.KnowledgeBaseSidebar extends App.Controller
super
@show()
- @bind 'knowledge_base::sidebar::rerender', => @rerender()
+ @controllerBind 'knowledge_base::sidebar::rerender', => @rerender()
@listenTo App.KnowledgeBase, 'kb_data_change_loaded', =>
@rerender()
diff --git a/app/assets/javascripts/app/controllers/layout_ref.coffee b/app/assets/javascripts/app/controllers/layout_ref.coffee
index 276209ee0..fe9b4a6b9 100644
--- a/app/assets/javascripts/app/controllers/layout_ref.coffee
+++ b/app/assets/javascripts/app/controllers/layout_ref.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerContent
+class LayoutRef extends App.ControllerAppContent
constructor: ->
super
@render()
@@ -6,10 +6,10 @@ class Index extends App.ControllerContent
render: ->
@html App.view('layout_ref/index')()
-App.Config.set( 'layout_ref', Index, 'Routes' )
+App.Config.set('layout_ref', LayoutRef, 'Routes')
-class Content extends App.ControllerContent
+class Content extends App.ControllerAppContent
events:
'hide.bs.dropdown .js-recipientDropdown': 'hideOrganizationMembers'
'click .js-organization': 'showOrganizationMembers'
@@ -103,7 +103,7 @@ class Content extends App.ControllerContent
App.Config.set( 'layout_ref/content', Content, 'Routes' )
-class CommunicationOverview extends App.ControllerContent
+class CommunicationOverview extends App.ControllerAppContent
events:
'click .js-unfold': 'unfold'
@@ -153,7 +153,7 @@ class CommunicationOverview extends App.ControllerContent
App.Config.set( 'layout_ref/communication_overview', CommunicationOverview, 'Routes' )
-class LayoutRefCommunicationReply extends App.ControllerContent
+class LayoutRefCommunicationReply extends App.ControllerAppContent
elements:
'.js-textarea' : 'textarea'
'.attachmentPlaceholder': 'attachmentPlaceholder'
@@ -389,7 +389,7 @@ App.Config.set( 'layout_ref/communication_reply/:content', LayoutRefCommunicatio
-class ContentSidebarRight extends App.ControllerContent
+class ContentSidebarRight extends App.ControllerAppContent
constructor: ->
super
@render()
@@ -400,7 +400,7 @@ class ContentSidebarRight extends App.ControllerContent
App.Config.set( 'layout_ref/content_sidebar_right', ContentSidebarRight, 'Routes' )
-class ContentSidebarRightSidebarOptional extends App.ControllerContent
+class ContentSidebarRightSidebarOptional extends App.ControllerAppContent
constructor: ->
super
@render()
@@ -442,7 +442,7 @@ class ModalText extends App.ControllerModal
App.Config.set( 'layout_ref/modal_text', ModalText, 'Routes' )
-class ContentSidebarTabsRight extends App.ControllerContent
+class ContentSidebarTabsRight extends App.ControllerAppContent
elements:
'.tabsSidebar' : 'sidebar'
@@ -510,7 +510,7 @@ class ContentSidebarTabsRight extends App.ControllerContent
App.Config.set( 'layout_ref/content_sidebar_tabs_right', ContentSidebarTabsRight, 'Routes' )
-class ContentSidebarLeft extends App.ControllerContent
+class ContentSidebarLeft extends App.ControllerAppContent
constructor: ->
super
@render()
@@ -521,7 +521,7 @@ class ContentSidebarLeft extends App.ControllerContent
App.Config.set( 'layout_ref/content_sidebar_left', ContentSidebarLeft, 'Routes' )
-class App.ControllerWizard extends App.ControllerContent
+class App.ControllerWizard extends App.ControllerAppContent
elements:
'[data-slide]': 'slides'
@@ -593,7 +593,7 @@ class ImportWizard extends App.ControllerWizard
App.Config.set( 'layout_ref/import_wizard', ImportWizard, 'Routes' )
-class ReferenceUserProfile extends App.ControllerContent
+class ReferenceUserProfile extends App.ControllerAppContent
constructor: ->
super
@@ -604,7 +604,7 @@ class ReferenceUserProfile extends App.ControllerContent
App.Config.set( 'layout_ref/user_profile', ReferenceUserProfile, 'Routes' )
-class ReferenceOrganizationProfile extends App.ControllerContent
+class ReferenceOrganizationProfile extends App.ControllerAppContent
constructor: ->
super
@@ -656,7 +656,7 @@ class ReferenceSetupWizard extends App.ControllerWizard
App.Config.set( 'layout_ref/setup', ReferenceSetupWizard, 'Routes' )
-class RichText extends App.ControllerContent
+class RichText extends App.ControllerAppContent
constructor: ->
super
@render()
@@ -724,7 +724,7 @@ class RichText extends App.ControllerContent
App.Config.set( 'layout_ref/richtext', RichText, 'Routes' )
-class LocalModalRef extends App.ControllerContent
+class LocalModalRef extends App.ControllerAppContent
constructor: ->
super
@@ -735,7 +735,7 @@ class LocalModalRef extends App.ControllerContent
App.Config.set( 'layout_ref/local_modal', LocalModalRef, 'Routes' )
-class LoadingPlaceholderRef extends App.ControllerContent
+class LoadingPlaceholderRef extends App.ControllerAppContent
constructor: ->
super
@@ -746,7 +746,7 @@ class LoadingPlaceholderRef extends App.ControllerContent
App.Config.set( 'layout_ref/loading_placeholder', LoadingPlaceholderRef, 'Routes' )
-class InsufficientRightsRef extends App.ControllerContent
+class InsufficientRightsRef extends App.ControllerAppContent
constructor: ->
super
@@ -758,7 +758,7 @@ class InsufficientRightsRef extends App.ControllerContent
App.Config.set( 'layout_ref/insufficient_rights', InsufficientRightsRef, 'Routes' )
-class ErrorRef extends App.ControllerContent
+class ErrorRef extends App.ControllerAppContent
constructor: ->
super
@@ -770,7 +770,7 @@ class ErrorRef extends App.ControllerContent
App.Config.set( 'layout_ref/error', ErrorRef, 'Routes' )
-class TicketZoomRef extends App.ControllerContent
+class TicketZoomRef extends App.ControllerAppContent
elements:
'.article-text': 'articles'
'.js-highlight-icon': 'highlightIcon'
@@ -980,7 +980,7 @@ class TicketZoomRef extends App.ControllerContent
App.Config.set( 'layout_ref/ticket_zoom', TicketZoomRef, 'Routes' )
-class CluesRef extends App.ControllerContent
+class CluesRef extends App.ControllerAppContent
clues: [
{
@@ -1298,7 +1298,7 @@ class CluesRef extends App.ControllerContent
App.Config.set( 'layout_ref/clues', CluesRef, 'Routes' )
-class AdminPlaceholderRef extends App.ControllerContent
+class AdminPlaceholderRef extends App.ControllerAppContent
constructor: ->
super
@@ -1309,7 +1309,7 @@ class AdminPlaceholderRef extends App.ControllerContent
App.Config.set( 'layout_ref/admin_placeholder', AdminPlaceholderRef, 'Routes' )
-class UserListRef extends App.ControllerContent
+class UserListRef extends App.ControllerAppContent
constructor: ->
super
@@ -1321,7 +1321,7 @@ class UserListRef extends App.ControllerContent
App.Config.set( 'layout_ref/user_list', UserListRef, 'Routes' )
-class SlaRef extends App.ControllerContent
+class SlaRef extends App.ControllerAppContent
events:
'click .js-activateColumn': 'activateColumn'
@@ -1377,7 +1377,7 @@ class SlaRef extends App.ControllerContent
App.Config.set( 'layout_ref/sla', SlaRef, 'Routes' )
-class SchedulersRef extends App.ControllerContent
+class SchedulersRef extends App.ControllerAppContent
events:
'click .select-value': 'select'
'click [data-type=new]': 'createNew'
@@ -1457,7 +1457,7 @@ class SchedulersRef extends App.ControllerContent
App.Config.set( 'layout_ref/schedulers', SchedulersRef, 'Routes' )
-class InputsRef extends App.ControllerContent
+class InputsRef extends App.ControllerAppContent
constructor: ->
super
@@ -1584,7 +1584,7 @@ class InputsRef extends App.ControllerContent
App.Config.set( 'layout_ref/inputs', InputsRef, 'Routes' )
-class CalendarSubscriptionsRef extends App.ControllerContent
+class CalendarSubscriptionsRef extends App.ControllerAppContent
elements:
'input[type=checkbox]': 'options'
@@ -1660,7 +1660,7 @@ class CalendarSubscriptionsRef extends App.ControllerContent
App.Config.set( 'layout_ref/calendar_subscriptions', CalendarSubscriptionsRef, 'Routes' )
-class ButtonsRef extends App.ControllerContent
+class ButtonsRef extends App.ControllerAppContent
elements:
'.js-submitDropdown': 'buttonDropdown'
@@ -1697,7 +1697,7 @@ class ButtonsRef extends App.ControllerContent
App.Config.set( 'layout_ref/buttons', ButtonsRef, 'Routes' )
-class MergeCustomerRef extends App.ControllerContent
+class MergeCustomerRef extends App.ControllerAppContent
mergeTarget:
firstname: 'Nicole',
@@ -1747,7 +1747,7 @@ class MergeCustomerRef extends App.ControllerContent
App.Config.set( 'layout_ref/merge_customer', MergeCustomerRef, 'Routes' )
-class PrimaryEmailRef extends App.ControllerContent
+class PrimaryEmailRef extends App.ControllerAppContent
constructor: ->
super
@@ -2164,7 +2164,7 @@ class ChatWindowRef extends Spine.Controller
@scrollHolder.scrollTop(@scrollHolder.prop('scrollHeight'))
-class AdminLoadRef extends App.ControllerContent
+class AdminLoadRef extends App.ControllerAppContent
constructor: ->
super
@@ -2176,7 +2176,7 @@ class AdminLoadRef extends App.ControllerContent
App.Config.set( 'layout_ref/admin_loading', AdminLoadRef, 'Routes' )
-class TwitterConversationRef extends App.ControllerContent
+class TwitterConversationRef extends App.ControllerAppContent
elements:
'.js-textarea': 'textarea'
'.article-add': 'articleNewEdit'
@@ -2264,7 +2264,7 @@ class TwitterConversationRef extends App.ControllerContent
App.Config.set( 'layout_ref/twitter_conversation', TwitterConversationRef, 'Routes' )
-class UI extends App.ControllerContent
+class UI extends App.ControllerAppContent
constructor: ->
super
@render()
@@ -2274,7 +2274,7 @@ class UI extends App.ControllerContent
App.Config.set( 'layout_ref/ui', UI, 'Routes' )
-class ChatToTicketRef extends App.ControllerContent
+class ChatToTicketRef extends App.ControllerAppContent
elements:
'.js-scrollHolder': 'scrollHolder'
@@ -2309,7 +2309,7 @@ class ChatToTicketRef extends App.ControllerContent
App.Config.set('layout_ref/chat_to_ticket', ChatToTicketRef, 'Routes')
-class KnowledgeBaseAgentReaderRef extends App.ControllerContent
+class KnowledgeBaseAgentReaderRef extends App.ControllerAppContent
className: 'flex knowledge-base vertical'
elements:
@@ -2349,7 +2349,7 @@ class KnowledgeBaseAgentReaderRef extends App.ControllerContent
App.Config.set('layout_ref/kb_agent_reader', KnowledgeBaseAgentReaderRef, 'Routes')
-class KnowledgeBaseLinkTicketToAnswerRef extends App.ControllerContent
+class KnowledgeBaseLinkTicketToAnswerRef extends App.ControllerAppContent
constructor: ->
super
App.Utils.loadIconFont('anticon')
@@ -2364,7 +2364,7 @@ class KnowledgeBaseLinkTicketToAnswerRef extends App.ControllerContent
App.Config.set('layout_ref/kb_link_ticket_to_answer', KnowledgeBaseLinkTicketToAnswerRef, 'Routes')
-class KnowledgeBaseLinkAnswerToAnswerRef extends App.ControllerContent
+class KnowledgeBaseLinkAnswerToAnswerRef extends App.ControllerAppContent
elements:
'.js-form': 'form'
diff --git a/app/assets/javascripts/app/controllers/login.coffee b/app/assets/javascripts/app/controllers/login.coffee
index c344770c9..3874d9093 100644
--- a/app/assets/javascripts/app/controllers/login.coffee
+++ b/app/assets/javascripts/app/controllers/login.coffee
@@ -1,6 +1,7 @@
-class Index extends App.ControllerContent
+class Login extends App.ControllerFullPage
events:
'submit #login': 'login'
+ className: 'login'
constructor: ->
super
@@ -15,14 +16,12 @@ class Index extends App.ControllerContent
@navigate '#'
return
- @navHide()
-
@title 'Sign in'
@render()
@navupdate '#login'
# observe config changes related to login page
- @bind('config_update_local', (data) =>
+ @controllerBind('config_update_local', (data) =>
return if !data.name.match(/^maintenance/) &&
!data.name.match(/^auth/) &&
data.name != 'user_lost_password' &&
@@ -33,7 +32,7 @@ class Index extends App.ControllerContent
@render()
'rerender'
)
- @bind('ui:rerender', =>
+ @controllerBind('ui:rerender', =>
@render()
)
@@ -44,7 +43,7 @@ class Index extends App.ControllerContent
if @Config.get(provider.config) is true || @Config.get(provider.config) is 'true'
auth_providers.push provider
- @html App.view('login')(
+ @replaceWith App.view('login')(
item: data
logoUrl: @logoUrl()
auth_providers: auth_providers
@@ -77,6 +76,7 @@ class Index extends App.ControllerContent
)
success: (data, status, xhr) =>
+ App.Plugin.init()
# redirect to #
requested_url = @Config.get('requested_url')
@@ -110,4 +110,4 @@ class Index extends App.ControllerContent
600
)
-App.Config.set('login', Index, 'Routes')
+App.Config.set('login', Login, 'Routes')
diff --git a/app/assets/javascripts/app/controllers/logout.coffee b/app/assets/javascripts/app/controllers/logout.coffee
index 7fb2b1bd1..639c152b4 100644
--- a/app/assets/javascripts/app/controllers/logout.coffee
+++ b/app/assets/javascripts/app/controllers/logout.coffee
@@ -1,8 +1,6 @@
-class Index extends App.ControllerContent
+class Logout
constructor: ->
- super
-
App.Auth.logout()
-App.Config.set('logout', Index, 'Routes')
+App.Config.set('logout', Logout, 'Routes')
App.Config.set('Logout', { prio: 1800, parent: '#current_user', name: 'Sign out', translate: true, target: '#logout', divider: true, iconClass: 'signout' }, 'NavBarRight')
diff --git a/app/assets/javascripts/app/controllers/macro.coffee b/app/assets/javascripts/app/controllers/macro.coffee
index 801db2459..1f923d515 100644
--- a/app/assets/javascripts/app/controllers/macro.coffee
+++ b/app/assets/javascripts/app/controllers/macro.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class Macro extends App.ControllerSubContent
requiredPermission: 'admin.macro'
header: 'Macros'
constructor: ->
@@ -34,4 +34,4 @@ class Index extends App.ControllerSubContent
@genericController.paginate( @page || 1 )
-App.Config.set('Macros', { prio: 2310, name: 'Macros', parent: '#manage', target: '#manage/macros', controller: Index, permission: ['admin.macro'] }, 'NavBarAdmin')
+App.Config.set('Macros', { prio: 2310, name: 'Macros', parent: '#manage', target: '#manage/macros', controller: Macro, permission: ['admin.macro'] }, 'NavBarAdmin')
diff --git a/app/assets/javascripts/app/controllers/maintenance.coffee b/app/assets/javascripts/app/controllers/maintenance.coffee
index a13ac5ad6..9b94cc958 100644
--- a/app/assets/javascripts/app/controllers/maintenance.coffee
+++ b/app/assets/javascripts/app/controllers/maintenance.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class Maintenance extends App.ControllerSubContent
requiredPermission: 'admin.maintenance'
header: 'Maintenance'
events:
@@ -88,4 +88,4 @@ class Index extends App.ControllerSubContent
removeAll: true
@render()
-App.Config.set('Maintenance', { prio: 3600, name: 'Maintenance', parent: '#system', target: '#system/maintenance', controller: Index, permission: ['admin.maintenance'] }, 'NavBarAdmin')
+App.Config.set('Maintenance', { prio: 3600, name: 'Maintenance', parent: '#system', target: '#system/maintenance', controller: Maintenance, permission: ['admin.maintenance'] }, 'NavBarAdmin')
diff --git a/app/assets/javascripts/app/controllers/monitoring.coffee b/app/assets/javascripts/app/controllers/monitoring.coffee
index 2b6900248..be4dd4e84 100644
--- a/app/assets/javascripts/app/controllers/monitoring.coffee
+++ b/app/assets/javascripts/app/controllers/monitoring.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class Monitoring extends App.ControllerSubContent
requiredPermission: 'admin.monitoring'
header: 'Monitoring'
events:
@@ -53,4 +53,4 @@ class Index extends App.ControllerSubContent
@load()
)
-App.Config.set('Monitoring', { prio: 3600, name: 'Monitoring', parent: '#system', target: '#system/monitoring', controller: Index, permission: ['admin.monitoring'] }, 'NavBarAdmin')
+App.Config.set('Monitoring', { prio: 3600, name: 'Monitoring', parent: '#system', target: '#system/monitoring', controller: Monitoring, permission: ['admin.monitoring'] }, 'NavBarAdmin')
diff --git a/app/assets/javascripts/app/controllers/object_manager.coffee b/app/assets/javascripts/app/controllers/object_manager.coffee
index 01e712761..1e4d0f6e9 100644
--- a/app/assets/javascripts/app/controllers/object_manager.coffee
+++ b/app/assets/javascripts/app/controllers/object_manager.coffee
@@ -39,7 +39,7 @@ treeParams = (e, params) ->
params.data_option.options = tree
params
-class Index extends App.ControllerTabs
+class ObjectManager extends App.ControllerTabs
requiredPermission: 'admin.object'
constructor: ->
super
@@ -278,4 +278,4 @@ class Edit extends App.ControllerGenericEdit
ui.controller.showAlert(details.error_human || details.error || 'Unable to update object!')
)
-App.Config.set('SystemObject', { prio: 1700, parent: '#system', name: 'Objects', target: '#system/object_manager', controller: Index, permission: ['admin.object'] }, 'NavBarAdmin')
+App.Config.set('SystemObject', { prio: 1700, parent: '#system', name: 'Objects', target: '#system/object_manager', controller: ObjectManager, permission: ['admin.object'] }, 'NavBarAdmin')
diff --git a/app/assets/javascripts/app/controllers/organizations.coffee b/app/assets/javascripts/app/controllers/organization.coffee
similarity index 91%
rename from app/assets/javascripts/app/controllers/organizations.coffee
rename to app/assets/javascripts/app/controllers/organization.coffee
index 05a20ecb3..99ef60e06 100644
--- a/app/assets/javascripts/app/controllers/organizations.coffee
+++ b/app/assets/javascripts/app/controllers/organization.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class Organization extends App.ControllerSubContent
requiredPermission: 'admin.organization'
header: 'Organizations'
constructor: ->
@@ -41,4 +41,4 @@ class Index extends App.ControllerSubContent
@genericController.paginate( @page || 1 )
-App.Config.set('Organization', { prio: 2000, name: 'Organizations', parent: '#manage', target: '#manage/organizations', controller: Index, permission: ['admin.organization'] }, 'NavBarAdmin')
+App.Config.set('Organization', { prio: 2000, name: 'Organizations', parent: '#manage', target: '#manage/organizations', controller: Organization, permission: ['admin.organization'] }, 'NavBarAdmin')
diff --git a/app/assets/javascripts/app/controllers/organization_profile.coffee b/app/assets/javascripts/app/controllers/organization_profile.coffee
index cb4caaf0f..f3ffc80a9 100644
--- a/app/assets/javascripts/app/controllers/organization_profile.coffee
+++ b/app/assets/javascripts/app/controllers/organization_profile.coffee
@@ -73,7 +73,7 @@ class App.OrganizationProfile extends App.Controller
currentPosition: =>
@$('.profile').scrollTop()
-class ActionRow extends App.ObserverActionRow
+class ActionRow extends App.ControllerObserverActionRow
model: 'Organization'
observe:
member_ids: true
@@ -110,7 +110,7 @@ class ActionRow extends App.ObserverActionRow
}
]
-class Object extends App.ObserverController
+class Object extends App.ControllerObserver
model: 'Organization'
observe:
member_ids: true
@@ -182,7 +182,7 @@ class Object extends App.ObserverController
org.updateAttributes(data)
@log 'debug', 'update', name, value, org
-class Organization extends App.ObserverController
+class Organization extends App.ControllerObserver
model: 'Organization'
observe:
name: true
@@ -190,7 +190,7 @@ class Organization extends App.ObserverController
render: (organization) =>
@html App.Utils.htmlEscape(organization.displayName())
-class Member extends App.ObserverController
+class Member extends App.ControllerObserver
model: 'User'
observe:
firstname: true
diff --git a/app/assets/javascripts/app/controllers/overview.coffee b/app/assets/javascripts/app/controllers/overview.coffee
index b52a04455..1aad70caa 100644
--- a/app/assets/javascripts/app/controllers/overview.coffee
+++ b/app/assets/javascripts/app/controllers/overview.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class Overview extends App.ControllerSubContent
requiredPermission: 'admin.overview'
header: 'Overviews'
constructor: ->
@@ -46,4 +46,4 @@ class Index extends App.ControllerSubContent
)
)
-App.Config.set('Overview', { prio: 2300, name: 'Overviews', parent: '#manage', target: '#manage/overviews', controller: Index, permission: ['admin.overview'] }, 'NavBarAdmin')
+App.Config.set('Overview', { prio: 2300, name: 'Overviews', parent: '#manage', target: '#manage/overviews', controller: Overview, permission: ['admin.overview'] }, 'NavBarAdmin')
diff --git a/app/assets/javascripts/app/controllers/package.coffee b/app/assets/javascripts/app/controllers/package.coffee
index 8f7bb7af0..6ec8ab518 100644
--- a/app/assets/javascripts/app/controllers/package.coffee
+++ b/app/assets/javascripts/app/controllers/package.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class Package extends App.ControllerSubContent
requiredPermission: 'admin.package'
header: 'Packages'
events:
@@ -54,4 +54,4 @@ class Index extends App.ControllerSubContent
@load()
)
-App.Config.set('Packages', { prio: 3700, name: 'Packages', parent: '#system', target: '#system/package', controller: Index, permission: ['admin.package'] }, 'NavBarAdmin')
+App.Config.set('Packages', { prio: 3700, name: 'Packages', parent: '#system', target: '#system/package', controller: Package, permission: ['admin.package'] }, 'NavBarAdmin')
diff --git a/app/assets/javascripts/app/controllers/password_reset.coffee b/app/assets/javascripts/app/controllers/password_reset.coffee
index ea1060dea..bff592332 100644
--- a/app/assets/javascripts/app/controllers/password_reset.coffee
+++ b/app/assets/javascripts/app/controllers/password_reset.coffee
@@ -1,8 +1,10 @@
-class Index extends App.ControllerContent
+class PasswordReset extends App.ControllerFullPage
events:
'submit form': 'submit'
'click .submit': 'submit'
'click .retry': 'retry'
+ forceRender: true
+ className: 'reset_password'
constructor: ->
super
@@ -17,8 +19,6 @@ class Index extends App.ControllerContent
@navigate '#'
return
- @navHide()
-
# set title
@title 'Reset Password'
@navupdate '#password_reset'
@@ -30,10 +30,10 @@ class Index extends App.ControllerContent
{ name: 'username', display: 'Enter your username or email address', tag: 'input', type: 'text', limit: 100, null: false, class: 'input span4' }
]
- @html App.view('password/reset')(params)
+ @replaceWith(App.view('password/reset')(params))
@form = new App.ControllerForm(
- el: @el.find('.form-password-item')
+ el: @el.find('.js-password')
model: { configure_attributes: configure_attributes }
autofocus: true
)
@@ -64,142 +64,6 @@ class Index extends App.ControllerContent
redirect = =>
@navigate "#password_reset_verify/#{data.token}"
@delay(redirect, 2000)
- @render(sent: true)
+ @html(App.view('password/reset_sent')())
-App.Config.set('password_reset', Index, 'Routes')
-
-class Verify extends App.ControllerContent
- events:
- 'submit form': 'submit'
- 'click .submit': 'submit'
-
- constructor: ->
- super
-
- # go back if feature is not enabled
- if !@Config.get('user_lost_password')
- @navigate '#'
- return
-
- # if we are logged in, no passwort reset is wanted, redirect to app
- if @authenticateCheck()
- @navigate '#'
- return
-
- @navHide()
-
- # set title
- @title 'Reset Password'
- @navupdate '#password_reset_verify'
-
- # get data
- params =
- token: @token
- @ajax(
- id: 'password_reset_verify'
- type: 'POST'
- url: "#{@apiPath}/users/password_reset_verify"
- data: JSON.stringify(params)
- processData: true
- success: @renderChange
- )
-
- renderChange: (data) =>
- if data.message is 'ok'
- configure_attributes = [
- { name: 'password', display: 'Password', tag: 'input', type: 'password', limit: 100, null: false, class: 'input' }
- ]
-
- @html App.view('password/reset_change')()
-
- new App.ControllerForm(
- el: @el.find('.form-password-change')
- model: { configure_attributes: configure_attributes }
- autofocus: true
- )
- else
- @html App.view('password/reset_failed')(
- head: 'Reset Password failed!'
- message: 'Token is invalid!'
- )
-
- submit: (e) ->
- e.preventDefault()
- params = @formParam(e.target)
- params['token'] = @token
- @password = params['password']
-
- # disable form
- @formDisable(e)
-
- # validate
- if params['password_confirm'] isnt params['password']
- @formEnable(e)
- @$('[name=password]').val('')
- @$('[name=password_confirm]').val('')
- @notify
- type: 'error'
- msg: 'Can\'t update password, your new passwords do not match. Please try again!'
- removeAll: true
- return
- if !params['password']
- @formEnable(e)
- @notify
- type: 'error'
- msg: 'Please supply your new password!'
- removeAll: true
- return
-
- # get data
- @ajax(
- id: 'password_reset_verify'
- type: 'POST'
- url: "#{@apiPath}/users/password_reset_verify"
- data: JSON.stringify(params)
- processData: true
- success: @renderChanged
- )
-
- renderChanged: (data, status, xhr) =>
- if data.message is 'ok'
- App.Auth.login(
- data:
- username: data.user_login
- password: @password
- success: =>
-
- # login check
- App.Auth.loginCheck()
-
- # add notify
- @notify
- type: 'success'
- msg: 'Woo hoo! Your password has been changed!'
- removeAll: true
-
- # redirect to #
- @navigate '#'
-
- error: =>
- @formEnable( @$('form') )
-
- # add notify
- @notify
- type: 'error'
- msg: 'Something went wrong. Please contact your administrator.'
- removeAll: true
- )
- else
- if data.notice
- @notify
- type: 'error'
- msg: App.i18n.translateContent( data.notice[0], data.notice[1] )
- removeAll: true
- else
- @notify
- type: 'error'
- msg: 'Unable to set password. Please contact your administrator.'
- removeAll: true
- @formEnable( @$('form') )
-
-App.Config.set('password_reset_verify/:token', Verify, 'Routes')
+App.Config.set('password_reset', PasswordReset, 'Routes')
diff --git a/app/assets/javascripts/app/controllers/password_reset_verify.coffee b/app/assets/javascripts/app/controllers/password_reset_verify.coffee
new file mode 100644
index 000000000..78bc5d424
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/password_reset_verify.coffee
@@ -0,0 +1,141 @@
+class PasswordResetVerify extends App.ControllerFullPage
+ events:
+ 'submit form': 'submit'
+ 'click .submit': 'submit'
+ forceRender: true
+ className: 'reset_password'
+
+ constructor: ->
+ super
+
+ # go back if feature is not enabled
+ if !@Config.get('user_lost_password')
+ @navigate '#'
+ return
+
+ # if we are logged in, no passwort reset is wanted, redirect to app
+ if @authenticateCheck()
+ @navigate '#'
+ return
+
+ # set title
+ @title 'Reset Password'
+ @navupdate '#password_reset_verify'
+
+ # get data
+ params =
+ token: @token
+ @ajax(
+ id: 'password_reset_verify'
+ type: 'POST'
+ url: "#{@apiPath}/users/password_reset_verify"
+ data: JSON.stringify(params)
+ processData: true
+ success: @renderChange
+ )
+
+ renderChange: (data) =>
+ if data.message is 'ok'
+ configure_attributes = [
+ { name: 'password', display: 'Password', tag: 'input', type: 'password', limit: 100, null: false, class: 'input' }
+ ]
+
+ @replaceWith(App.view('password/reset_change')())
+
+ new App.ControllerForm(
+ el: @el.find('.js-password')
+ model: { configure_attributes: configure_attributes }
+ autofocus: true
+ )
+ else
+ @replaceWith(App.view('password/reset_failed')(
+ head: 'Reset Password failed!'
+ message: 'Token is invalid!'
+ ))
+
+ submit: (e) ->
+ e.preventDefault()
+ params = @formParam(e.target)
+ params['token'] = @token
+ @password = params['password']
+
+ # disable form
+ @formDisable(e)
+
+ # validate
+ if params['password_confirm'] isnt params['password']
+ @formEnable(e)
+ @$('[name=password]').val('')
+ @$('[name=password_confirm]').val('')
+ @notify(
+ type: 'error'
+ msg: 'Can\'t update password, your new passwords do not match. Please try again!'
+ removeAll: true
+ )
+ return
+ if !params['password']
+ @formEnable(e)
+ @notify(
+ type: 'error'
+ msg: 'Please supply your new password!'
+ removeAll: true
+ )
+ return
+
+ # get data
+ @ajax(
+ id: 'password_reset_verify'
+ type: 'POST'
+ url: "#{@apiPath}/users/password_reset_verify"
+ data: JSON.stringify(params)
+ processData: true
+ success: @renderChanged
+ )
+
+ renderChanged: (data, status, xhr) =>
+ if data.message is 'ok'
+ App.Auth.login(
+ data:
+ username: data.user_login
+ password: @password
+ success: =>
+
+ # login check
+ App.Auth.loginCheck()
+
+ # add notify
+ @notify(
+ type: 'success'
+ msg: 'Woo hoo! Your password has been changed!'
+ removeAll: true
+ )
+
+ # redirect to #
+ @navigate '#'
+
+ error: =>
+ @formEnable(@$('form'))
+
+ # add notify
+ @notify(
+ type: 'error'
+ msg: 'Something went wrong. Please contact your administrator.'
+ removeAll: true
+ )
+ )
+ else
+ if data.notice
+ @notify(
+ type: 'error'
+ msg: App.i18n.translateContent(data.notice[0], data.notice[1])
+ removeAll: true
+ )
+ else
+ @notify(
+ type: 'error'
+ msg: 'Unable to set password. Please contact your administrator.'
+ removeAll: true
+ )
+ @formEnable(@$('form'))
+
+App.Config.set('password_reset_verify/:token', PasswordResetVerify, 'Routes')
diff --git a/app/assets/javascripts/app/controllers/report.coffee b/app/assets/javascripts/app/controllers/report.coffee
index eabcb9a0f..0e2bde4a2 100644
--- a/app/assets/javascripts/app/controllers/report.coffee
+++ b/app/assets/javascripts/app/controllers/report.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerContent
+class Reporting extends App.ControllerAppContent
requiredPermission: 'report'
constructor: ->
@@ -98,13 +98,14 @@ class Index extends App.ControllerContent
ui: @
)
-class Graph extends App.ControllerContent
+class Graph extends App.Controller
constructor: ->
super
# rerender view
- @bind 'ui:report:rerender', =>
+ @controllerBind('ui:report:rerender', =>
@render()
+ )
@render()
@@ -380,8 +381,9 @@ class TimeRangePicker extends App.Controller
super
# rerender view
- @bind 'ui:report:rerender', =>
+ @controllerBind('ui:report:rerender', =>
@render()
+ )
@render()
@@ -411,9 +413,9 @@ class TimePicker extends App.Controller
@_timeSlotPicker()
# rerender view
- @bind 'ui:report:rerender', =>
+ @controllerBind('ui:report:rerender', =>
@render()
-
+ )
@render()
render: =>
@@ -588,5 +590,5 @@ class Sidebar extends App.Controller
App.Event.trigger('ui:report:rerender')
@ui.storeParams()
-App.Config.set('report', Index, 'Routes')
+App.Config.set('report', Reporting, 'Routes')
App.Config.set('Reporting', { prio: 8000, parent: '', name: 'Reporting', translate: true, target: '#report', icon: 'report', permission: ['report'] }, 'NavBarRight')
diff --git a/app/assets/javascripts/app/controllers/report_profile.coffee b/app/assets/javascripts/app/controllers/report_profile.coffee
index 865a4d709..f29378eac 100644
--- a/app/assets/javascripts/app/controllers/report_profile.coffee
+++ b/app/assets/javascripts/app/controllers/report_profile.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class ReportProfile extends App.ControllerSubContent
requiredPermission: 'admin.report_profile'
header: 'Report Profile'
constructor: ->
@@ -34,4 +34,4 @@ class Index extends App.ControllerSubContent
@genericController.paginate( @page || 1 )
-App.Config.set('ReportProfile', { prio: 8000, name: 'Report Profiles', parent: '#manage', target: '#manage/report_profiles', controller: Index, permission: ['admin.report_profile'] }, 'NavBarAdmin')
+App.Config.set('ReportProfile', { prio: 8000, name: 'Report Profiles', parent: '#manage', target: '#manage/report_profiles', controller: ReportProfile, permission: ['admin.report_profile'] }, 'NavBarAdmin')
diff --git a/app/assets/javascripts/app/controllers/role.coffee b/app/assets/javascripts/app/controllers/role.coffee
index dfa2616a4..b29c7f9e0 100644
--- a/app/assets/javascripts/app/controllers/role.coffee
+++ b/app/assets/javascripts/app/controllers/role.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class Role extends App.ControllerSubContent
requiredPermission: 'admin.role'
header: 'Roles'
constructor: ->
@@ -34,4 +34,4 @@ class Index extends App.ControllerSubContent
@genericController.paginate( @page || 1 )
-App.Config.set('Role', { prio: 1600, name: 'Roles', parent: '#manage', target: '#manage/roles', controller: Index, permission: ['admin.role'] }, 'NavBarAdmin')
+App.Config.set('Role', { prio: 1600, name: 'Roles', parent: '#manage', target: '#manage/roles', controller: Role, permission: ['admin.role'] }, 'NavBarAdmin')
diff --git a/app/assets/javascripts/app/controllers/search.coffee b/app/assets/javascripts/app/controllers/search.coffee
index 699563ec3..b2698c6e8 100644
--- a/app/assets/javascripts/app/controllers/search.coffee
+++ b/app/assets/javascripts/app/controllers/search.coffee
@@ -32,7 +32,7 @@ class App.Search extends App.Controller
@render()
# rerender view, e. g. on langauge change
- @bind('ui:rerender', =>
+ @controllerBind('ui:rerender', =>
@render()
)
diff --git a/app/assets/javascripts/app/controllers/session.coffee b/app/assets/javascripts/app/controllers/session.coffee
index 57bdd0a16..7d0217070 100644
--- a/app/assets/javascripts/app/controllers/session.coffee
+++ b/app/assets/javascripts/app/controllers/session.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class Session extends App.ControllerSubContent
requiredPermission: 'admin.session'
header: 'Sessions'
events:
@@ -49,4 +49,4 @@ class Index extends App.ControllerSubContent
@load()
)
-App.Config.set('Session', { prio: 3800, name: 'Sessions', parent: '#system', target: '#system/sessions', controller: Index, permission: ['admin.session'] }, 'NavBarAdmin' )
+App.Config.set('Session', { prio: 3800, name: 'Sessions', parent: '#system', target: '#system/sessions', controller: Session, permission: ['admin.session'] }, 'NavBarAdmin' )
diff --git a/app/assets/javascripts/app/controllers/signup.coffee b/app/assets/javascripts/app/controllers/signup.coffee
index ae75bd56b..d9da1e2d9 100644
--- a/app/assets/javascripts/app/controllers/signup.coffee
+++ b/app/assets/javascripts/app/controllers/signup.coffee
@@ -1,9 +1,10 @@
-class Index extends App.ControllerContent
+class Signup extends App.ControllerFullPage
events:
'submit form': 'submit'
'click .submit': 'submit'
'click .js-submitResend': 'resend'
'click .cancel': 'cancel'
+ className: 'signup'
constructor: ->
super
@@ -13,8 +14,6 @@ class Index extends App.ControllerContent
@navigate '#'
return
- @navHide()
-
# set title
@title 'Sign up'
@navupdate '#signup'
@@ -23,7 +22,7 @@ class Index extends App.ControllerContent
render: ->
- @html App.view('signup')()
+ @replaceWith(App.view('signup')())
@form = new App.ControllerForm(
el: @el.find('form')
@@ -70,9 +69,9 @@ class Index extends App.ControllerContent
# save user
user.save(
done: (r) =>
- @html App.view('signup/verify')(
+ @replaceWith(App.view('signup/verify')(
email: @params.email
- )
+ ))
fail: (settings, details) =>
@formEnable(e)
@form.showAlert(details.error_human || details.error || 'Unable to create user!')
@@ -93,10 +92,11 @@ class Index extends App.ControllerContent
@formEnable(e)
# add notify
- @notify
+ @notify(
type: 'success'
msg: App.i18n.translateContent('Email sent to "%s". Please verify your email address.', @params.email)
removeAll: true
+ )
if data.token && @Config.get('developer_mode') is true
@navigate "#email_verify/#{data.token}"
@@ -109,9 +109,9 @@ class Index extends App.ControllerContent
if !_.isEmpty(detailsRaw)
details = JSON.parse(detailsRaw)
- @notify
+ @notify(
type: 'error'
msg: App.i18n.translateContent(details.error || 'Could not process your request')
removeAll: true
-
-App.Config.set('signup', Index, 'Routes')
+ )
+App.Config.set('signup', Signup, 'Routes')
diff --git a/app/assets/javascripts/app/controllers/sla.coffee b/app/assets/javascripts/app/controllers/sla.coffee
index a8f5160bf..b3f50e1d3 100644
--- a/app/assets/javascripts/app/controllers/sla.coffee
+++ b/app/assets/javascripts/app/controllers/sla.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class Sla extends App.ControllerSubContent
requiredPermission: 'admin.sla'
header: 'SLAs'
events:
@@ -112,4 +112,4 @@ class Index extends App.ControllerSubContent
"#{hours}:#{minutes}"
-App.Config.set('Sla', { prio: 2900, name: 'SLAs', parent: '#manage', target: '#manage/slas', controller: Index, permission: ['admin.sla'] }, 'NavBarAdmin')
+App.Config.set('Sla', { prio: 2900, name: 'SLAs', parent: '#manage', target: '#manage/slas', controller: Sla, permission: ['admin.sla'] }, 'NavBarAdmin')
diff --git a/app/assets/javascripts/app/controllers/tag.coffee b/app/assets/javascripts/app/controllers/tag.coffee
index 62496f3fe..1af93e693 100644
--- a/app/assets/javascripts/app/controllers/tag.coffee
+++ b/app/assets/javascripts/app/controllers/tag.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class Tag extends App.ControllerSubContent
requiredPermission: 'admin.tag'
header: 'Tags'
events:
@@ -149,4 +149,4 @@ class DestroyConfirm extends App.ControllerModal
@close()
)
-App.Config.set('Tags', { prio: 2320, name: 'Tags', parent: '#manage', target: '#manage/tags', controller: Index, permission: ['admin.tag'] }, 'NavBarAdmin')
+App.Config.set('Tags', { prio: 2320, name: 'Tags', parent: '#manage', target: '#manage/tags', controller: Tag, permission: ['admin.tag'] }, 'NavBarAdmin')
diff --git a/app/assets/javascripts/app/controllers/taskbar_widget.coffee b/app/assets/javascripts/app/controllers/taskbar_widget.coffee
index 7d566799d..940d91c89 100644
--- a/app/assets/javascripts/app/controllers/taskbar_widget.coffee
+++ b/app/assets/javascripts/app/controllers/taskbar_widget.coffee
@@ -44,19 +44,19 @@ class App.TaskbarWidget extends App.CollectionController
@el.sortable(dndOptions)
# bind to changes
- @bind('taskInit', =>
+ @controllerBind('taskInit', =>
@queue.push ['renderAll']
@uIRunner()
)
- @bind('taskUpdate', (tasks) =>
+ @controllerBind('taskUpdate', (tasks) =>
@queue.push ['change', tasks]
@uIRunner()
)
- @bind('taskRemove', (tasks) =>
+ @controllerBind('taskRemove', (tasks) =>
@queue.push ['destroy', tasks]
@uIRunner()
)
- @bind('taskCollectionOrderSet', (taskKeys) =>
+ @controllerBind('taskCollectionOrderSet', (taskKeys) =>
@collectionOrderSet(taskKeys)
)
diff --git a/app/assets/javascripts/app/controllers/text_module.coffee b/app/assets/javascripts/app/controllers/text_module.coffee
index 2d39b1a72..c9bd21665 100644
--- a/app/assets/javascripts/app/controllers/text_module.coffee
+++ b/app/assets/javascripts/app/controllers/text_module.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class TextModule extends App.ControllerSubContent
requiredPermission: 'admin.text_module'
header: 'Text modules'
constructor: ->
@@ -41,4 +41,4 @@ class Index extends App.ControllerSubContent
@genericController.paginate( @page || 1 )
-App.Config.set('TextModule', { prio: 2300, name: 'Text modules', parent: '#manage', target: '#manage/text_modules', controller: Index, permission: ['admin.text_module'] }, 'NavBarAdmin')
+App.Config.set('TextModule', { prio: 2300, name: 'Text modules', parent: '#manage', target: '#manage/text_modules', controller: TextModule, permission: ['admin.text_module'] }, 'NavBarAdmin')
diff --git a/app/assets/javascripts/app/controllers/ticket_overview.coffee b/app/assets/javascripts/app/controllers/ticket_overview.coffee
index 7751af440..acb23f386 100644
--- a/app/assets/javascripts/app/controllers/ticket_overview.coffee
+++ b/app/assets/javascripts/app/controllers/ticket_overview.coffee
@@ -77,9 +77,9 @@ class App.TicketOverview extends App.Controller
@render()
# rerender view, e. g. on language change
- @bind 'ui:rerender', =>
+ @controllerBind('ui:rerender', =>
@renderBatchOverlay()
-
+ )
load = (data) =>
App.Collection.loadAssets(data.assets)
@formMeta = data.form_meta
@@ -134,7 +134,7 @@ class App.TicketOverview extends App.Controller
@renderOptions()
- $('#app').append @batchDragger
+ @appEl.append(@batchDragger)
@draggedItems.each (i, item) ->
dx = $(item).data('offset').left - $(item).offset().left - x
@@ -592,17 +592,20 @@ class App.TicketOverview extends App.Controller
render: ->
elLocal = $(App.view('ticket_overview/index')())
+ @navBarControllerVertical.releaseController() if @navBarControllerVertical
@navBarControllerVertical = new Navbar(
el: elLocal.find('.overview-header')
view: @view
vertical: true
)
+ @navBarController.releaseController() if @navBarController
@navBarController = new Navbar(
el: elLocal.filter('.sidebar')
view: @view
)
+ @contentController.releaseController() if @contentController
@contentController = new Table(
el: elLocal.find('.overview-table')
view: @view
@@ -614,14 +617,14 @@ class App.TicketOverview extends App.Controller
@html elLocal
- @el.find('.main').on('click', =>
+ @$('.main').on('click', =>
@activeFocus = 'overview'
)
- @el.find('.sidebar').on('click', =>
+ @$('.sidebar').on('click', =>
@activeFocus = 'nav'
)
- @bind('overview:fetch', =>
+ @controllerBind('overview:fetch', =>
return if !@view
update = =>
App.OverviewListCollection.fetch(@view)
@@ -692,7 +695,7 @@ class App.TicketOverview extends App.Controller
# redirect to last overview if we got called in first level
@view = params['view']
if !@view && @viewLast
- @navigate "ticket/view/#{@viewLast}", true
+ @navigate "ticket/view/#{@viewLast}", { hideCurrentLocationFromHistory: true }
return
# build nav bar
@@ -718,6 +721,7 @@ class App.TicketOverview extends App.Controller
@viewLast = @view
# build content
+ @contentController.releaseController() if @contentController
@contentController = new Table(
el: @$('.overview-table')
view: @view
@@ -860,9 +864,9 @@ class Navbar extends App.Controller
@bindId = App.OverviewIndexCollection.bind(@render)
# rerender view, e. g. on language change
- @bind 'ui:rerender', =>
+ @controllerBind('ui:rerender', =>
@render(App.OverviewIndexCollection.get())
-
+ )
if @vertical
$(window).on 'resize.navbar', @autoFoldTabs
@@ -946,7 +950,7 @@ class Navbar extends App.Controller
# redirect to first view
if @activeState && !@view && !@vertical
view = data[0].link
- @navigate "ticket/view/#{view}", true
+ @navigate "ticket/view/#{view}", { hideCurrentLocationFromHistory: true }
return
# add new views
@@ -979,10 +983,11 @@ class Table extends App.Controller
@bindId = App.OverviewListCollection.bind(@view, @updateTable)
# rerender view, e. g. on langauge change
- @bind 'ui:rerender', =>
+ @controllerBind('ui:rerender', =>
return if !@authenticateCheck()
return if !@view
@render(App.OverviewListCollection.get(@view))
+ )
show: =>
if @table
@@ -1333,6 +1338,7 @@ class Table extends App.Controller
settings: (e) =>
e.preventDefault()
@keyboardOff()
+
new App.OverviewSettings(
overview_id: @overview.id
view_mode: @view_mode
@@ -1495,10 +1501,10 @@ class BulkForm extends App.Controller
@bulkCount = @holder.find('.table-overview').find('[name="bulk"]:checked').length
if @bulkCount is 0
- App.Event.trigger 'notify', {
+ App.Event.trigger('notify', {
type: 'error'
msg: App.i18n.translateContent('At least one object must be selected.')
- }
+ })
return
ticket_ids = []
@@ -1535,10 +1541,10 @@ class BulkForm extends App.Controller
screen: 'edit'
)
- App.Event.trigger 'notify', {
+ App.Event.trigger('notify', {
type: 'error'
msg: App.i18n.translateContent('Bulk action stopped %s!', errorString)
- }
+ })
@cancel()
return
@@ -1580,10 +1586,10 @@ class BulkForm extends App.Controller
@saveTicketArticle(ticket, article)
@holder.find('.table-overview').find('[name="bulk"]:checked').prop('checked', false)
- App.Event.trigger 'notify', {
+ App.Event.trigger('notify', {
type: 'success'
msg: App.i18n.translateContent('Bulk action executed!')
- }
+ })
saveTicketArticle: (ticket, article) =>
ticket.save(
@@ -1749,6 +1755,7 @@ class TicketOverviewRouter extends App.ControllerPermanent
# cleanup params
clean_params =
view: params.view
+ appEl: params.appEl
App.TaskManager.execute(
key: 'TicketOverview'
diff --git a/app/assets/javascripts/app/controllers/ticket_zoom.coffee b/app/assets/javascripts/app/controllers/ticket_zoom.coffee
index d0bcf2a6b..878c9c660 100644
--- a/app/assets/javascripts/app/controllers/ticket_zoom.coffee
+++ b/app/assets/javascripts/app/controllers/ticket_zoom.coffee
@@ -43,7 +43,7 @@ class App.TicketZoom extends App.Controller
@interval(update, 1800000, 'pull_check')
# fetch new data if triggered
- @bind('Ticket:update Ticket:touch', (data) =>
+ @controllerBind('Ticket:update Ticket:touch', (data) =>
# check if current ticket has changed
return if data.id.toString() isnt @ticket_id.toString()
@@ -54,7 +54,7 @@ class App.TicketZoom extends App.Controller
)
# after a new websocket connection, check if ticket has changed
- @bind('spool:sent', =>
+ @controllerBind('spool:sent', =>
if @initSpoolSent
@fetch(true)
return
@@ -62,7 +62,7 @@ class App.TicketZoom extends App.Controller
)
# listen to rerender sidebars
- @bind('ui::ticket::sidebarRerender', (data) =>
+ @controllerBind('ui::ticket::sidebarRerender', (data) =>
return if data.taskKey isnt @taskKey
return if !@sidebarWidget
@sidebarWidget.render(@formCurrent())
diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee
index 2eaa18e1a..ad075af47 100644
--- a/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee
+++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee
@@ -55,7 +55,7 @@ class App.TicketZoomArticleNew extends App.Controller
@renderAttachment(attachment)
# set article type and expand text area
- @bind('ui::ticket::setArticleType', (data) =>
+ @controllerBind('ui::ticket::setArticleType', (data) =>
return if data.ticket.id.toString() isnt @ticket_id.toString()
@setArticleTypePre(data.type.name, data.signaturePosition)
@@ -81,7 +81,7 @@ class App.TicketZoomArticleNew extends App.Controller
)
# add article attachment
- @bind('ui::ticket::addArticleAttachent', (data) =>
+ @controllerBind('ui::ticket::addArticleAttachent', (data) =>
return if data.ticket?.id?.toString() isnt @ticket_id.toString() && data.form_id isnt @form_id
return if _.isEmpty(data.attachments)
for file in data.attachments
@@ -89,7 +89,7 @@ class App.TicketZoomArticleNew extends App.Controller
)
# reset new article screen
- @bind('ui::ticket::taskReset', (data) =>
+ @controllerBind('ui::ticket::taskReset', (data) =>
@releaseGlobalClickEvents()
return if data.ticket_id.toString() isnt @ticket_id.toString()
@type = 'note'
@@ -98,18 +98,18 @@ class App.TicketZoomArticleNew extends App.Controller
)
# set expand of text area only once
- @bind('ui::ticket::shown', (data) =>
+ @controllerBind('ui::ticket::shown', (data) =>
return if data.ticket_id.toString() isnt @ticket.id.toString()
@tokanice(@type)
)
# rerender, e. g. on language change
- @bind('ui:rerender', =>
+ @controllerBind('ui:rerender', =>
@render()
)
# update security options
- @bind('ui::ticket::updateSecurityOptions', (data) =>
+ @controllerBind('ui::ticket::updateSecurityOptions', (data) =>
return if data.taskKey isnt @taskKey
@updateSecurityOptions()
)
diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee
index 874d05e7f..563e71a09 100644
--- a/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee
+++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee
@@ -66,7 +66,7 @@ class App.TicketZoomArticleView extends App.Controller
for id, viewItem of @articleController
viewItem.updateFormId(newFormId)
-class ArticleViewItem extends App.ObserverController
+class ArticleViewItem extends App.ControllerObserver
model: 'TicketArticle'
observe:
from: true
@@ -96,7 +96,7 @@ class ArticleViewItem extends App.ObserverController
@seeMore = false
# set expand of text area only once
- @bind('ui::ticket::shown', (data) =>
+ @controllerBind('ui::ticket::shown', (data) =>
return if data.ticket_id.toString() isnt @ticket.id.toString()
# set highlighter
diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/attribute_bar.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/attribute_bar.coffee
index 0e95727f7..4abc20c8d 100644
--- a/app/assets/javascripts/app/controllers/ticket_zoom/attribute_bar.coffee
+++ b/app/assets/javascripts/app/controllers/ticket_zoom/attribute_bar.coffee
@@ -21,11 +21,11 @@ class App.TicketZoomAttributeBar extends App.Controller
@render()
# rerender, e. g. on language change
- @bind('ui:rerender', =>
+ @controllerBind('ui:rerender', =>
@render()
)
- @bind('MacroPreconditionUpdate', (data) =>
+ @controllerBind('MacroPreconditionUpdate', (data) =>
return if data.taskKey isnt @taskKey
@searchCondition = data.params
@render()
diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/customer_avatar.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/customer_avatar.coffee
index 1b1e7b07e..18335ed27 100644
--- a/app/assets/javascripts/app/controllers/ticket_zoom/customer_avatar.coffee
+++ b/app/assets/javascripts/app/controllers/ticket_zoom/customer_avatar.coffee
@@ -1,4 +1,4 @@
-class App.TicketCustomerAvatar extends App.ObserverController
+class App.TicketCustomerAvatar extends App.ControllerObserver
model: 'Ticket'
observe:
customer_id: true
diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/highlighter.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/highlighter.coffee
index 1ff299a4e..636a5115f 100644
--- a/app/assets/javascripts/app/controllers/ticket_zoom/highlighter.coffee
+++ b/app/assets/javascripts/app/controllers/ticket_zoom/highlighter.coffee
@@ -218,7 +218,6 @@ class App.TicketZoomHighlighter extends App.Controller
article.attr('data-highlightcolor', @colors[@activeColorIndex].name)
if @highlighter.selectionOverlapsHighlight selection
- console.log('SELECTION EXISTS, REMOVED IT')
@highlighter.unhighlightSelection()
selection.removeAllRanges()
@highlightDisable()
@@ -226,7 +225,6 @@ class App.TicketZoomHighlighter extends App.Controller
return
if selection && selection.rangeCount > 0
- console.log('NEW SELECTION', selection)
@highlighter.highlightSelection @highlightClass,
selection: selection
containerElementId: article.get(0).id
diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/meta.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/meta.coffee
index ed6dfc590..8c50fa54f 100644
--- a/app/assets/javascripts/app/controllers/ticket_zoom/meta.coffee
+++ b/app/assets/javascripts/app/controllers/ticket_zoom/meta.coffee
@@ -1,4 +1,4 @@
-class App.TicketZoomMeta extends App.ObserverController
+class App.TicketZoomMeta extends App.ControllerObserver
model: 'Ticket'
observe:
number: true
diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/sidebar.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/sidebar.coffee
index 4ebb1ab8d..20389ffc8 100644
--- a/app/assets/javascripts/app/controllers/ticket_zoom/sidebar.coffee
+++ b/app/assets/javascripts/app/controllers/ticket_zoom/sidebar.coffee
@@ -1,4 +1,4 @@
-class App.TicketZoomSidebar extends App.ObserverController
+class App.TicketZoomSidebar extends App.ControllerObserver
model: 'Ticket'
observe:
customer_id: true
diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/sidebar_ticket.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/sidebar_ticket.coffee
index 1a0f401ef..2fa7bee5d 100644
--- a/app/assets/javascripts/app/controllers/ticket_zoom/sidebar_ticket.coffee
+++ b/app/assets/javascripts/app/controllers/ticket_zoom/sidebar_ticket.coffee
@@ -1,4 +1,4 @@
-class Edit extends App.ObserverController
+class Edit extends App.ControllerObserver
model: 'Ticket'
observeNot:
created_at: true
@@ -50,7 +50,7 @@ class Edit extends App.ObserverController
return if @resetBind
@resetBind = true
- @bind('ui::ticket::taskReset', (data) =>
+ @controllerBind('ui::ticket::taskReset', (data) =>
return if data.ticket_id.toString() isnt ticket.id.toString()
@render(ticket)
)
@@ -58,7 +58,7 @@ class Edit extends App.ObserverController
class SidebarTicket extends App.Controller
constructor: ->
super
- @bind 'config_update_local', (data) => @configUpdated(data)
+ @controllerBind('config_update_local', (data) => @configUpdated(data))
configUpdated: (data) ->
if data.name != 'kb_active'
diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/time_unit.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/time_unit.coffee
index d89ebe6b3..5478c6259 100644
--- a/app/assets/javascripts/app/controllers/ticket_zoom/time_unit.coffee
+++ b/app/assets/javascripts/app/controllers/ticket_zoom/time_unit.coffee
@@ -1,4 +1,4 @@
-class App.TicketZoomTimeUnit extends App.ObserverController
+class App.TicketZoomTimeUnit extends App.ControllerObserver
model: 'Ticket'
observe:
time_unit: true
diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/title.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/title.coffee
index 013199454..a9acea2ea 100644
--- a/app/assets/javascripts/app/controllers/ticket_zoom/title.coffee
+++ b/app/assets/javascripts/app/controllers/ticket_zoom/title.coffee
@@ -1,4 +1,4 @@
-class App.TicketZoomTitle extends App.ObserverController
+class App.TicketZoomTitle extends App.ControllerObserver
model: 'Ticket'
template: 'ticket_zoom/title'
observe:
diff --git a/app/assets/javascripts/app/controllers/time_accounting.coffee b/app/assets/javascripts/app/controllers/time_accounting.coffee
index f63f3b449..7e1ec5d43 100644
--- a/app/assets/javascripts/app/controllers/time_accounting.coffee
+++ b/app/assets/javascripts/app/controllers/time_accounting.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class TimeAccounting extends App.ControllerSubContent
requiredPermission: 'admin.time_accounting'
header: 'Time Accounting'
events:
@@ -222,4 +222,4 @@ class ByOrganization extends App.Controller
rows: rows
)
-App.Config.set('TimeAccounting', { prio: 8500, name: 'Time Accounting', parent: '#manage', target: '#manage/time_accounting', controller: Index, permission: ['admin.time_accounting'] }, 'NavBarAdmin')
+App.Config.set('TimeAccounting', { prio: 8500, name: 'Time Accounting', parent: '#manage', target: '#manage/time_accounting', controller: TimeAccounting, permission: ['admin.time_accounting'] }, 'NavBarAdmin')
diff --git a/app/assets/javascripts/app/controllers/translation.coffee b/app/assets/javascripts/app/controllers/translation.coffee
index 70900c430..41e624d5f 100644
--- a/app/assets/javascripts/app/controllers/translation.coffee
+++ b/app/assets/javascripts/app/controllers/translation.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class Translation extends App.ControllerSubContent
requiredPermission: 'admin.translation'
header: 'Translations'
events:
@@ -10,13 +10,13 @@ class Index extends App.ControllerSubContent
super
@locale = App.i18n.get()
@render()
- @bind('i18n:translation_update_todo', =>
+ @controllerBind('i18n:translation_update_todo', =>
@load('i18n:translation_update_todo')
)
- @bind('i18n:translation_update_list', =>
+ @controllerBind('i18n:translation_update_list', =>
@load('i18n:translation_update_list')
)
- @bind('i18n:translation_update', =>
+ @controllerBind('i18n:translation_update', =>
@load()
)
@@ -350,4 +350,4 @@ class TranslationList extends App.Controller
reset.addClass('hidden')
reset.closest('tr').removeClass('warning')
-App.Config.set('Translation', { prio: 1800, parent: '#system', name: 'Translations', target: '#system/translation', controller: Index, permission: ['admin.translation'] }, 'NavBarAdmin' )
+App.Config.set('Translation', { prio: 1800, parent: '#system', name: 'Translations', target: '#system/translation', controller: Translation, permission: ['admin.translation'] }, 'NavBarAdmin' )
diff --git a/app/assets/javascripts/app/controllers/trigger.coffee b/app/assets/javascripts/app/controllers/trigger.coffee
index 202760626..ec1ff806e 100644
--- a/app/assets/javascripts/app/controllers/trigger.coffee
+++ b/app/assets/javascripts/app/controllers/trigger.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class Trigger extends App.ControllerSubContent
requiredPermission: 'admin.trigger'
header: 'Triggers'
constructor: ->
@@ -35,4 +35,4 @@ class Index extends App.ControllerSubContent
@genericController.paginate( @page || 1 )
-App.Config.set('Trigger', { prio: 3300, name: 'Trigger', parent: '#manage', target: '#manage/trigger', controller: Index, permission: ['admin.trigger'] }, 'NavBarAdmin')
+App.Config.set('Trigger', { prio: 3300, name: 'Trigger', parent: '#manage', target: '#manage/trigger', controller: Trigger, permission: ['admin.trigger'] }, 'NavBarAdmin')
diff --git a/app/assets/javascripts/app/controllers/users.coffee b/app/assets/javascripts/app/controllers/user.coffee
similarity index 97%
rename from app/assets/javascripts/app/controllers/users.coffee
rename to app/assets/javascripts/app/controllers/user.coffee
index a7b160350..7d4501bc4 100644
--- a/app/assets/javascripts/app/controllers/users.coffee
+++ b/app/assets/javascripts/app/controllers/user.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class User extends App.ControllerSubContent
requiredPermission: 'admin.user'
header: 'Users'
elements:
@@ -189,4 +189,4 @@ class Index extends App.ControllerSubContent
container: @el.closest('.content')
)
-App.Config.set( 'User', { prio: 1000, name: 'Users', parent: '#manage', target: '#manage/users', controller: Index, permission: ['admin.user'] }, 'NavBarAdmin' )
+App.Config.set( 'User', { prio: 1000, name: 'Users', parent: '#manage', target: '#manage/users', controller: User, permission: ['admin.user'] }, 'NavBarAdmin' )
diff --git a/app/assets/javascripts/app/controllers/user_profile.coffee b/app/assets/javascripts/app/controllers/user_profile.coffee
index f8989e481..3b3ed3ee7 100644
--- a/app/assets/javascripts/app/controllers/user_profile.coffee
+++ b/app/assets/javascripts/app/controllers/user_profile.coffee
@@ -74,7 +74,7 @@ class App.UserProfile extends App.Controller
currentPosition: =>
@$('.profile').scrollTop()
-class ActionRow extends App.ObserverActionRow
+class ActionRow extends App.ControllerObserverActionRow
model: 'User'
observe:
verified: true
@@ -159,7 +159,7 @@ class ActionRow extends App.ObserverActionRow
actions
-class Object extends App.ObserverController
+class Object extends App.ControllerObserver
model: 'User'
observeNot:
cid: true
@@ -221,7 +221,7 @@ class Object extends App.ObserverController
user.updateAttributes(data)
@log 'debug', 'update', name, value, user
-class Organization extends App.ObserverController
+class Organization extends App.ControllerObserver
model: 'Organization'
observe:
name: true
@@ -231,7 +231,7 @@ class Organization extends App.ObserverController
organization: organization
)
-class User extends App.ObserverController
+class User extends App.ControllerObserver
model: 'User'
observe:
firstname: true
diff --git a/app/assets/javascripts/app/controllers/version.coffee b/app/assets/javascripts/app/controllers/version.coffee
index 44bad0de8..c4a0becb3 100644
--- a/app/assets/javascripts/app/controllers/version.coffee
+++ b/app/assets/javascripts/app/controllers/version.coffee
@@ -1,4 +1,4 @@
-class Index extends App.ControllerSubContent
+class Version extends App.ControllerSubContent
requiredPermission: 'admin.version'
header: 'Version'
@@ -25,4 +25,4 @@ class Index extends App.ControllerSubContent
version: @version
)
-App.Config.set('Version', { prio: 3800, name: 'Version', parent: '#system', target: '#system/version', controller: Index, permission: ['admin.version'] }, 'NavBarAdmin' )
+App.Config.set('Version', { prio: 3800, name: 'Version', parent: '#system', target: '#system/version', controller: Version, permission: ['admin.version'] }, 'NavBarAdmin' )
diff --git a/app/assets/javascripts/app/controllers/widget/avatar.coffee b/app/assets/javascripts/app/controllers/widget/avatar.coffee
index 9dae76b9a..ff376ce01 100644
--- a/app/assets/javascripts/app/controllers/widget/avatar.coffee
+++ b/app/assets/javascripts/app/controllers/widget/avatar.coffee
@@ -1,4 +1,4 @@
-class App.WidgetAvatar extends App.ObserverController
+class App.WidgetAvatar extends App.ControllerObserver
@extend App.PopoverProvidable
@registerPopovers 'User'
diff --git a/app/assets/javascripts/app/controllers/widget/error_modal.coffee b/app/assets/javascripts/app/controllers/widget/error_modal.coffee
new file mode 100644
index 000000000..6133359c6
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/widget/error_modal.coffee
@@ -0,0 +1,17 @@
+class App.ErrorModal 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()
diff --git a/app/assets/javascripts/app/controllers/widget/import.coffee b/app/assets/javascripts/app/controllers/widget/import.coffee
new file mode 100644
index 000000000..45cccb567
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/widget/import.coffee
@@ -0,0 +1,67 @@
+class App.Import extends App.ControllerModal
+ buttonClose: true
+ buttonCancel: true
+ buttonSubmit: 'Import'
+ autoFocusOnFirstInput: false
+ head: 'Import'
+ large: true
+ templateDirectory: 'generic/object_import'
+ baseUrl: '/api/v1/text_modules'
+
+ content: =>
+
+ # show start dialog
+ content = $(App.view("#{@templateDirectory}/index")(
+ head: 'Import'
+ import_example_url: "#{@baseUrl}/import_example"
+ deleteOption: @deleteOption
+ ))
+
+ # check if data is processing...
+ if @data
+ result = App.view("#{@templateDirectory}/result")(
+ @data
+ )
+ content.find('.js-error').html(result)
+ if result
+ content.find('.js-error').removeClass('hide')
+ else
+ content.find('.js-error').addClass('hide')
+ content
+
+ onSubmit: (e) =>
+ params = new FormData($(e.currentTarget).closest('form').get(0))
+ params.set('try', true)
+ if _.isEmpty(params.get('data'))
+ params.delete('data')
+ @formDisable(e)
+ @ajax(
+ id: 'csv_import'
+ type: 'POST'
+ url: "#{@baseUrl}/import"
+ processData: false
+ contentType: false
+ cache: false
+ data: params
+ success: (data, status, xhr) =>
+ if data.result is 'success'
+ new App.ImportTryResult(
+ container: @el.closest('.content')
+ result: data
+ params: params
+ templateDirectory: @templateDirectory
+ baseUrl: @baseUrl
+ )
+ @close()
+ return
+ @data = data
+ @update()
+ @formEnable(e)
+ error: (data) =>
+ details = data.responseJSON || {}
+ @notify
+ type: 'error'
+ msg: App.i18n.translateContent(details.error_human || details.error || 'Unable to import!')
+ timeout: 6000
+ @formEnable(e)
+ )
diff --git a/app/assets/javascripts/app/controllers/widget/import_result.coffee b/app/assets/javascripts/app/controllers/widget/import_result.coffee
new file mode 100644
index 000000000..5a23d5b72
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/widget/import_result.coffee
@@ -0,0 +1,19 @@
+class App.ImportResult extends App.ControllerModal
+ buttonClose: true
+ buttonCancel: true
+ buttonSubmit: 'Close'
+ autoFocusOnFirstInput: false
+ head: 'Import'
+ large: true
+ templateDirectory: 'generic/object_import/'
+
+ content: =>
+
+ content = $(App.view("#{@templateDirectory}/imported")(
+ head: 'Imported'
+ result: @result
+ ))
+ content
+
+ onSubmit: (e) =>
+ @close()
diff --git a/app/assets/javascripts/app/controllers/widget/import_try_result.coffee b/app/assets/javascripts/app/controllers/widget/import_try_result.coffee
new file mode 100644
index 000000000..a333e06d8
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/widget/import_try_result.coffee
@@ -0,0 +1,65 @@
+class App.ImportTryResult extends App.ControllerModal
+ buttonClose: true
+ buttonCancel: true
+ buttonSubmit: 'Yes, start real import.'
+ autoFocusOnFirstInput: false
+ head: 'Import'
+ large: true
+ templateDirectory: 'generic/object_import/'
+ baseUrl: '/api/v1/text_modules'
+
+ content: =>
+
+ # show start dialog
+ content = $(App.view("#{@templateDirectory}/import_try")(
+ head: 'Import'
+ import_example_url: "#{@baseUrl}/import"
+ result: @result
+ ))
+
+ # check if data is processing...
+ if @data
+ result = App.view("#{@templateDirectory}/result")(
+ @data
+ )
+ content.find('.js-error').html(result)
+ if result
+ content.find('.js-error').removeClass('hide')
+ else
+ content.find('.js-error').addClass('hide')
+
+ content
+
+ onSubmit: (e) =>
+ @params.set('try', false)
+ @formDisable(e)
+ @ajax(
+ id: 'csv_import'
+ type: 'POST'
+ url: "#{@baseUrl}/import"
+ processData: false
+ contentType: false
+ cache: false
+ data: @params
+ success: (data, status, xhr) =>
+ if data.result is 'success'
+ new App.ImportResult(
+ container: @el.closest('.content')
+ result: data
+ params: @params
+ templateDirectory: @templateDirectory
+ baseUrl: @baseUrl
+ )
+ @close()
+ return
+ @data = data
+ @update()
+ @formEnable(e)
+ error: (data) =>
+ details = data.responseJSON || {}
+ @notify
+ type: 'error'
+ msg: App.i18n.translateContent(details.error_human || details.error || 'Unable to import!')
+ timeout: 6000
+ @formEnable(e)
+ )
diff --git a/app/assets/javascripts/app/controllers/widget/invite_user.coffee b/app/assets/javascripts/app/controllers/widget/invite_user.coffee
index 6b10fd9bd..852455f0c 100644
--- a/app/assets/javascripts/app/controllers/widget/invite_user.coffee
+++ b/app/assets/javascripts/app/controllers/widget/invite_user.coffee
@@ -1,4 +1,4 @@
-class App.InviteUser extends App.WizardModal
+class App.InviteUser extends App.ControllerWizardModal
events:
'click .js-close': 'hide'
'submit .js-user': 'submit'
diff --git a/app/assets/javascripts/app/controllers/widget/online_notification.coffee b/app/assets/javascripts/app/controllers/widget/online_notification.coffee
index bbca4f306..61b3460d9 100644
--- a/app/assets/javascripts/app/controllers/widget/online_notification.coffee
+++ b/app/assets/javascripts/app/controllers/widget/online_notification.coffee
@@ -20,7 +20,7 @@ class App.OnlineNotificationWidget extends App.Controller
super
# at runtime if an online notification has changed
- @bind('OnlineNotification::changed', =>
+ @controllerBind('OnlineNotification::changed', =>
@delay(
=> @fetch()
2200
@@ -30,7 +30,7 @@ class App.OnlineNotificationWidget extends App.Controller
# after new websocket connection has been established
@ignoreInitLogin = false
- @bind('ws:login', =>
+ @controllerBind('ws:login', =>
if @ignoreInitLogin
@delay(
=> @fetch()
@@ -41,7 +41,7 @@ class App.OnlineNotificationWidget extends App.Controller
)
# rebuild widget on auth
- @bind('auth', (user) =>
+ @controllerBind('auth', (user) =>
if !user
@counterUpdate(0)
return
@@ -55,7 +55,7 @@ class App.OnlineNotificationWidget extends App.Controller
@createContainer()
# rerender view, e.g. on language change
- @bind('ui:rerender', =>
+ @controllerBind('ui:rerender', =>
@createContainer()
'online_notification'
)
diff --git a/app/assets/javascripts/app/controllers/widget/organization.coffee b/app/assets/javascripts/app/controllers/widget/organization.coffee
index 6031d45bd..5901dbdc3 100644
--- a/app/assets/javascripts/app/controllers/widget/organization.coffee
+++ b/app/assets/javascripts/app/controllers/widget/organization.coffee
@@ -71,7 +71,7 @@ class App.WidgetOrganization extends App.Controller
org.updateAttributes(data)
@log 'notice', 'update', name, value, org
-class User extends App.ObserverController
+class User extends App.ControllerObserver
@extend App.PopoverProvidable
@registerPopovers 'User'
diff --git a/app/assets/javascripts/app/controllers/widget/session_message.coffee b/app/assets/javascripts/app/controllers/widget/session_message.coffee
new file mode 100644
index 000000000..3c6e5bacd
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/widget/session_message.coffee
@@ -0,0 +1,16 @@
+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()
diff --git a/app/assets/javascripts/app/controllers/widget/sidebar.coffee b/app/assets/javascripts/app/controllers/widget/sidebar.coffee
new file mode 100644
index 000000000..fe87e6ac9
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/widget/sidebar.coffee
@@ -0,0 +1,146 @@
+class App.Sidebar extends App.Controller
+ elements:
+ '.tabsSidebar-tab': 'tabs'
+ '.sidebar': 'sidebars'
+
+ events:
+ 'click .tabsSidebar-tab': 'toggleTab'
+ 'click .tabsSidebar-close': 'toggleSidebar'
+ 'click .sidebar-header .js-headline': 'toggleDropdown'
+
+ constructor: ->
+ super
+ @render()
+
+ # get active tab by name
+ if @name
+ name = @name
+
+ # get active tab last state
+ if !name && @sidebarState
+ name = @sidebarState.active
+
+ # get active tab by first tab
+ if !name
+ name = @tabs.first().data('tab')
+
+ # activate first tab
+ @toggleTabAction(name)
+
+ render: =>
+ itemsLocal = []
+ for item in @items
+ itemLocal = item.sidebarItem()
+ if itemLocal
+ itemsLocal.push itemLocal
+
+ # container
+ localEl = $(App.view('generic/sidebar_tabs')(
+ items: itemsLocal
+ scrollbarWidth: App.Utils.getScrollBarWidth()
+ dir: App.i18n.dir()
+ ))
+
+ # init sidebar badge
+ for item in itemsLocal
+ el = localEl.find('.tabsSidebar-tab[data-tab="' + item.name + '"]')
+ if item.badgeCallback
+ item.badgeCallback(el)
+ else
+ @badgeRender(el, item)
+
+ # init sidebar content
+ for item in itemsLocal
+ if item.sidebarCallback
+ el = localEl.filter('.sidebar[data-tab="' + item.name + '"]')
+ item.sidebarCallback(el.find('.sidebar-content'))
+ if !_.isEmpty(item.sidebarActions)
+ new ActionRow(
+ el: el.find('.js-actions')
+ items: item.sidebarActions
+ type: 'small'
+ )
+
+ @html localEl
+
+ badgeRender: (el, item) =>
+ @badgeEl = el
+ @badgeRenderLocal(item)
+
+ badgeRenderLocal: (item) =>
+ @badgeEl.html(App.view('generic/sidebar_tabs_item')(icon: item.badgeIcon))
+
+ toggleDropdown: (e) ->
+ e.stopPropagation()
+ $(e.currentTarget).next('.js-actions').find('.dropdown-toggle').dropdown('toggle')
+
+ toggleSidebar: =>
+ @el.parent().find('.tabsSidebar-sidebarSpacer').toggleClass('is-closed')
+ @el.parent().find('.tabsSidebar').toggleClass('is-closed')
+ #@el.parent().next('.attributeBar').toggleClass('is-closed')
+
+ showSidebar: ->
+ @el.parent().find('.tabsSidebar-sidebarSpacer').removeClass('is-closed')
+ @el.parent().find('.tabsSidebar').removeClass('is-closed')
+ #@el.parent().next('.attributeBar').addClass('is-closed')
+
+ toggleTab: (e) =>
+
+ # get selected tab
+ name = $(e.target).closest('.tabsSidebar-tab').data('tab')
+
+ if name
+
+ # if current tab is selected again, toggle side bar
+ if name is @currentTab
+ @toggleSidebar()
+
+ # toggle content tab
+ else
+ @toggleTabAction(name)
+
+ toggleTabAction: (name) ->
+ return if !name
+
+ # remember sidebarState for outsite
+ if @sidebarState
+ @sidebarState.active = name
+
+ # remove active state
+ @tabs.removeClass('active')
+
+ # add active state
+ @$('.tabsSidebar-tab[data-tab=' + name + ']').addClass('active')
+
+ # hide all content tabs
+ @sidebars.addClass('hide')
+
+ # show active tab content
+ tabContent = @$('.sidebar[data-tab=' + name + ']')
+ tabContent.removeClass('hide')
+
+ # remember current tab
+ @currentTab = name
+
+ # show sidebar if not shown
+ @showSidebar()
+
+class ActionRow extends App.Controller
+ constructor: ->
+ super
+ @render()
+
+ render: ->
+ @html App.view('generic/actions')(
+ items: @items
+ type: @type
+ )
+
+ for item in @items
+ do (item) =>
+ @$('[data-type="' + item.name + '"]').on(
+ 'click'
+ (e) ->
+ e.preventDefault()
+ item.callback()
+ )
diff --git a/app/assets/javascripts/app/controllers/widget/text_module.coffee b/app/assets/javascripts/app/controllers/widget/text_module.coffee
index a9e8df217..1ff860c67 100644
--- a/app/assets/javascripts/app/controllers/widget/text_module.coffee
+++ b/app/assets/javascripts/app/controllers/widget/text_module.coffee
@@ -19,7 +19,7 @@ class App.WidgetTextModule extends App.Controller
@subscribeId = App.TextModule.subscribe(@update, initFetch: true)
- @bind('TextModulePreconditionUpdate', (data) =>
+ @controllerBind('TextModulePreconditionUpdate', (data) =>
return if data.taskKey isnt @taskKey
@searchCondition = data.params
@update()
diff --git a/app/assets/javascripts/app/controllers/widget/ticket_stats.coffee b/app/assets/javascripts/app/controllers/widget/ticket_stats.coffee
index 3e6a3f44f..905363f2a 100644
--- a/app/assets/javascripts/app/controllers/widget/ticket_stats.coffee
+++ b/app/assets/javascripts/app/controllers/widget/ticket_stats.coffee
@@ -19,9 +19,10 @@ class App.TicketStats extends App.Controller
@subscribeIdOrganization = App.Organization.full(@organization.id, @load, false, true)
# rerender view, e.g. on language change
- @bind 'ui:rerender', =>
+ @controllerBind('ui:rerender', =>
return if !@authenticateCheck()
@render()
+ )
release: =>
if @subscribeIdUser
diff --git a/app/assets/javascripts/app/controllers/widget/update_taskbar.coffee b/app/assets/javascripts/app/controllers/widget/update_taskbar.coffee
new file mode 100644
index 000000000..3f419eb57
--- /dev/null
+++ b/app/assets/javascripts/app/controllers/widget/update_taskbar.coffee
@@ -0,0 +1,14 @@
+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)
\ No newline at end of file
diff --git a/app/assets/javascripts/app/index.coffee b/app/assets/javascripts/app/index.coffee
index 4901183c8..623df6842 100644
--- a/app/assets/javascripts/app/index.coffee
+++ b/app/assets/javascripts/app/index.coffee
@@ -5,6 +5,7 @@
#= require_tree ./lib/mixins
#= require ./config.coffee
#= require_tree ./models
+#= require_tree ./controllers/_application_controller
#= require_tree ./controllers
#= require_tree ./views
#= require_tree ./lib/app_post
diff --git a/app/assets/javascripts/app/lib/app_post/auth.coffee b/app/assets/javascripts/app/lib/app_post/auth.coffee
index 6ccc72ec0..8fd411422 100644
--- a/app/assets/javascripts/app/lib/app_post/auth.coffee
+++ b/app/assets/javascripts/app/lib/app_post/auth.coffee
@@ -98,9 +98,8 @@ class App.Auth
# rebuild navbar with new navbar items
App.Event.trigger('auth')
- App.Event.trigger('auth:logout')
+ App.Event.trigger('auth:failed')
App.Event.trigger('ui:rerender')
- App.TaskManager.tasksInitial()
return false
# clear local store
@@ -160,8 +159,10 @@ class App.Auth
if _.isFunction(model_object.clearInMemory)
model_object.clearInMemory()
+ App.Plugin.init()
App.Event.trigger('auth')
App.Event.trigger('auth:logout')
+
if rerender
@loginCheck(->
window.location.href = '#login'
@@ -177,6 +178,6 @@ class App.Auth
# rebuild navbar
App.Event.trigger('auth')
- App.Event.trigger('auth:logout')
+ App.Event.trigger('auth:failed')
App.Event.trigger('ui:rerender')
App.Event.trigger('clearStore')
diff --git a/app/assets/javascripts/app/lib/app_post/interface_handle.coffee b/app/assets/javascripts/app/lib/app_post/interface_handle.coffee
index 96b25142d..06d25d4d1 100644
--- a/app/assets/javascripts/app/lib/app_post/interface_handle.coffee
+++ b/app/assets/javascripts/app/lib/app_post/interface_handle.coffee
@@ -21,82 +21,16 @@ class App.Run extends App.Controller
# create web socket connection
App.WebSocket.connect()
+ # init plugins
+ App.Plugin.init(@el)
+
+ # init routes
+ App.Router.init(@el)
+
# start frontend time update
@frontendTimeUpdate()
- # start navbars
- @setupWidget('Navigations', 'nav', @el)
-
- # start widgets
- @setupWidget('Widgets', 'widget', @el)
-
# bind to fill selected text into
App.ClipBoard.bind(@el)
App.Event.trigger('app:ready')
-
- setupWidget: (config, event, el) ->
-
- # start widgets
- App.Event.trigger(event + ':init')
- widgets = App.Config.get(config)
- if widgets
- sortedKeys = Object.keys(widgets).sort()
- for key in sortedKeys
- widget = widgets[key]
- try
- new widget(
- el: el
- key: key
- )
- catch e
- @log 'error', "widget #{key}:", e
- App.Event.trigger(event + ':ready')
-
-class App.Content extends App.ControllerWidgetPermanent
- className: 'content flex horizontal'
-
- constructor: ->
- super
-
- Routes = @Config.get('Routes')
- for route, callback of Routes
- do (route, callback) =>
- @route(route, (params) ->
-
- @log 'debug', 'execute page controller', route, params
-
- # remove events for page
- App.Event.unbindLevel('page')
-
- # remove delay for page
- App.Delay.clearLevel('page')
-
- # remove interval for page
- App.Interval.clearLevel('page')
-
- # unbind in controller area
- @el.unbind()
- @el.undelegate()
-
- # remember history
- # needed to mute "redirect" url to support browser back
- history = App.Config.get('History')
- if history[10]
- history.shift()
-
- history.push '#' + params.match.input
-
- # execute controller
- controller = (params) =>
- params.el = @el
- try
- new callback(params)
- catch e
- @log 'error', "route #{route}:", e
- controller(params)
- )
-
- Spine.Route.setup()
-
-App.Config.set('content', App.Content, 'Widgets')
diff --git a/app/assets/javascripts/app/lib/app_post/plugin.coffee b/app/assets/javascripts/app/lib/app_post/plugin.coffee
new file mode 100644
index 000000000..9871d04a7
--- /dev/null
+++ b/app/assets/javascripts/app/lib/app_post/plugin.coffee
@@ -0,0 +1,49 @@
+class App.Plugin
+ _instance = undefined
+
+ @init: (el) ->
+ if _instance == undefined
+ _instance ?= new _pluginSingleton
+ _instance.init(el)
+
+class _pluginSingleton
+ backends: {}
+ el: undefined
+
+ constructor: ->
+
+ init: (el) =>
+ @appEl = el if el
+ @setupAll()
+
+ App.Event.bind('auth:login auth:logout', (user) =>
+ @setupAll()
+ )
+
+ setupAll: =>
+ @appEl.empty()
+ for key, backend of @backend
+ if backend.release
+ backend.release()
+ if backend.releaseController
+ backend.releaseController()
+ @backend = {}
+ @setup('Plugins', 'plugin')
+
+ setup: (config, event) ->
+
+ # start plugins
+ App.Event.trigger(event + ':init')
+ plugins = App.Config.get(config)
+ if plugins
+ sortedKeys = Object.keys(plugins).sort()
+ for key in sortedKeys
+ plugin = plugins[key]
+ try
+ @backend[key] = new plugin(
+ appEl: @appEl
+ key: key
+ )
+ catch e
+ App.Log.error "plugin #{key}:", e
+ App.Event.trigger(event + ':ready')
diff --git a/app/assets/javascripts/app/lib/app_post/router.coffee b/app/assets/javascripts/app/lib/app_post/router.coffee
new file mode 100644
index 000000000..9b64d1808
--- /dev/null
+++ b/app/assets/javascripts/app/lib/app_post/router.coffee
@@ -0,0 +1,30 @@
+class App.Router extends Spine.Controller
+ @init: (el) ->
+ new App.Router(el)
+
+ constructor: (el) ->
+ routes = App.Config.get('Routes')
+ for route, callback of routes
+ do (route, callback) =>
+ @route(route, (params) ->
+
+ App.Log.debug 'execute page controller', route, params
+
+ # remember history
+ # needed to mute "redirect" url to support browser back
+ history = App.Config.get('History')
+ if history[10]
+ history.shift()
+ history.push window.location.hash
+
+ # execute controller
+ controller = (params) ->
+ params.appEl = el
+ try
+ new callback(params)
+ catch e
+ App.Log.error "route #{route}:", e
+ controller(params)
+ )
+
+ Spine.Route.setup()
diff --git a/app/assets/javascripts/app/lib/app_post/task_manager.coffee b/app/assets/javascripts/app/lib/app_post/task_manager.coffee
index ad91110fd..aa6881808 100644
--- a/app/assets/javascripts/app/lib/app_post/task_manager.coffee
+++ b/app/assets/javascripts/app/lib/app_post/task_manager.coffee
@@ -8,6 +8,7 @@ class App.TaskManager
_instance ?= new _taskManagerSingleton(params)
@all: ->
+ return [] if !_instance
_instance.all()
@allWithMeta: ->
@@ -112,7 +113,7 @@ class _taskManagerSingleton extends App.Controller
@offlineModus = params.offlineModus
@tasksInitial()
- @bind('taskbar:preferences', (data) =>
+ @controllerBind('taskbar:preferences', (data) =>
@tasksPreferences[data.key] = data.preferences
@preferencesTrigger(data.key)
)
@@ -275,7 +276,7 @@ class _taskManagerSingleton extends App.Controller
# empty static content if task is shown
if params.show
- @$('#content').empty()
+ @$('#content').remove()
# set all tasks to active false, only new/selected one to active
if params.show
@@ -311,7 +312,7 @@ class _taskManagerSingleton extends App.Controller
el = $("
")
@domStore[domKey] = { el: el }
params_app['el'] = el
- params_app['task_key'] = params.key
+ params_app['appEl'] = @el
params_app['taskKey'] = params.key
if !params.show
params_app['doNotLog'] = 1
diff --git a/app/assets/javascripts/app/views/dashboard/stats/ticket_channel_distribution.jst.eco b/app/assets/javascripts/app/views/dashboard/stats/ticket_channel_distribution.jst.eco
index 92efdd2de..70d16d410 100644
--- a/app/assets/javascripts/app/views/dashboard/stats/ticket_channel_distribution.jst.eco
+++ b/app/assets/javascripts/app/views/dashboard/stats/ticket_channel_distribution.jst.eco
@@ -18,7 +18,8 @@