From: Moritz Bunkus Date: Thu, 7 Mar 2013 11:17:06 +0000 (+0100) Subject: Error-Handling: Bei AJAX-Requests Fehler als JSON-Object zurückgeben X-Git-Tag: release-3.1.0beta1~550 X-Git-Url: http://wagnertech.de/git?a=commitdiff_plain;h=b9740e8a9a77eafcaf7aacd530af23fa8dbcb9f9;p=kivitendo-erp.git Error-Handling: Bei AJAX-Requests Fehler als JSON-Object zurückgeben --- diff --git a/SL/ClientJS.pm b/SL/ClientJS.pm index 99598afc6..6a458be1a 100644 --- a/SL/ClientJS.pm +++ b/SL/ClientJS.pm @@ -9,10 +9,13 @@ use SL::JSON (); use Rose::Object::MakeMethods::Generic ( - 'scalar --get_set_init' => [ qw(_actions) ], + 'scalar --get_set_init' => [ qw(_actions _flash _error) ], ); my %supported_methods = ( + # ## Non-jQuery methods ## + flash => 2, # display_flash(, ) + # ## jQuery basics ## # Basic effects @@ -123,8 +126,18 @@ sub init__actions { return []; } +sub init__flash { + return {}; +} + +sub init__error { + return ''; +} + sub to_json { my ($self) = @_; + + return SL::JSON::to_json({ error => $self->_error }) if $self->_error; return SL::JSON::to_json({ eval_actions => $self->_actions }); } @@ -144,6 +157,29 @@ sub jstree { return $self; } +sub flash { + my ($self, $type, @messages) = @_; + + my $message = join ' ', grep { $_ } @messages; + + if (!$self->_flash->{$type}) { + $self->_flash->{$type} = [ 'flash', $type, $message ]; + push @{ $self->_actions }, $self->_flash->{$type}; + } else { + $self->_flash->{$type}->[-1] .= ' ' . $message; + } + + return $self; +} + +sub error { + my ($self, @messages) = @_; + + $self->_error(join ' ', grep { $_ } ($self->_error, @messages)); + + return $self; +} + 1; __END__ @@ -301,6 +337,29 @@ Instead of: The first variation is obviously better suited for chaining. +Additional functions: + +=over 4 + +=item C + +Display a C<$message> in the flash of type C<$type>. Multiple calls of +C on the same C<$self> will be merged by type. + +On the client side the flash of this type will be cleared before the +message is shown. + +=item C + +Causes L (and therefore L) to output a JSON object +that only contains an C field set to this C<$message>. The +client will then show the message in the 'error' flash. + +The messages of multiple calls of C on the same C<$self> will +be merged. + +=back + =head2 JQUERY FUNCTIONS The following jQuery functions are supported: diff --git a/SL/Dispatcher.pm b/SL/Dispatcher.pm index 5282369fd..828dc1f1a 100644 --- a/SL/Dispatcher.pm +++ b/SL/Dispatcher.pm @@ -30,6 +30,7 @@ use SL::Dispatcher::AuthHandler; use SL::LXDebug; use SL::LxOfficeConf; use SL::Locale; +use SL::ClientJS; use SL::Common; use SL::Form; use SL::Helper::DateTime; @@ -74,6 +75,14 @@ sub pre_request_checks { } } +sub render_error_ajax { + my ($error) = @_; + + SL::ClientJS->new + ->error($error) + ->render(SL::Controller::Base->new); +} + sub show_error { $::lxdebug->enter_sub; my $template = shift; @@ -85,6 +94,8 @@ sub show_error { $::form->{error} = $::locale->text('The session is invalid or has expired.') if ($error_type eq 'session'); $::form->{error} = $::locale->text('Incorrect password!') if ($error_type eq 'password'); + return render_error_ajax($::form->{error}) if $::request->is_ajax; + $::form->header; print $::form->parse_html_template($template, \%params); $::lxdebug->leave_sub; @@ -272,10 +283,16 @@ sub handle_request { 1; } or do { if ($EVAL_ERROR ne END_OF_REQUEST) { - print STDERR $EVAL_ERROR; - $::form->{label_error} = $::request->{cgi}->pre($EVAL_ERROR); - chdir SL::System::Process::exe_dir; - eval { show_error('generic/error') }; + my $error = $EVAL_ERROR; + print STDERR $error; + + if ($::request->is_ajax) { + eval { render_error_ajax($error) }; + } else { + $::form->{label_error} = $::request->{cgi}->pre($error); + chdir SL::System::Process::exe_dir; + eval { show_error('generic/error') }; + } } }; diff --git a/SL/Form.pm b/SL/Form.pm index 3c809b302..d130272dd 100644 --- a/SL/Form.pm +++ b/SL/Form.pm @@ -704,6 +704,14 @@ sub show_generic_error { return; } + if ($::request->is_ajax) { + $::lxdebug->message(0, "trying to render AJAX response..."); + SL::ClientJS->new + ->error($error) + ->render(SL::Controller::Base->new); + ::end_of_request(); + } + my $add_params = { 'title_error' => $params{title}, 'label_error' => $error, diff --git a/js/client_js.js b/js/client_js.js index 08b9b7248..fa116dda4 100644 --- a/js/client_js.js +++ b/js/client_js.js @@ -4,10 +4,21 @@ // "scripts/generate_client_js_actions.pl". See the documentation for // SL/ClientJS.pm for instructions. +function display_flash(type, message) { + $('#flash_' + type + '_content').text(message); + $('#flash_' + type).show(); +} + function eval_json_result(data) { if (!data) return; + if (data.error) + return display_flash('error', data.error); + + $('#flash_error').hide(); + $('#flash_error_content').empty(); + if ((data.js || '') != '') eval(data.js); @@ -15,9 +26,13 @@ function eval_json_result(data) { $(data.eval_actions).each(function(idx, action) { // console.log("ACTION " + action[0] + " ON " + action[1]); + // ## Non-jQuery methods ## + if (action[0] == 'flash') display_flash(action[1], action[2]); + // ## jQuery basics ## + // Basic effects - if (action[0] == 'hide') $(action[1]).hide(); + else if (action[0] == 'hide') $(action[1]).hide(); else if (action[0] == 'show') $(action[1]).show(); else if (action[0] == 'toggle') $(action[1]).toggle(); @@ -94,3 +109,7 @@ function eval_json_result(data) { // console.log("current_content_type " + $('#current_content_type').val() + ' ID ' + $('#current_content_id').val()); } + +// Local Variables: +// mode: js +// End: diff --git a/scripts/generate_client_js_actions.tpl b/scripts/generate_client_js_actions.tpl index 6572e22c3..7fa7baf95 100644 --- a/scripts/generate_client_js_actions.tpl +++ b/scripts/generate_client_js_actions.tpl @@ -4,10 +4,21 @@ // "scripts/generate_client_js_actions.pl". See the documentation for // SL/ClientJS.pm for instructions. +function display_flash(type, message) { + $('#flash_' + type + '_content').text(message); + $('#flash_' + type).show(); +} + function eval_json_result(data) { if (!data) return; + if (data.error) + return display_flash('error', data.error); + + $('#flash_error').hide(); + $('#flash_error_content').empty(); + if ((data.js || '') != '') eval(data.js); @@ -20,3 +31,7 @@ function eval_json_result(data) { // console.log("current_content_type " + $('#current_content_type').val() + ' ID ' + $('#current_content_id').val()); } + +// Local Variables: +// mode: js +// End: