[Bps-public-commit] r14629 - in Pushmi/trunk: . Pushmi-Admin/lib/Pushmi/Admin Pushmi-Admin/lib/Pushmi/Admin/Action Pushmi-Admin/lib/Pushmi/Admin/Model Pushmi-Admin/share/web/static/css Pushmi-Admin/share/web/static/js

alexmv at bestpractical.com alexmv at bestpractical.com
Tue Jul 29 19:04:40 EDT 2008


Author: alexmv
Date: Tue Jul 29 19:04:40 2008
New Revision: 14629

Added:
   Pushmi/trunk/Pushmi-Admin/share/web/static/js/
   Pushmi/trunk/Pushmi-Admin/share/web/static/js/jquery.progressbar.js
Removed:
   Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Action/CheckURL.pm
Modified:
   Pushmi/trunk/   (props changed)
   Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin.pm
   Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Action/CreateReplica.pm
   Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Dispatcher.pm
   Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Model/Replica.pm
   Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/View.pm
   Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Watcher.pm
   Pushmi/trunk/Pushmi-Admin/share/web/static/css/app.css

Log:
 r34943 at kohr-ah:  chmrr | 2008-07-29 19:04:34 -0400
  * Remove CheckURL -- instead, use Multipage plugin
  * Progress bars and more AJAX


Modified: Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin.pm
==============================================================================
--- Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin.pm	(original)
+++ Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin.pm	Tue Jul 29 19:04:40 2008
@@ -5,6 +5,13 @@
 
 use SVK::Util 'str2time';
 
