[Jifty-commit] r3405 - in jifty/trunk: . lib/Jifty lib/Jifty/Plugin lib/Jifty/Plugin/SinglePage lib/Jifty/Web share/web/static/js share/web/templates/__jifty/webservices

jifty-commit at lists.jifty.org jifty-commit at lists.jifty.org
Fri Jun 8 16:46:17 EDT 2007


Author: clkao
Date: Fri Jun  8 16:46:17 2007
New Revision: 3405

Added:
   jifty/trunk/lib/Jifty/Plugin/SinglePage/
   jifty/trunk/lib/Jifty/Plugin/SinglePage/Dispatcher.pm
Modified:
   jifty/trunk/   (props changed)
   jifty/trunk/lib/Jifty/Continuation.pm
   jifty/trunk/lib/Jifty/Dispatcher.pm
   jifty/trunk/lib/Jifty/Plugin/SinglePage.pm
   jifty/trunk/lib/Jifty/Request.pm
   jifty/trunk/lib/Jifty/Web.pm
   jifty/trunk/lib/Jifty/Web/Form.pm
   jifty/trunk/lib/Jifty/Web/Form/Clickable.pm
   jifty/trunk/lib/Jifty/Web/Form/Element.pm
   jifty/trunk/lib/Jifty/Web/PageRegion.pm
   jifty/trunk/share/web/static/js/jifty.js
   jifty/trunk/share/web/templates/__jifty/webservices/xml

Log:
Merge from fragcont branch to include minimum support of continuation in
webservices requests to make SinglePage work.

 r18076 at ubuntu (orig r3386):  clkao | 2007-06-07 15:59:34 -0400
 branch for supporting fragment calls with continuation.
 r18077 at ubuntu (orig r3387):  clkao | 2007-06-07 16:05:17 -0400
 first cut of continuation serialization & calling with webservices.
 r18078 at ubuntu (orig r3388):  clkao | 2007-06-07 17:35:03 -0400
 Have call continuation work on webservices, but not return properly yet.
 r18080 at ubuntu (orig r3390):  clkao | 2007-06-07 18:11:09 -0400
 keeping __page's state won't get us anywhere...
 r18093 at ubuntu (orig r3392):  clkao | 2007-06-07 19:19:35 -0400
 ditto for other implicit __page fragment to ignore region state.
 r18094 at ubuntu (orig r3393):  clkao | 2007-06-07 19:20:11 -0400
 fallback value being array makes the crud action on server side sad.
 r18110 at ubuntu (orig r3397):  clkao | 2007-06-08 02:43:23 -0400
 Support redirect to external url in webservices.
 r18111 at ubuntu (orig r3398):  clkao | 2007-06-08 03:01:27 -0400
 Prevent infinite loop when unable to render mason_internal_error.
 
 r18112 at ubuntu (orig r3399):  clkao | 2007-06-08 03:15:31 -0400
 Handle J:C internal redirect, which is used by error raised by dispatcher.
 r18118 at ubuntu (orig r3401):  clkao | 2007-06-08 13:00:58 -0400
 * If we are doing external redirect, supress fragment replacement.
 * fix refresh_self in submit so on failed action response we get
   __page refreshed that is like page reload.
 
 r18119 at ubuntu (orig r3402):  clkao | 2007-06-08 13:13:54 -0400
 On internal redirect, reset nav and page_nav.
 r18120 at ubuntu (orig r3403):  clkao | 2007-06-08 15:42:44 -0400
 There's no point removing url in clickable and put in _orig_url anymore,
 which also happens to break redirect($clickable).
 
 r18125 at ubuntu (orig r3404):  clkao | 2007-06-08 16:42:32 -0400
 misc cleanups.


Modified: jifty/trunk/lib/Jifty/Continuation.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Continuation.pm	(original)
+++ jifty/trunk/lib/Jifty/Continuation.pm	Fri Jun  8 16:46:17 2007
@@ -156,6 +156,18 @@
 sub call {
     my $self = shift;
 
+    Jifty->log->debug("Redirect to @{[$self->request->path]} via continuation");
+    if (Jifty->web->request->argument('_webservice_redirect')) {
+	# for continuation - perform internal redirect under webservices.
+	Jifty->web->request->remove_state_variable('region-__page');
+	Jifty->web->request->add_fragment(
+            name      => '__page',
+            path      => $self->request->path,
+            arguments => {},
+            wrapper   => 0
+        );
+	return;
+    }
     # If we needed to fix up the path (it contains invalid
     # characters) then warn, because this may cause infinite
     # redirects
@@ -189,6 +201,7 @@
 
     # Redirect to right page if we're not there already
     Jifty->web->_redirect($next->request->path . "?J:RETURN=" . $next->id);
+    return 1;
 }
 
 =head2 return

