[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