+sub start {
+    my $class = shift;
+    Jifty->web->add_javascript(qw(
+        jquery.progressbar.js
+    ));
+}
+
 sub svn_info_for {
     my $class = shift;
     my ($url) = @_;
@@ -19,6 +26,7 @@
     eval {
         my ($baton, $ref) = SVN::Core::auth_open_helper(undef);
         my $ra = SVN::Ra->new( url => $url, config => undef, auth => $baton);
+        $props->{root} = $ra->get_repos_root;
         $props->{rev} = $ra->get_latest_revnum;
         $props->{date} = 1e6 * str2time($ra->rev_prop($props->{rev}, 'svn:date'));
     };

Modified: Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Action/CreateReplica.pm
==============================================================================
--- Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Action/CreateReplica.pm	(original)
+++ Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Action/CreateReplica.pm	Tue Jul 29 19:04:40 2008
@@ -2,16 +2,39 @@
 use warnings;
 
 package Pushmi::Admin::Action::CreateReplica;
-use base qw/Jifty::Action::Record::Create/;
 
-sub arguments {
+use Moose;
+
+extends('Jifty::Action::Record::Create');
+with('Jifty::Plugin::Multipage::Action');
+
+sub validate_url {
     my $self = shift;
-    my $args = $self->SUPER::arguments;
+    my ($url) = @_;
+    return $self->validation_error(
+        url => "We can only deal with http:// or file:// urls" )
+        unless $url =~ m{^(http|file)://};
+
+    $url =~ s{/+$}{};
+
+    my $props = Pushmi::Admin->svn_info_for($url);
+
+    return $self->validation_error( url => "Read of $url failed\n" ) unless $props;
+    $self->argument_value( url => $props->{root} );
+    return $self->validation_ok("url");
+}
+
+around 'arguments' => sub {
+    my ($next, $self) = @_;
+    my $args = $next->($self);
     $args->{name}{ajax_validates} = 1;
+    $args->{url}{ajax_validates} = 1;
     $args->{mirror} = {};
     return $args;
-}
+};
 
 sub record_class {'Pushmi::Admin::Model::Replica'}
 
+sub report_success {}
+
 1;

Modified: Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Dispatcher.pm
==============================================================================
--- Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Dispatcher.pm	(original)
+++ Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Dispatcher.pm	Tue Jul 29 19:04:40 2008
@@ -4,7 +4,7 @@
 package Pushmi::Admin::Dispatcher;
 use Jifty::Dispatcher -base;
 
-on '/create' => run {
+on '/created' => run {
     if (    Jifty->web->response->result("create")
         and Jifty->web->response->result("create")->success )
     {
@@ -12,7 +12,7 @@
             Jifty->web->response->result("create")->content("id") );
         redirect( "/replica/" . $replica->clean_name );
     } else {
-        show "/create";
+        redirect "/";
     }
 };
 

Modified: Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Model/Replica.pm
==============================================================================
--- Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Model/Replica.pm	(original)
+++ Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Model/Replica.pm	Tue Jul 29 19:04:40 2008
@@ -12,13 +12,11 @@
 
 use Time::Duration qw//;
 
-my %CACHE;
-
 use Pushmi::Admin::Record schema {
 
     column name =>
         type is 'text',
-        is mandatory, is unique;
+        is mandatory, is unique, ajax validates;
 
     column clean_name =>
         type is 'text',
@@ -26,7 +24,7 @@
 
     column url =>
         type is 'text',
-        is mandatory;
+        is mandatory, ajax validates;
 
     column status =>
         type is 'text',
@@ -122,7 +120,8 @@
     return if $self->pushmi and $self->pushmi->locked;
 
     unless (fork) {
-        close STDOUT; # XXX This doesn't work?
+        close STDOUT;
+        close STDIN;
         exec( $^X, Jifty->config->app("pushmi_bin"), "sync",
             $self->svn_root );
     }
@@ -254,6 +253,7 @@
             } else {
                 my $id = $self->id;
                 close STDOUT;
+                close STDIN;
                 exec( $^X => "-Ilib",
                     "-MPushmi::Admin::Watcher",
                     "-e" => "Pushmi::Admin::Watcher->new($id)"

Modified: Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/View.pm
==============================================================================
--- Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/View.pm	(original)
+++ Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/View.pm	Tue Jul 29 19:04:40 2008
@@ -24,72 +24,68 @@
         }
     };
 
-    add_replica();
+    div {
+        { id is 'new_replica', class is 'roundbox' };
+        h2 {"Add a new replica"};
+        form {
+            my $check = Jifty->web->new_action(
+                class   => "CreateReplica",
+                moniker => "create",
+            );
+            render_param( $check => "name" );
+            render_param( $check => "url" );
+            div {
+                {class is "submit_button"};
+                outs_raw(
+                    $check->next_page_button(
+                        label => "Create",
+                        url   => "/create",
+                    )
+                );
+            }
+        }
+    };
 };
 
 template 'create' => page { title => "Create a new replica" } content {
-    my $result = Jifty->web->response->result("check");
-    my $data = $result ? $result->content("repository") : {};
+    my $new = Jifty->web->new_action(
+        class   => "CreateReplica",
+        moniker => "create",
+    );
+    Jifty->web->redirect('/') unless $new->argument_value("url");
+    my $data = Pushmi::Admin->svn_info_for( $new->argument_value("url") );
     my $changed
-        = DateTime->from_epoch( epoch => $data->{last_changed_date} / 1e6 );
+        = DateTime->from_epoch( epoch => $data->{date} / 1e6 );
     $changed->set_time_zone("EST");
     div {
         { id is 'new_replica', class is 'roundbox' };
         h2 {"Add a new replica"};
         div {
             { id is 'replica_status', class is 'roundbox' };
-            h3 { $data->{repos_root_URL} }
+            h3 { $new->argument_value("url") }
             p  { $data->{rev} . " revisions" } p {
                 "Last modified on " . $changed->ymd . ", at " . $changed->hms;
             }
         };
 
         form {
-            my $new = Jifty->web->new_action(
-                class   => "CreateReplica",
-                moniker => "create",
+            $new->argument_value(
+                mirror => Pushmi::Admin::Model::Replica->_clean_name(
+                    $new->argument_value("name")
+                )
             );
-            if ( my $prev = Jifty->web->request->action("check") ) {
-                $new->argument_value( name => $prev->argument("name") );
-                $new->argument_value(
-                    mirror => Pushmi::Admin::Model::Replica->_clean_name(
-                        $prev->argument("name")
-                    )
-                );
-                $new->argument_value( url => $data->{repos_root_URL} );
-            }
 
-            render_param( $new => "name" );
-            outs_raw( $new->form_value("url") );
-            render_param( $new => "url", render_as => "hidden" );
+            render_param( $new => "name", default_value => $new->argument_value("name") );
+            outs_raw( $new->form_value("url", default_value => $new->argument_value("url")) );
             render_param( $new => "mirror" );
-            form_submit( label => "Create" );
+            div {
+                {class is "submit_button"};
+                outs_raw( $new->finish_button( label => "Create", url => "/created", class => "submit" ) );
+            }
         };
     }
 };
 
-template 'check' => page { title => "Create a new replica" } content {
-    add_replica();
-};
-
-sub add_replica {
-    div {
-        { id is 'new_replica', class is 'roundbox' };
-        h2 {"Add a new replica"};
-        form {
-            my $check = Jifty->web->new_action(
-                class             => "CheckURL",
-                moniker           => "check",
-                sticky_on_failure => 1,
-                sticky_on_success => 1,
-            );
-            render_param( $check => "name" );
-            render_param( $check => "url" );
-            form_submit( label => "Create" );
-        }
-    }
-}
-
 template 'fragments/summary' => sub {
     my $id = get('id');
     my $replica = Pushmi::Admin::Model::Replica->load($id);
@@ -108,6 +104,11 @@
         }
     };
 
+    if ($replica->remote_revision) {
+        my $progress = int(($replica->local_revision / $replica->remote_revision) * 100);
+        outs_raw( qq{<script>if (jQuery("#progress")) jQuery("#progress").progressBar($progress)</script>} );
+    }
+
     # Add a PubSub watcher, if need be
     Jifty->subs->add(
         class       => 'ReplicaStatus',
@@ -119,8 +120,75 @@
     $replica->start_watcher;
 };
 
-template 'replica' => page { title => "About " . get("replica")->name }
-    content {
+template 'fragments/details' => sub {
+    my $id = get('id');
+    my $replica = Pushmi::Admin::Model::Replica->load($id);
+    if ( $replica->status eq "behind" and $replica->local_revision == 0 )
+    {
+        h2 {"Next step: mirroring"}
+        p {
+            "The next step is to mirror all "
+                . $replica->remote_revision
+                . " revisions from the remote mirror.  This may take some time!";
+        };
+
+#        p {
+#            "If you have a bootstrap file for this mirror, you can upload it below."
+#        };
+        form {
+            my $sync = Jifty->web->new_action( class => "Sync", );
+            render_param(
+                $sync => "replica" => default_value => $replica->id );
+            form_submit( label => "Start mirroring", onclick => {submit => $sync, region => "progress-".$replica->id, replace_with => "/fragments/progressbar", effect => "Appear"} );
+        }
+    } elsif ( $replica->status ne "failed" ) {
+        h2 {"Replica health"};
+        p {
+            "Last local commit: r"
+                . $replica->local_revision . " - "
+                . $replica->last_local;
+        };
+        if ( $replica->latency ) {
+            p {
+                "Last master commit: r"
+                    . $replica->remote_revision . " - "
+                    . $replica->last_remote;
+            }
+            p { "Latency to master: " . $replica->latency };
+        }
+        if ($replica->status ne "loading") {
+            form {
+                my $sync = Jifty->web->new_action( class => "Sync", );
+                render_param(
+                    $sync => "replica" => default_value => $replica->id );
+                form_submit( label => "Force an update now", onclick => {submit => $sync, region => "progress-".$replica->id, replace_with => "/fragments/progressbar", effect => "Appear"} );
+            }
+        }
+    } else {
+        h2 {"Local replica failure"};
+    }
+    Jifty->subs->add(
+        class       => 'ReplicaStatus',
+        queries     => [{ id => $id }],
+        mode        => 'Replace',
+        region      => Jifty->web->qualified_region,
+        render_with => '/fragments/details',
+    );
+};
+
+template 'fragments/progressbar' => sub {
+    my $id = get('id');
+    my $replica = Pushmi::Admin::Model::Replica->load($id);
+    return unless $replica->remote_revision;
+    return if $replica->remote_revision eq $replica->local_revision;
+    return unless $replica->status eq "loading";
+
+    my $progress = int(($replica->local_revision / $replica->remote_revision) * 100);
+    outs_raw( q{<script>jQuery(document).ready(function() {jQuery("#progress").progressBar();})</script>} );
+    span {{ class is "progressBar", id is "progress"}; $progress . "%" };
+};
+
+template 'replica' => page { title => "About " . get("replica")->name } content {
     my $replica = get 'replica';
     div {
         { class is 'roundbox' };
@@ -128,55 +196,21 @@
         render_region(
             name      => "summary-" . $replica->id,
             path      => "/fragments/summary",
-            arguments => { id => $replica->id }
+            arguments => { id => $replica->id },
         );
+        my @args;
+        @args = (pqth => "/fragments/progressbar") if $replica->status eq "loading";
+        div { render_region( name => "progress-" . $replica->id, arguments => {id => $replica->id}, @args ) };
     };
 
+
     div {
         { class is 'roundbox' };
-
-        if ( $replica->status eq "behind" and $replica->local_revision == 0 )
-        {
-            h2 {"Next step: mirroring"}
-            p {
-                "The next step is to mirror all "
-                    . $replica->remote_revision
-                    . " revisions from the remote mirror.  This may take some time!";
-            };
-
-#            p {
-#                "If you have a bootstrap file for this mirror, you can upload it below."
-#            };
-            form {
-                my $sync = Jifty->web->new_action( class => "Sync", );
-                render_param(
-                    $sync => "replica" => default_value => $replica->id );
-                form_submit( label => "Start mirroring" );
-            }
-        } elsif ( $replica->status ne "failed" ) {
-            h2 {"Replica health"};
-            p {
-                "Last local commit: r"
-                    . $replica->local_revision . " - "
-                    . $replica->last_local;
-            };
-            if ( $replica->latency ) {
-                p {
-                    "Last master commit: r"
-                        . $replica->remote_revision . " - "
-                        . $replica->last_remote;
-                }
-                p { "Latency to master: " . $replica->latency };
-            }
-            form {
-                my $sync = Jifty->web->new_action( class => "Sync", );
-                render_param(
-                    $sync => "replica" => default_value => $replica->id );
-                form_submit( label => "Force an update now" );
-            }
-        } else {
-            h2 {"Local replica failure"};
-        }
+        render_region(
+            name      => "details-" . $replica->id,
+            path      => "/fragments/details",
+            arguments => { id => $replica->id },
+        );
     };
 
     div {
@@ -186,11 +220,9 @@
             label => "Advanced.."
         );
     }
-}
+};
 