Modified: jifty/trunk/lib/Jifty/Dispatcher.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Dispatcher.pm	(original)
+++ jifty/trunk/lib/Jifty/Dispatcher.pm	Fri Jun  8 16:46:17 2007
@@ -736,7 +736,7 @@
     $self->_abort;
 }
 
-sub _abort { die "ABORT" }
+sub _abort { Carp::croak "ABORT" }
 
 =head2 _do_show [PATH]
 
@@ -1149,6 +1149,7 @@
     my $self     = shift;
     my $template = shift;
     my $showed   = 0;
+#    local $@;
     eval {
         foreach my $handler ( Jifty->handler->view_handlers ) {
             if ( Jifty->handler->view($handler)->template_exists($template) ) {
@@ -1166,8 +1167,13 @@
     my $err = $@;
 
     # Handle parse errors
+    $self->log->fatal("view class error: $err") if $err;
     if ( $err and not eval { $err->isa('HTML::Mason::Exception::Abort') } ) {
-
+        if ($template eq '/__jifty/error/mason_internal_error') {
+            $self->log->debug("can't render internal_error: $err");
+            $self->_abort;
+            return;
+        }
         # Save the request away, and redirect to an error page
         Jifty->web->response->error($err);
         my $c = Jifty::Continuation->new(
@@ -1176,8 +1182,6 @@
             parent   => Jifty->web->request->continuation,
         );
 
-        warn "$err";
-
         # Redirect with a continuation
         Jifty->web->_redirect( "/__jifty/error/mason_internal_error?J:C=" . $c->id );
     } elsif ($err) {

Modified: jifty/trunk/lib/Jifty/Plugin/SinglePage.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Plugin/SinglePage.pm	(original)
+++ jifty/trunk/lib/Jifty/Plugin/SinglePage.pm	Fri Jun  8 16:46:17 2007
@@ -13,34 +13,42 @@
     $self->region_name($opt{region_name} || '__page');
 }
 
+sub _push_onclick {
+    my $self = shift;
+    my $args = shift;
+    $args->{onclick} = [ $args->{onclick} ] unless ref $args->{onclick} eq 'ARRAY';
+    push @{$args->{onclick}}, @_ if @_;
+}
+
 sub _sp_link {
     my $self = shift;
     return sub {
         my ( $clickable, $args ) = @_;
         my $url = $args->{'url'};
-        if ( $url && $url !~ m/^#/ ) {
-            delete $args->{'url'};
+        if ( $url && $url !~ m/^#/ && $url !~ m{^https?://} ) {
             # XXX mind the existing onclick
-            warn 'ooops got original onclick' . Dumper( $args->{onclick} )
-                if $args->{onclick};
-            $args->{onclick} = {
+            $self->_push_onclick($args, {
                 region       => $self->region_name,
                 replace_with => $url,
-                args         => delete $args->{parameters}
-            };
+                args         => delete $args->{parameters}});
         }
-	elsif (exists $args->{submit}) {
-	    $args->{onclick} = { submit => delete $args->{submit} };
-	    $args->{refresh_self} = 1;
+        elsif (exists $args->{submit}) {
+	    $self->_push_onclick($args, { refresh_self => 1, submit => delete $args->{submit} });
 	    $args->{as_button} = 1;
 	}
+        if (my $form = delete $args->{_form}) {
+	    $args->{call} = $form->call;
+	}
         my $onclick = $args->{onclick};
-        if ( ref($onclick) eq 'HASH' ) {
-            if ( $onclick->{region} && !ref( $onclick->{region} ) ) {
-		my $region = $self->region_name;
-                $onclick->{region}
-                    = $region . '-' . $onclick->{region}
-                    unless $onclick->{region} eq $region or $onclick->{region} =~ m/^\Q$region\E-/;
+        if ( $args->{onclick} ) {
+            $self->_push_onclick($args);    # make sure it's array
+            for my $onclick ( @{ $args->{onclick} } ) {
+                if ( $onclick->{region} && !ref( $onclick->{region} ) ) {
+                    my $region = $self->region_name;
+                    $onclick->{region} = $region . '-' . $onclick->{region}
+                        unless $onclick->{region} eq $region
+                        or $onclick->{region} =~ m/^\Q$region\E-/;
+                }
             }
         }
     }

Added: jifty/trunk/lib/Jifty/Plugin/SinglePage/Dispatcher.pm
==============================================================================
--- (empty file)
+++ jifty/trunk/lib/Jifty/Plugin/SinglePage/Dispatcher.pm	Fri Jun  8 16:46:17 2007
@@ -0,0 +1,36 @@
+package Jifty::Plugin::SinglePage::Dispatcher;
+use strict;
+use warnings;
+use Jifty::Dispatcher -base;
+
+before '__jifty/webservices/*' => run {
+    my (@actions) = grep { $_->class eq 'Jifty::Action::Redirect' } values %{ Jifty->web->request->{'actions'} };
+    $_->active(0) for @actions;
+
+    # XXX: shouldn't have multiple redirect
+    # Simply ignore Redirect from webservice if we are not in SPA
+    set '_webservice_redirect' => [map { $_->arguments->{url} } @actions]
+        if Jifty->find_plugin('Jifty::Plugin::SinglePage');
+
+};
+
+on qr{(__jifty/webservices/.*)} => run {
+    my $actions = get '_webservice_redirect';
+    Jifty->web->request->remove_state_variable('region-__page');
+    for my $act (@$actions) {
+	if ($act =~ m{^https?://}) {
+	    set '_webservice_external_redirect' => $act;
+	}
+	else {
+	    Jifty->web->request->add_fragment(
+                name      => '__page',
+                path      => $act,
+                arguments => {},
+                wrapper   => 0
+            );
+	}
+    }
+    show $1;
+};
+
+1;

Modified: jifty/trunk/lib/Jifty/Request.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Request.pm	(original)
+++ jifty/trunk/lib/Jifty/Request.pm	Fri Jun  8 16:46:17 2007
@@ -530,8 +530,7 @@
     return if $self->is_subrequest;
     return unless $self->continuation_type and $self->continuation_type eq "call" and $self->continuation;
     $self->log->debug("Calling continuation ".$self->continuation->id);
-    $self->continuation->call;
-    return 1;
+    return $self->continuation->call;
 }
 
 =head2 return_from_continuation

Modified: jifty/trunk/lib/Jifty/Web.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Web.pm	(original)
+++ jifty/trunk/lib/Jifty/Web.pm	Fri Jun  8 16:46:17 2007
@@ -329,6 +329,17 @@
 
         push @valid_actions, $request_action;
     }
+    if ($self->request->continuation_path && Jifty->web->request->argument('_webservice_redirect')) {
+	# for continuation - perform internal redirect under webservices
+	Jifty->web->request->remove_state_variable('region-__page');
+	Jifty->web->request->add_fragment(
+            name      => '__page',
+            path      => $self->request->continuation_path,
+            arguments => {},
+            wrapper   => 0
+        );
+	return;
+    }
     $self->request->save_continuation;
 
     unless ( $self->request->just_validating ) {
@@ -606,7 +617,7 @@
 redirects to that URL rather than B<next_page>.
 
 It creates a continuation of where you want to be, and then calls it.
-If you want to redirect to a parge with parameters, pass in a
+If you want to redirect to a page with parameters, pass in a
 L<Jifty::Web::Form::Clickable> object.
 
 =cut
@@ -636,8 +647,7 @@
 
     # To submit a Jifty::Action::Redirect, we don't need to serialize a continuation,
     # unlike any other kind of actions.
-    
-    
+
     my $redirect_to_url = '' ;
 
     if (  (grep { not $_->action_class->isa('Jifty::Action::Redirect') }
@@ -687,21 +697,23 @@
     my $self = shift;
     my ($page) = @_;
 
-
-
     # It's an experimental feature to support redirect within a
-    # region.  It's currently enabled only for SPA.  We should make
-    # sure we understand what existing code is call this kind of replace.
-    my ($spa) = Jifty->find_plugin('Jifty::Plugin::SinglePage');
-
-    if ($spa && $self->current_region) { 
+    # region.
+    if ($self->current_region) { 
         # If we're within a region stack, we don't really want to
-        # redirect. We want to redispatch.
+        # redirect. We want to redispatch.  Also reset the things
+        # applied on beofre.
+        local $self->{navigation} = undef;
+        local $self->{page_navigation} = undef;
         $self->replace_current_region($page);
         Jifty::Dispatcher::_abort;
         return;
     }
 
+    if (my $redir = Jifty->web->request->argument('_webservice_redirect')) {
+	push @$redir, $page;
+	return;
+    }
     # $page can't lead with // or it assumes it's a URI scheme.
     $page =~ s{^/+}{/};
 

Modified: jifty/trunk/lib/Jifty/Web/Form.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Web/Form.pm	(original)
+++ jifty/trunk/lib/Jifty/Web/Form.pm	Fri Jun  8 16:46:17 2007
@@ -217,8 +217,7 @@
 
 sub submit {
     my $self = shift;
-
-    my $button = Jifty::Web::Form::Clickable->new(submit => undef, @_)->generate;
+    my $button = Jifty::Web::Form::Clickable->new(submit => undef, _form => $self, @_)->generate;
     Jifty->web->out(qq{<div class="submit_button">});
     $button->render_widget;
     Jifty->web->out(qq{</div>});

Modified: jifty/trunk/lib/Jifty/Web/Form/Clickable.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Web/Form/Clickable.pm	(original)
+++ jifty/trunk/lib/Jifty/Web/Form/Clickable.pm	Fri Jun  8 16:46:17 2007
@@ -455,11 +455,25 @@
           escape_label => $self->escape_label,
           url          => $self->complete_url,
           target       => $self->target,
+          continuation => $self->_continuation,
           @_ }
     );
     return $link;
 }
 
+sub _continuation {
+    # continuation info used by the update() call on client side
+    my $self = shift;
+    if ($self->call) {
+	return { 'type' => 'call', id => $self->call };
+    }
+    if ($self->returns) {
+	return { 'create' => $self->url };
+    }
+
+    return {};
+}
+
 =head2 as_button
 
 Returns the clickable as a L<Jifty::Web::Form::Field::InlineButton>,
@@ -476,6 +490,7 @@
     my $field = Jifty::Web::Form::Field->new(
         { %$args,
           type => 'InlineButton',
+          continuation => $self->_continuation,
           @_ }
     );
     my %parameters = $self->post_parameters;

Modified: jifty/trunk/lib/Jifty/Web/Form/Element.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Web/Form/Element.pm	(original)
+++ jifty/trunk/lib/Jifty/Web/Form/Element.pm	Fri Jun  8 16:46:17 2007
@@ -149,8 +149,8 @@
 
 =cut
 
-sub accessors { shift->handlers, qw(class key_binding key_binding_label id label tooltip) }
-__PACKAGE__->mk_accessors(qw(_onclick class key_binding key_binding_label id label tooltip));
+sub accessors { shift->handlers, qw(class key_binding key_binding_label id label tooltip continuation) }
+__PACKAGE__->mk_accessors(qw(_onclick class key_binding key_binding_label id label tooltip continuation));
 
 =head2 new PARAMHASH OVERRIDE
 
@@ -320,7 +320,7 @@
         my $string = join ";", (grep {not ref $_} (ref $value eq "ARRAY" ? @{$value} : ($value)));
         if (@fragments or (!$actions || %$actions)) {
 
-            my $update = Jifty->web->escape("update( ". Jifty::JSON::objToJson( {actions => $actions, fragments => \@fragments }, {singlequote => 1}) .", this );");
+            my $update = Jifty->web->escape("update( ". Jifty::JSON::objToJson( {actions => $actions, fragments => \@fragments, continuation => $self->continuation }, {singlequote => 1}) .", this );");
             $string .= $self->javascript_preempt ? "return $update" : "$update; return true;";
         }
         if ($confirm) {

Modified: jifty/trunk/lib/Jifty/Web/PageRegion.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Web/PageRegion.pm	(original)
+++ jifty/trunk/lib/Jifty/Web/PageRegion.pm	Fri Jun  8 16:46:17 2007
@@ -316,6 +316,10 @@
 	# clone.
 	my ($path, $arg) = split(/\?/, $self->path, 2);
 	$subrequest->path( $path );
+	my %args = (map { split /=/, $_ } split /&/, $arg);
+	if ($args{'J:C'}) {
+	    $subrequest->continuation($args{'J:C'});
+	}
     }
     # Remove all of the actions
     unless ($enable_actions) {

Modified: jifty/trunk/share/web/static/js/jifty.js
==============================================================================
--- jifty/trunk/share/web/static/js/jifty.js	(original)
+++ jifty/trunk/share/web/static/js/jifty.js	Fri Jun  8 16:46:17 2007
@@ -121,7 +121,10 @@
                     a['fields'][Form.Element.getField(f)] = {};
                 var field = Form.Element.getField(f);
                 var type = Form.Element.getType(f);
-                    
+
+                // XXX: fallback value being an array makes server upset
+                if (type == 'fallback' && a['fields'][field][type])
+                    continue                    
                 a['fields'][field][type] = this._mergeValues(a['fields'][field][type],
                                                              Form.Element.getValue(f));
             }
@@ -719,7 +722,6 @@
 //     - 'mode' is one of 'Replace', or the name of a Prototype Insertion
 //     - 'effect' is the name of a Prototype Effect
 function update() {
-    // If we don't have XMLHttpRequest, bail and fallback on full-page
     // loads
     if(!Ajax.getTransport()) return true;
     // XXX: prevent default behavior in IE
@@ -740,19 +742,21 @@
     // Grab extra arguments (from a button)
     var button_args = Form.Element.buttonFormElements(trigger);
 
+    var form = Form.Element.getForm(trigger);
     // If the action is null, take all actions
     if (named_args['actions'] == null) {
         named_args['actions'] = {};
         // default to disable fields
-        var form = Form.Element.getForm(trigger);
         if (form)
             Form.getActions(form).map(function(x){
                 named_args['actions'][x.moniker] = 1;
             });
     }
+    var optional_fragments;
+    if (form && form['J:CALL']) 
+	optional_fragments = [ prepare_element_for_update({'mode':'Replace','args':{},'region':'__page','path': null}) ];
     // Build actions structure
     request['actions'] = $H();
-    var optional_fragments;
     for (var moniker in named_args['actions']) {
         var disable = named_args['actions'][moniker];
         var a = new Action(moniker, button_args);
@@ -823,6 +827,13 @@
                 }
             }
         }
+        for (var redirect = response.firstChild;
+             redirect != null;
+             redirect = redirect.nextSibling) {
+            if (redirect.nodeName == 'redirect') {
+                document.location = redirect.getAttribute("url");
+            }
+        }
     };
     var onFailure = function(transport, object) {
         hide_wait_message_now();
@@ -846,6 +857,9 @@
         request['variables']['region-'+k] = current_args[k];
     }
 
+    // Build continuation structure
+    request['continuation'] = named_args['continuation'];
+
     // Push any state variables which we set into the forms
     for (var i = 0; i < document.forms.length; i++) {
         var form = document.forms[i];

Modified: jifty/trunk/share/web/templates/__jifty/webservices/xml
==============================================================================
--- jifty/trunk/share/web/templates/__jifty/webservices/xml	(original)
+++ jifty/trunk/share/web/templates/__jifty/webservices/xml	Fri Jun  8 16:46:17 2007
@@ -4,6 +4,12 @@
 $writer->xmlDecl( "UTF-8", "yes" );
 $writer->startTag("response");
 
+if (my $ext = Jifty->web->request->argument('_webservice_external_redirect')) {
+    $writer->startTag("redirect", url => $ext);
+    $writer->endTag();
+}
+else {
+
 FRAGMENT:
 for my $f ( Jifty->web->request->fragments ) {
     # Set up the region stack
@@ -50,6 +56,8 @@
     Jifty->web->current_region->exit while Jifty->web->current_region;
 }
 
+}
+
 my %results = Jifty->web->response->results;
 for (keys %results) {
     $writer->startTag("result", moniker => $_, class => $results{$_}->action_class);


More information about the Jifty-commit mailing list