0.14_33 commit r0_14_33
authorTony Cook <tony@develop-help.com>
Thu, 16 Sep 2004 01:34:24 +0000 (01:34 +0000)
committertony <tony@45cb6cf1-00bc-42d2-bb5a-07f51df49f94>
Thu, 16 Sep 2004 01:34:24 +0000 (01:34 +0000)
22 files changed:
MANIFEST
Makefile
localinst.perl
site/cgi-bin/bse.cfg
site/cgi-bin/modules/BSE/CfgInfo.pm
site/cgi-bin/modules/BSE/DB/Mysql.pm
site/cgi-bin/modules/BSE/Edit/Article.pm
site/cgi-bin/modules/BSE/Edit/Product.pm
site/cgi-bin/modules/BSE/TB/Order.pm
site/cgi-bin/modules/BSE/Thumb/Imager.pm [new file with mode: 0644]
site/cgi-bin/modules/BSE/UI/Affiliate.pm
site/cgi-bin/modules/BSE/UserReg.pm
site/cgi-bin/user.pl
site/docs/.cvsignore
site/docs/bse.pod
site/docs/config.pod
site/docs/makedocs
site/docs/thumbnails.pod [new file with mode: 0644]
site/templates/admin/article_img.tmpl
site/templates/user/base_orderdetail.tmpl [new file with mode: 0644]
site/templates/user/userpage_base.tmpl
test.cfg

index 62ff768..4ed3cbc 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -96,6 +96,7 @@ site/cgi-bin/modules/BSE/TB/Subscription.pm
 site/cgi-bin/modules/BSE/TB/Subscription/Calc.pm
 site/cgi-bin/modules/BSE/TB/Subscriptions.pm
 site/cgi-bin/modules/BSE/Template.pm
+site/cgi-bin/modules/BSE/Thumb/Imager.pm
 site/cgi-bin/modules/BSE/UI/AdminDispatch.pm
 site/cgi-bin/modules/BSE/UI/Affiliate.pm
 site/cgi-bin/modules/BSE/UI/Dispatch.pm
@@ -177,6 +178,8 @@ site/docs/standard.pod
 site/docs/shopadmin.html
 site/docs/templates.html
 site/docs/templates.pod
+site/docs/thumbnails.html
+site/docs/thumbnails.pod
 site/docs/upgrade_mysql.html
 site/htdocs/a/.htaccess
 site/htdocs/admin/advanced.html
@@ -201,6 +204,7 @@ site/htdocs/images/admin/error.gif
 site/htdocs/images/admin/help.gif
 site/htdocs/images/admin/move_down.gif
 site/htdocs/images/admin/move_up.gif
+site/htdocs/images/admin/nothumb.png
 site/htdocs/images/admin/unchecked.gif
 site/htdocs/images/filestatus/download.gif
 site/htdocs/images/filestatus/forSale.gif
@@ -341,6 +345,7 @@ site/templates/sidebar/logon.tmpl
 site/templates/test/children.tmpl
 site/templates/textemail/basic.tmpl
 site/templates/user/alreadyblacklisted_base.tmpl
+site/templates/user/base_orderdetail.tmpl
 site/templates/user/blacklistdone_base.tmpl
 site/templates/user/cantunsub_base.tmpl
 site/templates/user/confirmed_base.tmpl
index e97060f..1ee4fb7 100755 (executable)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-VERSION=0.14_32
+VERSION=0.14_33
 DISTNAME=bse-$(VERSION)
 DISTBUILD=$(DISTNAME)
 DISTTAR=../$(DISTNAME).tar
index 41c0cd3..b6a2661 100644 (file)
@@ -21,8 +21,8 @@ system("rm -rf $instbase/cgi-bin")
   and die "Cannot remove cgi-bin";
 system "rm -rf $instbase/data"
   and die "Cannot remove data";
-system "rm -f $instbase/htdocs/{*.html,a/*.html,shop/*.html,images/*.jpg}"
-  and die "Cannot remove htdocs";
+#system "rm -f $instbase/htdocs/{*.html,a/*.html,shop/*.html,images/*.jpg}"
+#  and die "Cannot remove htdocs";
 
 system "cp -rf $dist/site/cgi-bin $instbase"
   and die "Cannot copy cgi-bin";
index dd84b41..427c800 100644 (file)
@@ -16,6 +16,7 @@ siteuser_images = $(paths/downloads)
 [pregenerate]
 
 ; the following are required by the system - don't modify them
+user/orderdetail.tmpl = user,user/base_orderdetail.tmpl
 user/alreadyblacklisted.tmpl = user,user/alreadyblacklisted_base.tmpl
 user/blacklistdone.tmpl = user,user/blacklistdone_base.tmpl
 user/cantunsub.tmpl = user,user/cantunsub_base.tmpl
@@ -311,6 +312,10 @@ Product=
 6=formatting guide
 7=RDF
 
+[editor]
+;allow_thumbs=1
+;thumbs_class=BSE::Thumb::Imager
+
 [site users]
 display_name1=First Name
 display_name2=Last Name