-template 'advanced' =>
-    page { title => "Advanced configuration for " . get("replica")->name }
-    content {
+template 'advanced' => page { title => "Advanced configuration for " . get("replica")->name } content {
     my $replica = get 'replica';
 
     div {
@@ -235,4 +267,4 @@
             }
         };
     }
-}
+};

Modified: Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Watcher.pm
==============================================================================
--- Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Watcher.pm	(original)
+++ Pushmi/trunk/Pushmi-Admin/lib/Pushmi/Admin/Watcher.pm	Tue Jul 29 19:04:40 2008
@@ -8,6 +8,7 @@
 BEGIN {
     # We must close STDOUT, or our parent request may never return to the client
     close STDOUT;
+    close STDIN;
     Jifty->new;
 }
     

Modified: Pushmi/trunk/Pushmi-Admin/share/web/static/css/app.css
==============================================================================
--- Pushmi/trunk/Pushmi-Admin/share/web/static/css/app.css	(original)
+++ Pushmi/trunk/Pushmi-Admin/share/web/static/css/app.css	Tue Jul 29 19:04:40 2008
@@ -137,6 +137,13 @@
 .status-light.offline { background-image: url(/static/images/status/red.png);    }
 .status-light.failed  { background-image: url(/static/images/status/red.png);    }
 
