Merge branch 'develop' of github.com:martini/zammad into develop
This commit is contained in:
commit
ef621269f9
11 changed files with 168 additions and 40 deletions
|
@ -12,6 +12,10 @@ class App.ControllerForm extends App.Controller
|
||||||
# set empty class attributes if needed
|
# set empty class attributes if needed
|
||||||
if !@form
|
if !@form
|
||||||
@form = @formGen()
|
@form = @formGen()
|
||||||
|
|
||||||
|
# add alert placeholder
|
||||||
|
@form.prepend('<div class="alert alert--danger js-alert hide" role="alert"></div>')
|
||||||
|
|
||||||
if !@model
|
if !@model
|
||||||
@model = {}
|
@model = {}
|
||||||
if !@attributes
|
if !@attributes
|
||||||
|
@ -27,9 +31,18 @@ class App.ControllerForm extends App.Controller
|
||||||
@form.find('textarea').trigger('change')
|
@form.find('textarea').trigger('change')
|
||||||
@form.find('select').trigger('change')
|
@form.find('select').trigger('change')
|
||||||
|
|
||||||
|
# remove alert on input
|
||||||
|
@form.on('input', @hideAlert)
|
||||||
|
|
||||||
@finishForm = true
|
@finishForm = true
|
||||||
@form
|
@form
|
||||||
|
|
||||||
|
showAlert: (message) =>
|
||||||
|
@form.find('.alert').removeClass('hide').html( App.i18n.translateContent( message ) )
|
||||||
|
|
||||||
|
hideAlert: =>
|
||||||
|
@form.find('.alert').addClass('hide').html()
|
||||||
|
|
||||||
html: =>
|
html: =>
|
||||||
@form.html()
|
@form.html()
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,13 @@ class App.ControllerGenericNew extends App.ControllerModal
|
||||||
|
|
||||||
content: =>
|
content: =>
|
||||||
@head = @pageData.object
|
@head = @pageData.object
|
||||||
controller = new App.ControllerForm(
|
@controller = new App.ControllerForm(
|
||||||
model: App[ @genericObject ]
|
model: App[ @genericObject ]
|
||||||
params: @item
|
params: @item
|
||||||
screen: @screen || 'edit'
|
screen: @screen || 'edit'
|
||||||
autofocus: true
|
autofocus: true
|
||||||
)
|
)
|
||||||
controller.form
|
@controller.form
|
||||||
|
|
||||||
onSubmit: (e) ->
|
onSubmit: (e) ->
|
||||||
params = @formParam(e.target)
|
params = @formParam(e.target)
|
||||||
|
@ -39,9 +39,10 @@ class App.ControllerGenericNew extends App.ControllerModal
|
||||||
ui.callback(item)
|
ui.callback(item)
|
||||||
ui.close()
|
ui.close()
|
||||||
|
|
||||||
fail: ->
|
fail: (settings, details) ->
|
||||||
ui.log 'errors'
|
ui.log 'errors', details
|
||||||
ui.close()
|
ui.formEnable(e)
|
||||||
|
ui.controller.showAlert(details.error_human || details.error || 'Unable to create object!')
|
||||||
)
|
)
|
||||||
|
|
||||||
class App.ControllerGenericEdit extends App.ControllerModal
|
class App.ControllerGenericEdit extends App.ControllerModal
|
||||||
|
@ -54,13 +55,13 @@ class App.ControllerGenericEdit extends App.ControllerModal
|
||||||
@item = App[ @genericObject ].find( @id )
|
@item = App[ @genericObject ].find( @id )
|
||||||
@head = @pageData.object
|
@head = @pageData.object
|
||||||
|
|
||||||
controller = new App.ControllerForm(
|
@controller = new App.ControllerForm(
|
||||||
model: App[ @genericObject ]
|
model: App[ @genericObject ]
|
||||||
params: @item
|
params: @item
|
||||||
screen: @screen || 'edit'
|
screen: @screen || 'edit'
|
||||||
autofocus: true
|
autofocus: true
|
||||||
)
|
)
|
||||||
controller.form
|
@controller.form
|
||||||
|
|
||||||
onSubmit: (e) ->
|
onSubmit: (e) ->
|
||||||
params = @formParam(e.target)
|
params = @formParam(e.target)
|
||||||
|
@ -85,9 +86,10 @@ class App.ControllerGenericEdit extends App.ControllerModal
|
||||||
ui.callback(item)
|
ui.callback(item)
|
||||||
ui.close()
|
ui.close()
|
||||||
|
|
||||||
fail: ->
|
fail: (settings, details) ->
|
||||||
ui.log 'errors'
|
ui.log 'errors'
|
||||||
ui.close()
|
ui.formEnable(e)
|
||||||
|
ui.controller.showAlert(details.error_human || details.error || 'Unable to update object!')
|
||||||
)
|
)
|
||||||
|
|
||||||
class App.ControllerGenericIndex extends App.Controller
|
class App.ControllerGenericIndex extends App.Controller
|
||||||
|
@ -351,25 +353,44 @@ class App.ControllerNavSidbar extends App.ControllerContent
|
||||||
|
|
||||||
@params = params
|
@params = params
|
||||||
|
|
||||||
# get groups
|
# get accessable groups
|
||||||
|
roles = App.Session.get('roles')
|
||||||
groups = App.Config.get(@configKey)
|
groups = App.Config.get(@configKey)
|
||||||
groupsUnsorted = []
|
groupsUnsorted = []
|
||||||
for key, value of groups
|
for key, item of groups
|
||||||
if !value.controller
|
if !item.controller
|
||||||
groupsUnsorted.push value
|
if !item.role
|
||||||
|
groupsUnsorted.push item
|
||||||
|
else
|
||||||
|
match = _.include(item.role, 'Anybody')
|
||||||
|
if !match
|
||||||
|
for role in roles
|
||||||
|
if !match
|
||||||
|
match = _.include(item.role, role.name)
|
||||||
|
if match
|
||||||
|
groupsUnsorted.push item
|
||||||
|
|
||||||
@groupsSorted = _.sortBy( groupsUnsorted, (item) -> return item.prio )
|
@groupsSorted = _.sortBy(groupsUnsorted, (item) -> return item.prio)
|
||||||
|
|
||||||
# get items of group
|
# get items of group
|
||||||
for group in @groupsSorted
|
for group in @groupsSorted
|
||||||
items = App.Config.get(@configKey)
|
items = App.Config.get(@configKey)
|
||||||
itemsUnsorted = []
|
itemsUnsorted = []
|
||||||
for key, value of items
|
for key, item of items
|
||||||
if value.controller
|
if item.parent is group.target
|
||||||
if value.parent is group.target
|
if item.controller
|
||||||
itemsUnsorted.push value
|
if !item.role
|
||||||
|
itemsUnsorted.push item
|
||||||
|
else
|
||||||
|
match = _.include(item.role, 'Anybody')
|
||||||
|
if !match
|
||||||
|
for role in roles
|
||||||
|
if !match
|
||||||
|
match = _.include(item.role, role.name)
|
||||||
|
if match
|
||||||
|
itemsUnsorted.push item
|
||||||
|
|
||||||
group.items = _.sortBy( itemsUnsorted, (item) -> return item.prio )
|
group.items = _.sortBy(itemsUnsorted, (item) -> return item.prio)
|
||||||
|
|
||||||
# check last selected item
|
# check last selected item
|
||||||
selectedItem = undefined
|
selectedItem = undefined
|
||||||
|
|
|
@ -228,11 +228,11 @@ class Admin extends App.ControllerContent
|
||||||
)
|
)
|
||||||
@Config.set('system_init_done', true)
|
@Config.set('system_init_done', true)
|
||||||
|
|
||||||
fail: (data) =>
|
fail: (settings, details) =>
|
||||||
@formEnable(e)
|
@formEnable(e)
|
||||||
App.Event.trigger 'notify', {
|
App.Event.trigger 'notify', {
|
||||||
type: 'error'
|
type: 'error'
|
||||||
msg: App.i18n.translateContent( 'Can\'t create user!' )
|
msg: App.i18n.translateContent( details.error_human || 'Can\'t create user!' )
|
||||||
timeout: 2500
|
timeout: 2500
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -984,11 +984,11 @@ class Agent extends App.ControllerContent
|
||||||
# rerender page
|
# rerender page
|
||||||
@render()
|
@render()
|
||||||
|
|
||||||
fail: (data) =>
|
fail: (settings, details) =>
|
||||||
@formEnable(e)
|
@formEnable(e)
|
||||||
App.Event.trigger 'notify', {
|
App.Event.trigger 'notify', {
|
||||||
type: 'error'
|
type: 'error'
|
||||||
msg: App.i18n.translateContent( 'Can\'t create user!' )
|
msg: App.i18n.translateContent( details.error_human || 'Can\'t create user!' )
|
||||||
timeout: 2500
|
timeout: 2500
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -24,7 +24,7 @@ class Index extends App.ControllerContent
|
||||||
|
|
||||||
@html App.view('signup')()
|
@html App.view('signup')()
|
||||||
|
|
||||||
new App.ControllerForm(
|
@form = new App.ControllerForm(
|
||||||
el: @el.find('form')
|
el: @el.find('form')
|
||||||
model: App.User
|
model: App.User
|
||||||
screen: 'signup'
|
screen: 'signup'
|
||||||
|
@ -34,7 +34,7 @@ class Index extends App.ControllerContent
|
||||||
cancel: ->
|
cancel: ->
|
||||||
@navigate '#login'
|
@navigate '#login'
|
||||||
|
|
||||||
submit: (e) ->
|
submit: (e) =>
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
@formDisable(e)
|
@formDisable(e)
|
||||||
@params = @formParam(e.target)
|
@params = @formParam(e.target)
|
||||||
|
@ -67,6 +67,9 @@ class Index extends App.ControllerContent
|
||||||
success: @success
|
success: @success
|
||||||
error: @error
|
error: @error
|
||||||
)
|
)
|
||||||
|
fail: (settings, details) =>
|
||||||
|
@formEnable(e)
|
||||||
|
@form.showAlert(details.error_human || details.error || 'Unable to update object!')
|
||||||
)
|
)
|
||||||
|
|
||||||
success: (data, status, xhr) =>
|
success: (data, status, xhr) =>
|
||||||
|
|
|
@ -73,6 +73,7 @@ class _ajaxSingleton
|
||||||
# do not show any error message with code 401/404 (handled by controllers)
|
# do not show any error message with code 401/404 (handled by controllers)
|
||||||
return if status is 401
|
return if status is 401
|
||||||
return if status is 404
|
return if status is 404
|
||||||
|
return if status is 422
|
||||||
|
|
||||||
# do not show any error message with code 502
|
# do not show any error message with code 502
|
||||||
return if status is 502
|
return if status is 502
|
||||||
|
|
|
@ -166,7 +166,14 @@ class Collection extends Base
|
||||||
failResponse: (options) =>
|
failResponse: (options) =>
|
||||||
(xhr, statusText, error, settings) =>
|
(xhr, statusText, error, settings) =>
|
||||||
@model.trigger('ajaxError', null, xhr, statusText, error, settings)
|
@model.trigger('ajaxError', null, xhr, statusText, error, settings)
|
||||||
options.fail?.call(@model, settings)
|
# add errors to calllback
|
||||||
|
@record.trigger('ajaxError', @record, xhr, statusText, error, settings)
|
||||||
|
#options.fail?.call(@model, settings)
|
||||||
|
detailsRaw = xhr.responseText
|
||||||
|
if !_.isEmpty(detailsRaw)
|
||||||
|
details = JSON.parse(detailsRaw)
|
||||||
|
options.fail?.call(@record, settings, details)
|
||||||
|
# /add errors to calllback
|
||||||
|
|
||||||
class Singleton extends Base
|
class Singleton extends Base
|
||||||
constructor: (@record) ->
|
constructor: (@record) ->
|
||||||
|
@ -230,8 +237,15 @@ class Singleton extends Base
|
||||||
switch settings.type
|
switch settings.type
|
||||||
when 'POST' then @createFailed()
|
when 'POST' then @createFailed()
|
||||||
when 'DELETE' then @destroyFailed()
|
when 'DELETE' then @destroyFailed()
|
||||||
|
# add errors to calllback
|
||||||
@record.trigger('ajaxError', @record, xhr, statusText, error, settings)
|
@record.trigger('ajaxError', @record, xhr, statusText, error, settings)
|
||||||
options.fail?.call(@record, settings)
|
#options.fail?.call(@record, settings)
|
||||||
|
detailsRaw = xhr.responseText
|
||||||
|
if !_.isEmpty(detailsRaw)
|
||||||
|
details = JSON.parse(detailsRaw)
|
||||||
|
options.fail?.call(@record, settings, details)
|
||||||
|
@record.trigger('remove', @record)
|
||||||
|
# /add errors to calllback
|
||||||
|
|
||||||
createFailed: ->
|
createFailed: ->
|
||||||
@record.remove(clear: true)
|
@record.remove(clear: true)
|
||||||
|
|
|
@ -307,7 +307,7 @@ class App.Model extends Spine.Model
|
||||||
|
|
||||||
# subscribe and render data / fetch new data if triggered
|
# subscribe and render data / fetch new data if triggered
|
||||||
@bind(
|
@bind(
|
||||||
'refresh change'
|
'refresh change remove'
|
||||||
(items) =>
|
(items) =>
|
||||||
App.Log.debug('Model', "local collection refresh/change #{@className}", items)
|
App.Log.debug('Model', "local collection refresh/change #{@className}", items)
|
||||||
for key, callback of @SUBSCRIPTION_COLLECTION
|
for key, callback of @SUBSCRIPTION_COLLECTION
|
||||||
|
@ -376,6 +376,19 @@ class App.Model extends Spine.Model
|
||||||
item = App[ @className ]._fillUp( item )
|
item = App[ @className ]._fillUp( item )
|
||||||
callback(item, 'change')
|
callback(item, 'change')
|
||||||
)
|
)
|
||||||
|
@bind(
|
||||||
|
'remove'
|
||||||
|
(items) =>
|
||||||
|
|
||||||
|
# check if result is array or singel item
|
||||||
|
if !_.isArray(items)
|
||||||
|
items = [items]
|
||||||
|
App.Log.debug('Model', "local remove #{@className}", items)
|
||||||
|
for item in items
|
||||||
|
for key, callback of App[ @className ].SUBSCRIPTION_ITEM[ item.id ]
|
||||||
|
item = App[ @className ]._fillUp( item )
|
||||||
|
callback(item, 'remove')
|
||||||
|
)
|
||||||
|
|
||||||
@changeTable = {}
|
@changeTable = {}
|
||||||
@bind(
|
@bind(
|
||||||
|
|
|
@ -313,7 +313,7 @@ class ApplicationController < ActionController::Base
|
||||||
rescue => e
|
rescue => e
|
||||||
logger.error e.message
|
logger.error e.message
|
||||||
logger.error e.backtrace.inspect
|
logger.error e.backtrace.inspect
|
||||||
render json: { error: e.message }, status: :unprocessable_entity
|
render json: model_match_error(e.message), status: :unprocessable_entity
|
||||||
end
|
end
|
||||||
|
|
||||||
def model_create_render_item (generic_object)
|
def model_create_render_item (generic_object)
|
||||||
|
@ -335,7 +335,7 @@ class ApplicationController < ActionController::Base
|
||||||
rescue => e
|
rescue => e
|
||||||
logger.error e.message
|
logger.error e.message
|
||||||
logger.error e.backtrace.inspect
|
logger.error e.backtrace.inspect
|
||||||
render json: { error: e.message }, status: :unprocessable_entity
|
render json: model_match_error(e.message), status: :unprocessable_entity
|
||||||
end
|
end
|
||||||
|
|
||||||
def model_update_render_item (generic_object)
|
def model_update_render_item (generic_object)
|
||||||
|
@ -349,7 +349,7 @@ class ApplicationController < ActionController::Base
|
||||||
rescue => e
|
rescue => e
|
||||||
logger.error e.message
|
logger.error e.message
|
||||||
logger.error e.backtrace.inspect
|
logger.error e.backtrace.inspect
|
||||||
render json: { error: e.message }, status: :unprocessable_entity
|
render json: model_match_error(e.message), status: :unprocessable_entity
|
||||||
end
|
end
|
||||||
|
|
||||||
def model_destory_render_item ()
|
def model_destory_render_item ()
|
||||||
|
@ -369,7 +369,7 @@ class ApplicationController < ActionController::Base
|
||||||
rescue => e
|
rescue => e
|
||||||
logger.error e.message
|
logger.error e.message
|
||||||
logger.error e.backtrace.inspect
|
logger.error e.backtrace.inspect
|
||||||
render json: { error: e.message }, status: :unprocessable_entity
|
render json: model_match_error(e.message), status: :unprocessable_entity
|
||||||
end
|
end
|
||||||
|
|
||||||
def model_show_render_item (generic_object)
|
def model_show_render_item (generic_object)
|
||||||
|
@ -382,11 +382,20 @@ class ApplicationController < ActionController::Base
|
||||||
rescue => e
|
rescue => e
|
||||||
logger.error e.message
|
logger.error e.message
|
||||||
logger.error e.backtrace.inspect
|
logger.error e.backtrace.inspect
|
||||||
render json: { error: e.message }, status: :unprocessable_entity
|
render json: model_match_error(e.message), status: :unprocessable_entity
|
||||||
end
|
end
|
||||||
|
|
||||||
def model_index_render_result (generic_objects)
|
def model_index_render_result (generic_objects)
|
||||||
render json: generic_objects, status: :ok
|
render json: generic_objects, status: :ok
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def model_match_error (error)
|
||||||
|
data = {
|
||||||
|
error: error
|
||||||
|
}
|
||||||
|
if error =~ /(already exists|duplicate key)/i
|
||||||
|
data[:error_human] = 'Object already exists!'
|
||||||
|
end
|
||||||
|
data
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -77,7 +77,7 @@ class UsersController < ApplicationController
|
||||||
|
|
||||||
# check if feature is enabled
|
# check if feature is enabled
|
||||||
if !Setting.get('user_create_account')
|
if !Setting.get('user_create_account')
|
||||||
render json: { error: 'Feature not enabled!' }, status: :unprocessable_entity
|
render json: { error_human: 'Feature not enabled!' }, status: :unprocessable_entity
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ class UsersController < ApplicationController
|
||||||
if user.email
|
if user.email
|
||||||
exists = User.where(email: user.email.downcase).first
|
exists = User.where(email: user.email.downcase).first
|
||||||
if exists
|
if exists
|
||||||
render json: { error: 'User already exists!' }, status: :unprocessable_entity
|
render json: { error_human: 'User already exists!' }, status: :unprocessable_entity
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -180,7 +180,7 @@ class UsersController < ApplicationController
|
||||||
user_new = User.find(user.id)
|
user_new = User.find(user.id)
|
||||||
render json: user_new, status: :created
|
render json: user_new, status: :created
|
||||||
rescue => e
|
rescue => e
|
||||||
render json: { error: e.message }, status: :unprocessable_entity
|
render json: model_match_error(e.message), status: :unprocessable_entity
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,60 @@
|
||||||
require 'browser_test_helper'
|
require 'browser_test_helper'
|
||||||
|
|
||||||
class PreferencesTest < TestCase
|
class PreferencesTest < TestCase
|
||||||
|
def test_permission_agent
|
||||||
|
@browser = browser_instance
|
||||||
|
login(
|
||||||
|
username: 'master@example.com',
|
||||||
|
password: 'test',
|
||||||
|
url: browser_url,
|
||||||
|
)
|
||||||
|
click( css: 'a[href="#current_user"]' )
|
||||||
|
click( css: 'a[href="#profile"]' )
|
||||||
|
match(
|
||||||
|
css: '.content .NavBarProfile',
|
||||||
|
value: 'Password',
|
||||||
|
)
|
||||||
|
match(
|
||||||
|
css: '.content .NavBarProfile',
|
||||||
|
value: 'Language',
|
||||||
|
)
|
||||||
|
match(
|
||||||
|
css: '.content .NavBarProfile',
|
||||||
|
value: 'Notifications',
|
||||||
|
)
|
||||||
|
match(
|
||||||
|
css: '.content .NavBarProfile',
|
||||||
|
value: 'Calendar',
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_permission_customer
|
||||||
|
@browser = browser_instance
|
||||||
|
login(
|
||||||
|
username: 'nicole.braun@zammad.org',
|
||||||
|
password: 'test',
|
||||||
|
url: browser_url,
|
||||||
|
)
|
||||||
|
click( css: 'a[href="#current_user"]' )
|
||||||
|
click( css: 'a[href="#profile"]' )
|
||||||
|
match(
|
||||||
|
css: '.content .NavBarProfile',
|
||||||
|
value: 'Password',
|
||||||
|
)
|
||||||
|
match(
|
||||||
|
css: '.content .NavBarProfile',
|
||||||
|
value: 'Language',
|
||||||
|
)
|
||||||
|
match_not(
|
||||||
|
css: '.content .NavBarProfile',
|
||||||
|
value: 'Notifications',
|
||||||
|
)
|
||||||
|
match_not(
|
||||||
|
css: '.content .NavBarProfile',
|
||||||
|
value: 'Calendar',
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
def test_preferences
|
def test_preferences
|
||||||
@browser = browser_instance
|
@browser = browser_instance
|
||||||
login(
|
login(
|
||||||
|
|
|
@ -80,8 +80,8 @@ class UserOrganizationControllerTest < ActionDispatch::IntegrationTest
|
||||||
post '/api/v1/users', {}, @headers
|
post '/api/v1/users', {}, @headers
|
||||||
assert_response(422)
|
assert_response(422)
|
||||||
result = JSON.parse(@response.body)
|
result = JSON.parse(@response.body)
|
||||||
assert(result['error'])
|
assert(result['error_human'])
|
||||||
assert_equal('Feature not enabled!', result['error'])
|
assert_equal('Feature not enabled!', result['error_human'])
|
||||||
|
|
||||||
# already existing user with enabled feature
|
# already existing user with enabled feature
|
||||||
Setting.set('user_create_account', true)
|
Setting.set('user_create_account', true)
|
||||||
|
@ -89,8 +89,8 @@ class UserOrganizationControllerTest < ActionDispatch::IntegrationTest
|
||||||
post '/api/v1/users', params.to_json, @headers
|
post '/api/v1/users', params.to_json, @headers
|
||||||
assert_response(422)
|
assert_response(422)
|
||||||
result = JSON.parse(@response.body)
|
result = JSON.parse(@response.body)
|
||||||
assert(result['error'])
|
assert(result['error_human'])
|
||||||
assert_equal('User already exists!', result['error'])
|
assert_equal('User already exists!', result['error_human'])
|
||||||
|
|
||||||
# create user with enabled feature
|
# create user with enabled feature
|
||||||
params = { firstname: 'Me First', lastname: 'Me Last', email: 'new_here@example.com' }
|
params = { firstname: 'Me First', lastname: 'Me Last', email: 'new_here@example.com' }
|
||||||
|
|
Loading…
Reference in a new issue