index 1017969..0952086 100644 (file)
@@ -4,7 +4,7 @@ use strict;
 use vars qw(@ISA @EXPORT_OK);
 require Exporter;
 @ISA = qw(Exporter);
-@EXPORT_OK = qw(custom_class admin_base_url);
+@EXPORT_OK = qw(custom_class admin_base_url cfg_image_dir);
 
 =head1 NAME
 
@@ -63,6 +63,12 @@ sub admin_base_url {
   return $base;
 }
 
+sub cfg_image_dir {
+  my ($cfg) = @_;
+
+  $cfg->entry('paths', 'images', $Constants::IMAGEDIR);
+}
+
 1;
 
 __END__
index bfa0ede..d434ba4 100644 (file)
@@ -75,6 +75,10 @@ EOS
 select ar.*, pr.* from article ar, product pr
    where ar.id = pr.articleId
      and (pr.subscription_id = ? or subscription_required = ?)
+SQL
+   'Products.orderProducts' => <<SQL,
+select ar.*, pr.* from article ar, product pr, order_item oi
+  where oi.orderId = ? and oi.productId = ar.id and ar.id = pr.articleId
 SQL
    deleteProduct => 'delete from product where articleId = ?',
    Orders => 'select * from orders',
index 9469595..4089026 100644 (file)
@@ -7,7 +7,8 @@ use BSE::Util::Valid qw/valid_date/;
 use BSE::Permissions;
 use DevHelp::HTML qw(:default popup_menu);
 use BSE::Arrows;
-use BSE::CfgInfo qw(custom_class admin_base_url);
+use BSE::CfgInfo qw(custom_class admin_base_url cfg_image_dir);
+use BSE::Util::Iterate;
 
 sub article_dispatch {
   my ($self, $req, $article, $articles) = @_;
@@ -80,6 +81,7 @@ sub article_actions {
      filesave => 'filesave',
      hide => 'hide',
      unhide => 'unhide',
+     a_thumb => 'req_thumb',
     );
 }
 