+/* Progressbar */
+
+#progress {
+  text-align: center;
+  display: block;
+}
+
 
 /* The "advanced" button and page */
 

Added: Pushmi/trunk/Pushmi-Admin/share/web/static/js/jquery.progressbar.js
==============================================================================
--- (empty file)
+++ Pushmi/trunk/Pushmi-Admin/share/web/static/js/jquery.progressbar.js	Tue Jul 29 19:04:40 2008
@@ -0,0 +1,130 @@
+/*
+ * jQuery Progress Bar plugin
+ * Version 1.1.0 (06/20/2008)
+ * @requires jQuery v1.2.1 or later
+ *
+ * Copyright (c) 2008 Gary Teo
+ * http://t.wits.sg
+
+USAGE:
+	$(".someclass").progressBar();
+	$("#progressbar").progressBar();
+	$("#progressbar").progressBar(45);							// percentage
+	$("#progressbar").progressBar({showText: false });			// percentage with config
+	$("#progressbar").progressBar(45, {showText: false });		// percentage with config
+*/
+(function($) {
+	$.extend({
+		progressBar: new function() {
+
+			this.defaults = {
+				increment	: 1,
+				speed		: 15,
+				showText	: false,											// show text with percentage in next to the progressbar? - default : true
+				width		: 250,											// Width of the progressbar - don't forget to adjust your image too!!!
+				boxImage	: '/images/progressbar/bigbox.png',		// boxImage : image around the progress bar
+				barImage	: '/images/progressbar/bigblue.png',	// Image to use in the progressbar. Can be an array of images too.
+				height		: 25											// Height of the progressbar - don't forget to adjust your image too!!!
+			};
+			
+			/* public methods */
+			this.construct = function(arg1, arg2) {
+				var argpercentage	= null;
+				var argconfig		= null;
+				
+				if (arg1 != null) {
+					if (!isNaN(arg1)) {
+						argpercentage 	= arg1;
+						if (arg2 != null) {
+							argconfig	= arg2; }
+					} else {
+						argconfig		= arg1; 
+					}
+				}
+				
+				return this.each(function(child) {
+					var pb		= this;
+					if (argpercentage != null && this.bar != null && this.config != null) {
+						this.config.tpercentage	= argpercentage;
+						if (argconfig != null)
+							pb.config			= $.extend(this.config, argconfig);
+					} else {
+						var $this				= $(this);
+						var config				= $.extend({}, $.progressBar.defaults, argconfig);
+						var percentage			= argpercentage;
+						if (argpercentage == null)
+							var percentage		= $this.html().replace("%","");	// parsed percentage
+						
+						
+						$this.html("");
+						var bar					= document.createElement('img');
+						var text				= document.createElement('span');
+						bar.id 					= this.id + "_percentImage";
+						text.id 				= this.id + "_percentText";
+						bar.src					= config.boxImage;
+						bar.width				= config.width;
+						var $bar				= $(bar);
+						var $text				= $(text);
+						
+						this.bar				= $bar;
+						this.text				= $text;
+						this.config				= config;
+						this.config.cpercentage	= 0;
+						this.config.tpercentage	= percentage;
+						
+						$bar.css("width", config.width + "px");
+						$bar.css("height", config.height + "px");
+						$bar.css("background-image", "url(" + config.barImage + ")");
+						$bar.css("padding", "0");
+						$bar.css("margin", "0");
+						$this.append($bar);
+						$this.append($text);
+						
+						bar.alt				= this.tpercentage;
+						bar.title			= this.tpercentage;
+					}
+					
+					
+					
+					var t = setInterval(function() {
+						var config		= pb.config;
+						var cpercentage = parseInt(config.cpercentage);
+						var tpercentage = parseInt(config.tpercentage);
+						var increment	= parseInt(config.increment);
+						var bar			= pb.bar;
+						var text		= pb.text;
+						var pixels		= config.width / 100;			// Define how many pixels go into 1%
+						
+						bar.css("background-position", (((config.width * -1)) + (cpercentage * pixels)) + 'px 50%');
+						
+						if (config.showText)
+							text.html(" " + Math.round(cpercentage) + "%");
+						
+						if (cpercentage > tpercentage) {
+							if (cpercentage - increment  < tpercentage) {
+								pb.config.cpercentage = 0 + tpercentage
+							} else {
+								pb.config.cpercentage -= increment;
+							}
+						}
+						else if (pb.config.cpercentage < pb.config.tpercentage) {
+							if (cpercentage + increment  > tpercentage) {
+								pb.config.cpercentage = tpercentage
+							} else {
+								pb.config.cpercentage += increment;
+							}
+						} 
+						else {
+							clearInterval(t);
+						}
+					}, pb.config.speed); 
+				});
+			};
+		}
+	});
+		
+	$.fn.extend({
+        progressBar: $.progressBar.construct
+	});
+	
+})(jQuery);



More information about the Bps-public-commit mailing list