Merge branch 'develop' of github.com:martini/zammad into develop

This commit is contained in:
Felix Niklas 2016-02-17 09:22:11 +01:00
commit ef621269f9
11 changed files with 168 additions and 40 deletions

View file

@ -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()

View file

@ -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

View file

@ -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
} }
) )

View file

@ -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) =>

View file

@ -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

View file

@ -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)

View file

@ -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(

View file

@ -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

View file

@ -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

View file

@ -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(

View file

@ -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' }