@@ -348,7 +350,7 @@ sub title_images {
   my ($self, $article) = @_;
 
   my @title_images;
-  my $imagedir = $self->{cfg}->entry('paths', 'images', $Constants::IMAGEDIR);
+  my $imagedir = cfg_image_dir($self->{cfg});
   if (opendir TITLE_IMAGES, "$imagedir/titles") {
     @title_images = sort 
       grep -f "$imagedir/titles/$_" && /\.(gif|jpeg|jpg|png)$/i,
@@ -928,10 +930,78 @@ sub tag_typename {
   return $1;
 }
 
+sub _get_thumbs_class {
+  my ($self) = @_;
+
+  $self->{cfg}->entry('editor', 'allow_thumb', 0)
+    or return;
+
+  my $class = $self->{cfg}->entry('editor', 'thumbs_class')
+    or return;
+  
+  (my $filename = "$class.pm") =~ s!::!/!g;
+  eval { require $filename; };
+  if ($@) {
+    print STDERR "** Error loading thumbs_class $class ($filename): $@\n";
+    return;
+  }
+  my $obj;
+  eval { $obj = $class->new($self->{cfg}) };
+  if ($@) {
+    print STDERR "** Error creating thumbs objects $class: $@\n";
+    return;
+  }
+
+  return $obj;
+}
+
+sub tag_thumbimage {
+  my ($cfg, $thumbs_obj, $current_image, $args) = @_;
+
+  $$current_image or return '** no current image **';
+
+  my $imagedir = cfg_image_dir($cfg);
+
+  my $filename = "$imagedir/$$current_image->{image}";
+  -e $filename or return "** image file missing **";
+
+  my ($max_width, $max_height, $max_pixels) = split ' ', $args;
+  defined $max_width && $max_width eq '-' and undef $max_width;
+  defined $max_height && $max_height eq '-' and undef $max_height;
+  defined $max_pixels && $max_pixels eq '-' and undef $max_pixels;
+
+  my ($use_orig, $width, $height) = $thumbs_obj->thumb_dimensions
+    ($filename, $$current_image, $max_width, $max_height, $max_pixels);
+
+
+  my ($uri, $alt);
+  if ($use_orig) {
+    $alt = $$current_image->{alt};
+    $uri = "/images/$$current_image->{image}";
+  }
+  elsif ($width) {
+    $alt = "thumbnail of ".$$current_image->{alt};
+    $uri = "$ENV{SCRIPT_NAME}?a_thumb=1&id=$$current_image->{articleId}&im=$$current_image->{id}&w=$width&h=$height";
+  }
+  else {
+    # link to the default thumbnail
+    $uri = $cfg->entry('editor', 'default_thumbnail', '/images/admin/nothumb.png');
+    $width = $cfg->entry('editor', 'default_thumbnail_width', 100);
+    $height = $cfg->entry('editor', 'default_thumbnail_height', 100);
+    $alt = $cfg->entry('editor', 'default_thumbnail_alt', 
+                      "no thumbnail available");
+  }
+  
+  $alt = escape_html($alt);
+  $uri = escape_html($uri);
+  return qq!<img src="$uri" width="$width" height="$height" alt="$alt" border="0" />!;
+}
+
 sub low_edit_tags {
   my ($self, $acts, $request, $article, $articles, $msg, $errors) = @_;
 
   my $cgi = $request->cgi;
+  my $show_full = $cgi->param('f_showfull');
   $msg ||= $cgi->param('message');
   $msg ||= '';
   $errors ||= {};
@@ -958,8 +1028,11 @@ sub low_edit_tags {
   my $cfg = $self->{cfg};
   my $mbcs = $cfg->entry('html', 'mbcs', 0);
   my $tag_hash = $mbcs ? \&tag_hash_mbcs : \&tag_hash;
+  my $thumbs_obj_real = $self->_get_thumbs_class();
+  my $thumbs_obj = $show_full ? undef : $thumbs_obj_real;
   my @images;
   my $image_index;
+  my $current_image;
   my @children;
   my $child_index;
   my %stepkids;
@@ -972,6 +1045,7 @@ sub low_edit_tags {
   my @stepparentpossibles;
   my @files;
   my $file_index;
+  my $it = BSE::Util::Iterate->new;
   return
     (
      BSE::Util::Tags->basic($acts, $cgi, $cfg),
@@ -987,9 +1061,12 @@ sub low_edit_tags {
      script => $ENV{SCRIPT_NAME},
      level => $article->{level},
      checked => \&tag_checked,
-     DevHelp::Tags->make_iterator2
+     $it->make_iterator
      ([ \&iter_get_images, $self, $article ], 'image', 'images', \@images, 
-      \$image_index),
+      \$image_index, undef, \$current_image),
+     thumbimage => [ \&tag_thumbimage, $cfg, $thumbs_obj, \$current_image ],
+     ifThumbs => defined($thumbs_obj),
+     ifCanThumbs => defined($thumbs_obj_real),
      imgmove => [ \&tag_imgmove, $request, $article, \$image_index, \@images ],
      message => $msg,
      DevHelp::Tags->make_iterator2
@@ -1523,7 +1600,7 @@ sub save_thumbnail {
   unless ($original) {
     @$newdata{qw/thumbImage thumbWidth thumbHeight/} = ('', 0, 0);
   }
-  my $imagedir = $self->{cfg}->entry('paths', 'images', $Constants::IMAGEDIR);
+  my $imagedir = cfg_image_dir($self->{cfg});
   if ($cgi->param('remove_thumb') && $original && $original->{thumbImage}) {
     unlink("$imagedir/$original->{thumbImage}");
     @$newdata{qw/thumbImage thumbWidth thumbHeight/} = ('', 0, 0);
@@ -1987,7 +2064,7 @@ sub add_image {
   # for the sysopen() constants
   use Fcntl;
 
-  my $imagedir = $req->cfg->entry('paths', 'images', $Constants::IMAGEDIR);
+  my $imagedir = cfg_image_dir($req->cfg);
   # loop until we have a unique filename
   my $counter="";
   $filename = time. '_' . $counter . '_' . $basename 
@@ -2054,7 +2131,7 @@ sub remove_img {
   my @images = $self->get_images($article);
   my ($image) = grep $_->{id} == $imageid, @images
     or return $self->show_images($req, $article, $articles, "No such image");
-  my $imagedir = $req->cfg->entry('paths', 'images', $Constants::IMAGEDIR);
+  my $imagedir = cfg_image_dir($req->cfg);
   unlink "$imagedir$image->{image}";
   $image->remove;
 
@@ -2114,6 +2191,67 @@ sub move_img_down {
   return $self->refresh($article, $req->cgi, undef, 'Image moved');
 }
 
+sub req_thumb {
+  my ($self, $req, $article) = @_;
+
+  my $cgi = $req->cgi;
+  my $cfg = $req->cfg;
+  my $im_id = $cgi->param('im');
+  my $image;
+  if (defined $im_id && $im_id =~ /^\d+$/) {
+    ($image) = grep $_->{id} == $im_id, $article->images;
+  }
+  my $thumb_obj = $self->_get_thumbs_class();
+  my ($data, $type);
+  if ($image && $thumb_obj) {
+    my $width = $cgi->param('w');
+    my $height = $cgi->param('h');
+    my $pixels = $cgi->param('p');
+    my $imagedir = $cfg->entry('paths', 'images', $Constants::IMAGEDIR);
+    
+    ($type, $data) = $thumb_obj->
+      thumb_data("$imagedir/$image->{image}", $image, $width, $height, 
+                $pixels);
+  }
+
+  if ($type && $data) {
+    
+    return
+      {
+       type => $type,
+       content => $data,
+       headers => [ 
+                  "Content-Length: ".length($data),
+                  "Cache-Control: max-age=3600",
+                 ],
+      };
+  }
+  else {
+    # grab the nothumb image
+    my $uri = $cfg->entry('editor', 'default_thumbnail', '/images/admin/nothumb.png');
+    my $filebase = $Constants::CONTENTBASE;
+    if (open IMG, "<$filebase/$uri") {
+      binmode IMG;
+      my $data = do { local $/; <IMG> };
+      close IMG;
+      my $type = $uri =~ /\.(\w+)$/ ? $1 : 'png';
+      return
+       {
+        type => "image/$type",
+        content => $data,
+        headers => [ "Content-Length: ".length($data) ],
+       };
+    }
+    else {
+      return
+       {
+        type=>"text/html",
+        content => "<html><body>Cannot make thumb or default image</body></html>",
+       };
+    }
+  }
+}
+
 sub get_article {
   my ($self, $articles, $article) = @_;
 
index 67864f9..77de2a9 100644 (file)
@@ -130,9 +130,13 @@ sub _validate_common {
     }
   }
   if (defined $data->{subscription_period}) {
-    unless ($data->{subscription_period} =~ /^\d+$/ && $data->{subscription_period} > 0) {
+    my $sub = $data->{subscription_id};
+    if ($data->{subscription_period} !~ /^\d+$/) {
       $errors->{subscription_period} = "Invalid subscription period, it must be the number of months to subscribe";
     }
+    elsif ($sub != -1 && $data->{subscription_period} < 1) {
+      $errors->{subscription_period} = "Subscription period must be 1 or more when a subscription is selected";
+    }
   }
   if (defined $data->{subscription_usage}) {
     unless ($data->{subscription_usage} =~ /^[123]$/) {
index 311a8a8..bc66a22 100644 (file)
@@ -45,4 +45,17 @@ sub items {
   return BSE::TB::OrderItems->getBy(orderId => $self->{id});
 }
 
+sub files {
+  my ($self) = @_;
+
+  BSE::DB->query(orderFiles=>$self->{id});
+}
+
+sub products {
+  my ($self) = @_;
+
+  require Products;
+  Products->getSpecial(orderProducts=>$self->{id});
+}
+
 1;
diff --git a/site/cgi-bin/modules/BSE/Thumb/Imager.pm b/site/cgi-bin/modules/BSE/Thumb/Imager.pm
new file mode 100644 (file)
index 0000000..f4486fb
--- /dev/null
@@ -0,0 +1,101 @@
+package BSE::Thumb::Imager;
+use strict;
+#use blib '/home/tony/dev/imager/maint/Imager/';
+use Imager;
+
+sub new {
+  my ($class, $cfg) = @_;
+  
+  return bless { cfg => $cfg }, $class;
+}
+
+sub _width_height {
+  my ($self, $image, $max_width, $max_height, $max_pixels) = @_;
+
+  # figure out a scale size
+  my $cfg = $self->{cfg};
+  $max_pixels ||= $cfg->entry('thumbnails', 'max_pixels', 50000);
+  $max_pixels = 100 if $max_pixels < 100;
+  $max_width ||= $cfg->entry('thumbnails', 'max_width', 200);
+  $max_width = 10 if $max_width < 10;
+  $max_height ||= $cfg->entry('thumbnails', 'max_height', 200);
+  $max_height = 10 if $max_height < 10;
+
+  my $width = $image->{width};
+  my $height = $image->{height};
+  if ($width > $max_width) {
+    $width = $max_width;
+    $height = $height * $max_width / $image->{width};
+  }
+  if ($height > $max_height) {
+    my $old_height = $height;
+    $height = $max_height;
+    $width = $width * $max_height / $old_height;
+  }
+
+  if ($width * $height > $max_pixels) {
+    my $scale  = ($max_pixels * 1.0 / $width / $height) ** 0.5;
+    $width *= $scale;
+    $height *= $scale;
+  }
+
+  return ($width == $image->{width} && $height == $image->{height}, 
+         int($width), int($height));
+}
+
+# returns (width, height) as a list
+sub thumb_dimensions {
+  my ($self, $image_filename, $image, $max_width, $max_height, $max_pixels) = @_;
+
+  my $im = Imager->new();
+
+  # as long as we can read it
+  unless ($im->read(file=>$image_filename)) {
+    print STDERR "Error reading image '$image_filename' for thumb calculations: ",
+      $im->errstr,"\n";
+    return;
+  }
+
+
+  return $self->_width_height($image, $max_width, $max_height, $max_pixels);
+}
+
+# returns (content type, image data) as a list
+sub thumb_data {
+  my ($self, $image_filename, $image, $max_width, $max_height, 
+      $max_pixels) = @_;
+
+  my ($use_orig, $width, $height) = 
+    $self->_width_height($image, $max_width, $max_height, $max_pixels);
+
+  my $im = Imager->new();
+
+  unless ($im->read(file=>$image_filename)) {
+    print STDERR "Error reading image  '$image_filename' for thumb calculations: ",
+      $im->errstr,"\n";
+    return;
+  }
+
+  my $out;
+  if ($use_orig) {
+    $out = $im;
+  }
+  else {
+    $out = $im->scale(xpixels => $width, ypixels=>$height);
+  }
+
+  my $type = 'jpeg';
+  if ($image_filename =~ /\.(gif|png)$/i
+     || ($out->getchannels != 3 && $out->getchannels != 1)) {
+    $type = 'png';
+  }
+
+  my $data;
+  unless ($out->write(data => \$data, type=>$type)) {
+    print STDERR "Error writing: ",$out->errstr,"\n";
+  }
+
+  return ("image/$type", $data);
+}
+
+1;
index 4a7a657..ca579f1 100644 (file)
@@ -223,6 +223,8 @@ sub req_show {
   }
   $user
     or return $class->req_none($req, "Unknown user");
+  $user->{disabled}
+    and return $class->req_none($req, "User disabled");
   require BSE::TB::Subscriptions;
   my $subid = $cfg->entry('affiliate', 'subscription_required');
   if ($subid) {
index 8e389c6..aa83b44 100644 (file)
@@ -2,7 +2,7 @@ package BSE::UserReg;
 use strict;
 use base qw(BSE::UI::SiteuserCommon);
 use SiteUsers;
-use BSE::Util::Tags qw(tag_error_img);
+use BSE::Util::Tags qw(tag_error_img tag_hash);
 use BSE::Template;
 use Constants qw($SHOP_FROM);
 use BSE::Message;
@@ -886,6 +886,96 @@ sub userpage {
   BSE::Template->show_page($template, $cfg, \%acts, $base_template);
 }
 
+sub tag_detail_product {
+  my ($ritem, $products, $field) = @_;
+
+  $$ritem or return '';
+  my $product = $products->{$$ritem->{productId}}
+    or return '';
+
+  defined $product->{$field} or return '';
+
+  return escape_html($product->{$field});
+}
+
+sub iter_detail_productfiles {
+  my ($ritem, $files) = @_;
+
+  $$ritem or return;
+
+  grep $$ritem->{productId} == $_->{articleId}, @$files;
+}
+
+sub tag_detail_ifFileAvail {
+  my ($order, $rfile, $must_be_paid, $must_be_filled) = @_;
+
+  $$rfile or return 0;
+  $$rfile->{forSale} or return 1;
+
+  return 0 if $must_be_paid && !$order->{paidFor};
+  return 0 if $must_be_filled && !$order->{filled};
+
+  return 1;
+}
+
+sub req_orderdetail {
+  my ($self, $session, $cgi, $cfg, $message) = @_;
+
+  my $user = $self->_get_user($session, $cgi, $cfg, 'userpage')
+    or return;
+  my $order_id = $cgi->param('id');
+  my $order;
+  if (defined $order_id && $order_id =~ /^\d+$/) {
+    require BSE::TB::Orders;
+    $order = BSE::TB::Orders->getByPkey($order_id);
+  }
+  $order->{userId} eq $user->{userId} || $order->{siteuser_id} == $user->{id}
+    or undef $order;
+  $order
+    or return $self->userpage($session, $cgi, $cfg, "No such order");
+  $message ||= $cgi->param('message') || '';
+
+  my $must_be_paid = $cfg->entryBool('downloads', 'must_be_paid', 0);
+  my $must_be_filled = $cfg->entryBool('downloads', 'must_be_filled', 0);
+
+  my @items = $order->items;
+  my @files = $order->files;
+  my @products = $order->products;
+  my %products = map { $_->{id} => $_ } @products;
+  my $current_item;
+  my $current_file;
+
+  my $it = BSE::Util::Iterate->new;
+
+  my %acts;
+  %acts =
+    (
+     BSE::Util::Tags->basic(\%acts, $cgi, $cfg),
+     order => [ \&tag_hash, $order ],
+     $self->user_tags(\%acts, $session, $user),
+     message => sub { CGI::escapeHTML($message) },
+     $it->make_iterator
+     (undef, 'item', 'items', \@items, undef, undef, \$current_item),
+     $it->make_iterator
+     (undef, 'orderfile', 'orderfiles', \@files, undef, undef, \$current_file),
+     product => [ \&tag_detail_product, \$current_item, \%products ],
+     $it->make_iterator
+     ([ \&iter_detail_prodfiles, \$current_item, \@files ],
+      'prodfile', 'prodfiles', undef, undef, \$current_file),
+     ifFileAvail =>
+     [ \&tag_detail_ifFileAvail, $order, \$current_file, 
+       $must_be_paid, $must_be_filled ],
+    );
+
+  my $base_template = 'user/orderdetail';
+  my $template = $base_template;
+  my $t = $cgi->param('_t');
+  if (defined $t && $t =~ /^\w+$/) {
+    $template = $template . '_' . $t;
+  }
+  BSE::Template->show_page($template, $cfg, \%acts, $base_template);
+}
+
 sub download {
   my ($self, $session, $cgi, $cfg) = @_;
 
index f205ae5..b36ba70 100755 (executable)
@@ -40,6 +40,7 @@ my %actions =
    setcookie => 'set_cookie',
    nopassword => 'nopassword',
    a_image => 'req_image',
+   a_orderdetail => 'req_orderdetail',
   );
 
 my $cgi = CGI->new;
index 2e8cf6e..feac7e9 100644 (file)
@@ -20,3 +20,4 @@ standard.html
 BSE::UI::Affiliate.html
 affiliate.html
 future_plans.html
+thumbnails.html
index a0662e4..fce5343 100644 (file)
@@ -10,6 +10,40 @@ Maybe I'll add some other bits here.
 
 =head1 CHANGES
 
+=head2 0.14_33
+
+=over
+
+=item *
+
+user.pl now has an C<a_orderdetail> target which accepts the order
+number in C<id>.  The order must belong to the currently logged on
+user to be displayed.
+
+=item *
+
+affiliate.pl will no longer display pages for disabled users
+
+=item *
+
+the image manager will now display images as thumbnails if configured
+to do so.
+
+Currently the only imaging tool that can be used for the thumbnailing
+process is Imager.
+
+This adds the thumbimage, ifThumbs and ifCanThumbs tags to the article
+editor pages.
+
+See thumbnails.pod for more information.
+
+=item *
+
+localinst.perl (run with make testfiles) no longer deletes the content
+of your htdocs/images directory.
+
+=back
+
 =head2 0.14_32
 
 =over
index 1625f1e..1e3fef8 100644 (file)
@@ -1012,6 +1012,55 @@ Error message displayed if the image uses too much storage.
 
 =back
 
+=head2 [editor]
+
+Various editor settings.
+
+=over
+
+=item allow_thumb
+
+If this is non-zero the system will attempt to load the configured
+thumbnail class, and put thumbnail images on the image manager page
+rather than full-size images.  Default: off
+
+=item thumbs_class
+
+The name of a perl class that implement's BSE's thumbnail API.  At
+this point the only class that implements that is BSE::Thumb::Imager,
+supplied with BSE.  Default: None
+
+=item default_thumbnail
+
+URI to the default thumbnail image.  This is presented when the
+runtime production of a thumbnail image fails.
+
+=item default_thumbnail_width
+
+=item default_thumbnail_height
+
+Dimensions of the default thumbnail image.
+
+=item default_thumbnail_alt
+
+Alt text for the default thumbnail image.
+
+=back
+
+=head2 [thumbnails]
+
+=over
+
+=item max_width
+
+=item max_height
+
+=item max_pixels
+
+Default values for the thumbimage tag.
+
+=back
+
 =head2 [includes]
 
 Each value is used as the relative or absolute name of a file or
index 47fc717..bb57971 100644 (file)
@@ -28,6 +28,7 @@ my @targets =
    'affiliate.html',
    'BSE::UI::Affiliate.html',
    'future_plans.html',
+   'thumbnails.html',
   );
 
 my @exts = qw(.pod .pm .pl);
diff --git a/site/docs/thumbnails.pod b/site/docs/thumbnails.pod
new file mode 100644 (file)
index 0000000..eed4423
--- /dev/null
@@ -0,0 +1,72 @@
+=head1 NAME
+
+thumbnails.pod - thumbnail images for BSE's image manager
+
+=head1 SYNOPSIS
+
+How to configure thumbnails for BSE image manager.
+
+=head1 DESCRIPTION
+
+If configured, the image manager will display thumbnails for each of
+the images attached to the article instead of displaying the images
+fullsize inline.
+
+If you don't want thumbnail make sure you configure them off or supply
+the C<f_showfull> parameter, since some processing is done whenever a
+<:thumbimage:> tag is seen, even if that tag is on the false side of
+an <:if ...:>.
+
+=head1 INSTALLATION
+
+You will need to install the perl Imager package, it's possible your
+operating system includes packages for this module.
+
+Otherwise install Imager from CPAN:
+
+=over
+
+=item 1
+
+install the libraries that Imager depends on, this is at least
+libjpeg, libgif (or libungif) and libpng.  You can also install
+libtiff, but this shouldn't be necessary, since TIFF isn't a common
+web format.
+
+All of these libraries are usually available in your operating
+system's packaging system, or are preinstalled.
+
+=item 2
+
+install Imager, as root:
+
+  perl -MCPAN -eshell
+  # you may be prompted here if you haven't run the shell before
+  > install Imager
+
+=back
+
+If you have problems with the tiff tests for Imager, you will need to
+either disable tiff support in Imager, or use the following tiff.c:
+
+  http://www.develop-help.com/imager/src/tiff.c
+
+Once you have Imager installed, add the following to bse.cfg (or
+bse-local.cfg):
+
+[editor]
+allow_thumb=1
+thumbs_class=BSE::Thumb::Imager
+
+If you don't see thumbnails on the image manager page, check your
+server error log file for error messages.
+
+=head1 AUTHOR
+
+Tony Cook <tony@develop-help.com>
+
+=head1 REVISION
+
+$Revision$
+
+=cut
index 9284262..fb8bfce 100644 (file)
 <:case default:><a href="/cgi-bin/admin/add.pl?id=<:article id:>"><:ifMatch
     [article generator] "Catalog":>Edit catalog<:or:>Edit article<:eif:></a>
 <:endswitch:>
-|</p><:if UserCan edit_images_add:article:>
+|
+<:if Thumbs:><a href="<:script:>?id=<:article id:>&amp;_t=img&amp;f_showfull=1">Full size images</a> |<:or Thumbs:><:ifCanThumbs:><a href="<:script:>?id=<:article id:>&amp;_t=img">With Thumbnails</a> |<:or:><:eif:><:eif Thumbs:>
+</p>
+<:if UserCan edit_images_add:article:>
 <h2>Add new image</h2>
 
 <form method="post" action="<:script:>" enctype="multipart/form-data" name="add">
 
            </td>
           </tr><:eif Eq:>
+<:if Thumbs:>
+          <tr bgcolor="#FFFFFF"> 
+            <th>Image</th>
+            <th colspan="2"> &nbsp;</th>
+            <th nowrap="nowrap"> Modify</th>
+           <th nowrap="nowrap"> Move</th>
+          </tr>
+<:iterator begin images:>
+       <tr>
+          <td rowspan="3" align="center" valign="center" bgcolor="#FFFFFF"><a href="#" onclick="window.open('/images/<:image image:>', 'fullimage', 'width=<:arithmetic [image width]+20:>,height=<:arithmetic [image height]+30:>,location=no,status=no,menubar=no,scrollbars=yes'); return 0;"><:thumbimage 150 150:></a></th>
+           <th>Alt text:</th>
+            <td valign="top" bgcolor="#FFFFFF"> 
+              <:ifUserCan edit_images_save:article:><input type="text" name="alt" value="<: image alt :>" size="32" /><:or:><: image alt :><:eif:>
+            </td>
+            <td valign="top" nowrap="nowrap" rowspan="3" bgcolor="#FFFFFF"> 
+              <:ifUserCan edit_images_delete:article:><b><a href="<:script:>?id=<:article id:>&removeimg_<: image id :>=1&_t=img" onClick="return window.confirm('Are you sure you want to delete this Image')">Delete</a></b><:or:><:eif:></td>
+            <td nowrap="nowrap" bgcolor="#FFFFFF" rowspan="3"><:imgmove:></td>
+         </tr>
+         <tr>        
+            <th>URL:</th>
+            <td valign="top" width="50%"  bgcolor="#FFFFFF"colspan="1"> 
+              <:ifUserCan edit_images_save:article:><input type="text" name="url" value="<: image url :>" size="32" /><:or:><: image url :><:eif:>
+            </td>
+          </tr>
+          <tr>
+           <th>Identifier:</th>
+            <td valign="top" nowrap="nowrap"  bgcolor="#FFFFFF"colspan="1"> 
+              <:ifUserCan edit_images_save:article:><input type="text" name="name<:image_index:>" value="<: image name :>" size="32" /> <:error_img [concatenate "name" [image_index] ]:><:or:><: image name :><:eif:>
+            </td>
+        </tr>
+<:iterator end images:>          
+<:or Thumbs:>
           <tr bgcolor="#FFFFFF"> 
             <th colspan="5">Image</th>
           </tr>
             <td colspan="5">&nbsp;</td>
           </tr>
           <: iterator end images :> 
+<:eif Thumbs:>
 <:ifUserCan edit_images_save:article:>
           <tr> 
             <td align="right" bgcolor="#FFFFFF" colspan="5"> 
diff --git a/site/templates/user/base_orderdetail.tmpl b/site/templates/user/base_orderdetail.tmpl
new file mode 100644 (file)
index 0000000..66370a5
--- /dev/null
@@ -0,0 +1,74 @@
+<:wrap base.tmpl:> 
+<div align="center"> 
+<h1>Order Detail: <:order id:></h1>
+<p><a href="<:script:>?userpage=1">Back to order list</a></p>
+   
+  <table width="100%" cellpadding="0" cellspacing="1">
+       <:if Message:> 
+    <tr> 
+      <th  align="center"><b><font face="Verdana, Arial, Helvetica, sans-serif" size="2"><:message:></font></b></th>
+    </tr>
+    <:or Message:><:eif Message:> 
+    <tr> 
+      <td bgcolor="#CCCCCC"> <table width="100%" cellpadding="3" cellspacing="1">
+          <tr> 
+            <th align="center" nowrap width="25%" bgcolor="#666666"><font face="Verdana, Arial, Helvetica, sans-serif" size="2" color="#CCCCCC">Order 
+              No:</font><font face="Verdana, Arial, Helvetica, sans-serif" size="2" color="#FFFFFF"> 
+              <:order id:></font></th>
+            <th align="center" width="25%" nowrap bgcolor="#666666"><font face="Verdana, Arial, Helvetica, sans-serif" size="2" color="#CCCCCC">Date:</font><font face="Verdana, Arial, Helvetica, sans-serif" size="2" color="#FFFFFF"> 
+              <:date order orderDate:></font></th>
+            <th align="center" width="25%" nowrap bgcolor="<:ifOrder filled:>#CC0033<:or:>#66CC00<:eif:>"><font face="Verdana, Arial, Helvetica, sans-serif" size="2" color="<:ifOrder filled:>#CCCCCC<:or:>#000000<:eif:>">Status:</font><font face="Verdana, Arial, Helvetica, sans-serif" size="2" color="#FFFFFF"> 
+              <:ifOrder filled:>Complete<:or:>Processing<:eif:></font></th>
+            <th align="center" width="25%" nowrap bgcolor="#FF7F00"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Total:</font><font face="Verdana, Arial, Helvetica, sans-serif" size="2" color="#FFFFFF"> 
+              $<:money order total:></font></th>
+          </tr>
+        </table>
+        <:if Items:> <table width="100%" cellpadding="3" cellspacing="1">
+          <tr bgcolor="#EEEEEE"> 
+            <th width="100%" align="left"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Product</font></th>
+            <th><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Quantity</font></th>
+            <th><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Unit</font></th>
+          </tr>
+          <:iterator begin items:> 
+          <tr bgcolor="#FFFFFF"> 
+            <td width="100%"><a href="<:product link:>"><font face="Verdana, Arial, Helvetica, sans-serif" size="2"><:product 
+              summary:></font></a></td>
+            <td align="center"><font face="Verdana, Arial, Helvetica, sans-serif" size="2"><:item 
+              units:></font></td>
+            <td align="right"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">$<:money 
+              item price:></font></td>
+          </tr>
+          <:iterator end items:> 
+        </table>
+        <:if Orderfiles:> <table width="100%" cellpadding="3" cellspacing="1">
+          <tr bgcolor="#CCCCCC"> 
+            <th colspan="4"><font face="Verdana, Arial, Helvetica, sans-serif" size="2" color="#666666"><:if 
+              Order filled:>Files available<:or Order:><:ifCfg downloads must_be_filled:>Files 
+              available when order status is &#145;Complete&#146;<:or:>Files<:eif:><:eif 
+              Order:></font></th>
+          </tr>
+          <tr bgcolor="#EEEEEE"> 
+            <th width="50%" align="left"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Description</font></th>
+            <th nowrap width="50%" align="left" colspan="2"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">File</font></th>
+            <th><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Size</font></th>
+          </tr>
+          <:iterator begin orderfiles:> 
+          <tr bgcolor="#FFFFFF"> 
+            <td width="50%"><font face="Verdana, Arial, Helvetica, sans-serif" size="2"><:orderfile 
+              description:></font></td>
+            <td nowrap width="50%"><font face="Verdana, Arial, Helvetica, sans-serif" size="2"><:if 
+              FileAvail:><a href="/cgi-bin/user.pl?download=1&file=<:orderfile id:>&order=<:order id:>&item=<:orderfile item_id:>"><:orderfile 
+              displayName:></a><:or FileAvail:><:orderfile displayName:><:eif 
+              FileAvail:></font></td>
+            <td><:if FileAvail:><a href="/cgi-bin/user.pl?download=1&file=<:orderfile id:>&order=<:order id:>&item=<:orderfile item_id:>"><img src="/images/filestatus/download.gif" width="15" height="15" alt="Download now" title="Download now" border="0"></a><:or 
+              FileAvail:><img src="/images/filestatus/locked.gif" width="15" height="15" alt="Locked" title="Locked"><:eif 
+              FileAvail:></td>
+            <td align="right"><font face="Verdana, Arial, Helvetica, sans-serif" size="2"><:kb 
+              orderfile sizeInBytes:></font></td>
+          </tr>
+          <:iterator end orderfiles:> 
+        </table>
+        <:or Orderfiles:><:eif Orderfiles:> <:or Items:><:eif Items:> </td>
+    </tr>
+  </table>
+</div>
index e52b1fa..2e18679 100644 (file)
@@ -53,9 +53,9 @@
     <tr> 
       <td bgcolor="#CCCCCC"> <table width="100%" cellpadding="3" cellspacing="1">
           <tr> 
-            <th align="center" nowrap width="25%" bgcolor="#666666"><font face="Verdana, Arial, Helvetica, sans-serif" size="2" color="#CCCCCC">Order 
+            <th align="center" nowrap width="25%" bgcolor="#666666"><a href="<:script:>?a_orderdetail=1&amp;id=<:order id:>"><font face="Verdana, Arial, Helvetica, sans-serif" size="2" color="#CCCCCC">Order 
               No:</font><font face="Verdana, Arial, Helvetica, sans-serif" size="2" color="#FFFFFF"> 
-              <:order id:></font></th>
+              <:order id:></font></a></th>
             <th align="center" width="25%" nowrap bgcolor="#666666"><font face="Verdana, Arial, Helvetica, sans-serif" size="2" color="#CCCCCC">Date:</font><font face="Verdana, Arial, Helvetica, sans-serif" size="2" color="#FFFFFF"> 
               <:date order orderDate:></font></th>
             <th align="center" width="25%" nowrap bgcolor="<:ifOrder filled:>#CC0033<:or:>#66CC00<:eif:>"><font face="Verdana, Arial, Helvetica, sans-serif" size="2" color="<:ifOrder filled:>#CCCCCC<:or:>#000000<:eif:>">Status:</font><font face="Verdana, Arial, Helvetica, sans-serif" size="2" color="#FFFFFF"> 
index 196e919..62b8946 100644 (file)
--- a/test.cfg
+++ b/test.cfg
@@ -87,4 +87,7 @@ debug.dump_session=0
 
 bse siteuser images.logo=1
 bse siteuser image logo.description=Your Logo
-affiliate.subscription_required=affiliatepage
\ No newline at end of file
+affiliate.subscription_required=affiliatepage
+
+editor.allow_thumb=1
+editor.thumbs_class=BSE::Thumb::Imager