0.10_07 prerelease r0_10_07
authorTony Cook <tony@develop-help.com>
Thu, 8 Nov 2001 22:30:40 +0000 (22:30 +0000)
committertony <tony@45cb6cf1-00bc-42d2-bb5a-07f51df49f94>
Thu, 8 Nov 2001 22:30:40 +0000 (22:30 +0000)
43 files changed:
MANIFEST
Makefile
schema/bse.sql
site/cgi-bin/admin/add.pl
site/cgi-bin/admin/move.pl
site/cgi-bin/admin/reorder.pl
site/cgi-bin/admin/shopadmin.pl
site/cgi-bin/modules/Article.pm
site/cgi-bin/modules/BSE/Admin/StepParents.pm [new file with mode: 0644]
site/cgi-bin/modules/BSE/Custom.pm
site/cgi-bin/modules/BSE/CustomBase.pm
site/cgi-bin/modules/BSE/DB/Mysql.pm
site/cgi-bin/modules/BSE/Util/SQL.pm [new file with mode: 0644]
site/cgi-bin/modules/BSE/Util/Valid.pm [new file with mode: 0644]
site/cgi-bin/modules/Constants.pm
site/cgi-bin/modules/Generate.pm
site/cgi-bin/modules/Generate/Catalog.pm
site/cgi-bin/modules/Generate/Product.pm
site/cgi-bin/modules/OtherParent.pm [new file with mode: 0644]
site/cgi-bin/modules/OtherParents.pm [new file with mode: 0644]
site/cgi-bin/modules/Squirrel/Table.pm
site/docs/TODO.pod
site/docs/bse.pod
site/templates/admin/add_product.tmpl
site/templates/admin/article_img.tmpl
site/templates/admin/edit_0.tmpl
site/templates/admin/edit_1.tmpl
site/templates/admin/edit_2.tmpl
site/templates/admin/edit_catalog.tmpl
site/templates/admin/edit_product.tmpl
site/templates/common/default.tmpl
site/templates/common/embedded_subsect.tmpl
site/templates/common/news_item.tmpl
site/templates/common/sidebar.tmpl
site/templates/common/sidebar_section.tmpl
site/templates/index2.tmpl
site/templates/menu/menu.tmpl [new file with mode: 0644]
site/templates/menu/menu1.tmpl [new file with mode: 0644]
site/templates/menu/menu2.tmpl [new file with mode: 0644]
site/templates/menu/menu3.tmpl [new file with mode: 0644]
site/templates/menu/menu4.tmpl [new file with mode: 0644]
site/templates/menu/menu5.tmpl [new file with mode: 0644]
site/util/initial.pl

index a548280..e230fed 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -30,6 +30,7 @@ site/cgi-bin/modules/Constants.pm
 #site/cgi-bin/modules/Constants.tmpl
 site/cgi-bin/modules/BSE/Custom.pm
 site/cgi-bin/modules/BSE/CustomBase.pm
+site/cgi-bin/modules/BSE/Admin/StepParents.pm
 site/cgi-bin/modules/BSE/DB.pm
 site/cgi-bin/modules/BSE/DB/Mysql.pm
 site/cgi-bin/modules/BSE/DB/MSSQL.pm
@@ -37,6 +38,8 @@ site/cgi-bin/modules/BSE/Mail.pm
 site/cgi-bin/modules/BSE/Mail/Sendmail.pm
 site/cgi-bin/modules/BSE/Mail/SMTP.pm
 site/cgi-bin/modules/BSE/Sort.pm
+site/cgi-bin/modules/BSE/Util/SQL.pm
+site/cgi-bin/modules/BSE/Util/Valid.pm
 #site/cgi-bin/modules/DatabaseHandle.pm    obsolete
 site/cgi-bin/modules/Generate.pm
 site/cgi-bin/modules/Generate/Article.pm
@@ -137,19 +140,25 @@ site/templates/admin/order_list_unfilled.tmpl
 site/templates/admin/product_detail.tmpl
 site/templates/admin/product_list.tmpl
 site/templates/admin/regenerror.tmpl
+site/templates/common/rssbase.tmpl
 site/templates/error.tmpl
 site/templates/extras.txt
+site/templates/include/rsslinks.tmpl
+site/templates/include/rssitems.tmpl
 site/templates/index.tmpl
 site/templates/index2.tmpl
 site/templates/lowmap.tmpl
 site/templates/mailconfirm.tmpl
 site/templates/mailorder.tmpl
+site/templates/menu/menu.tmpl
+site/templates/menu/menu1.tmpl
+site/templates/menu/menu2.tmpl
+site/templates/menu/menu3.tmpl
+site/templates/menu/menu4.tmpl
+site/templates/menu/menu5.tmpl
+site/templates/printable/printable.tmpl
 site/templates/search_base.tmpl
 site/templates/shop_help.tmpl
 site/templates/shop_sect.tmpl
 site/templates/shopitem.tmpl
-site/templates/common/rssbase.tmpl
-site/templates/include/rsslinks.tmpl
-site/templates/include/rssitems.tmpl
-site/templates/printable/printable.tmpl
 site/util/initial.pl
index a8f7c5f..f3c66cb 100755 (executable)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-VERSION=0.10_05
+VERSION=0.10_07
 DISTNAME=bse-$(VERSION)
 DISTBUILD=$(DISTNAME)
 DISTTAR=../$(DISTNAME).tar
index 1c5eb0a..0023da0 100644 (file)
@@ -229,7 +229,10 @@ create table other_parents (
   -- order as seen from the child
   childDisplayOrder integer not null,
 
+  release datetime default '0000-00-00 00:00:00' not null,
+  expire datetime default '9999-12-31 23:59:59' not null,
+
   primary key(id),
   unique (parentId, childId),
-  index (childId)
+  index (childId, childDisplayOrder)
 );
\ No newline at end of file
index 2fcec97..24d3017 100755 (executable)
@@ -1,11 +1,11 @@
-#!/usr/bin/perl -w
-# -d:ptkdb
+#!/usr/bin/perl -w 
+#-d:ptkdb
 #BEGIN { $ENV{DISPLAY} = '192.168.32.97:0.0'; }
 
 use strict;
 use FindBin;
 use lib "$FindBin::Bin/../modules";
-use Constants qw(:edit :session);
+use Constants qw(:edit :session $CGI_URI $IMAGES_URI);
 
 use Articles;
 use Article;
@@ -66,6 +66,9 @@ my %steps =
   (
    save=>\&save,
    remove=>\&remove,
+   add_stepkid=>\&add_stepkid,
+   del_stepkid=>\&del_stepkid,
+   save_stepkids => \&save_stepkids,
   );
 
 my $level = param('level') || 3;
@@ -141,7 +144,7 @@ $parent = $articles->getByPkey($article->{parentid})
   if $article && $article->{parentid} && $article->{parentid} > 0;
 
 my @images;
-my $message = ''; # for displaying error message
+my $message = param('message') || ''; # for displaying error message
 my @children;
 if (defined $id) {
   @children = sort { #$b->{listed} <=> $a->{listed} ||
@@ -200,6 +203,13 @@ unless ($level_cache{$level}{edit}) {
     $levels{$level}{edit};
 }
 
+use OtherParents;
+my @stepkids = OtherParents->getBy(parentId=>$article->{id}) if $article->{id};
+my %stepkids = map { $_->{childId} => $_ } @stepkids;
+my @allkids = $article->allkids if $article->{id};
+my $allkids_index = -1;
+my @possibles;
+
 my $child_index = -1;
 %acts =
   (
@@ -270,6 +280,67 @@ HTML
    },
    edit => \&edit_link,
    adminMenu => sub { $ROOT_URI . "admin/"; },
+   iterate_kids_reset => sub { $allkids_index = -1 },
+   iterate_kids => sub { ++$allkids_index < @allkids },
+   ifKids => sub { @allkids },
+   kid => 
+   sub { 
+     my $value = $allkids[$allkids_index]{$_[0]};
+     defined $value or $value = '';
+     CGI::escapeHTML($value)
+   },
+   ifStepKid => sub { exists $stepkids{$allkids[$allkids_index]{id}} },
+   stepkid =>
+   sub {
+     my $value = $stepkids{$allkids[$allkids_index]{id}}{$_[0]};
+     defined $value or $value = '';
+     CGI::escapeHTML($value);
+   },
+   movestepkid =>
+   sub {
+     my $html = '';
+     my $refreshto = CGI::escape($ENV{SCRIPT_NAME}
+                                ."?id=$article->{id}#step");
+     if ($allkids_index < $#allkids) {
+       $html .= <<HTML
+<a href="$CGI_URI/admin/move.pl?stepparent=$article->{id}&d=swap&id=$allkids[$allkids_index]{id}&other=$allkids[$allkids_index+1]{id}&refreshto=$refreshto"><img src="$IMAGES_URI/admin/move_down.gif" width="17" height="13" border="0" alt="Move Down" align="absbottom"></a>
+HTML
+     }
+     if ($allkids_index > 0) {
+       $html .= <<HTML
+<a href="$CGI_URI/admin/move.pl?stepparent=$article->{id}&d=swap&id=$allkids[$allkids_index]{id}&other=$allkids[$allkids_index-1]{id}&refreshto=$refreshto"><img src="$IMAGES_URI/admin/move_up.gif" width="17" height="13" border="0" alt="Move Up" align="absbottom"></a>
+HTML
+     }
+     return $html;
+   },
+   date =>
+   sub {
+     my ($func, $args) = split ' ', $_[0], 2;
+     $acts{$func} or return "** function $func not defined **";
+     use BSE::Util::SQL qw/sql_to_date/;
+     sql_to_date($acts{$func}->($args));
+   },
+   possible_stepkids =>
+   sub {
+     @possibles =
+       sort { $a->{title} cmp $b->{title} }
+       grep $_->{generator} eq 'Generate::Product' && !$stepkids{$_->{id}},
+       $articles->all()
+        unless @possibles;
+     my %labels = map { $_->{id}, "$_->{title} ($_->{id})" } @possibles;
+     CGI::popup_menu(-name=>'stepkid',
+                    -values => [ map $_->{id}, @possibles ],
+                    -labels => \%labels);
+   },
+   ifPossibles =>
+   sub {
+     @possibles =
+       sort { $a->{title} cmp $b->{title} }
+       grep $_->{generator} eq 'Generate::Product' && !$stepkids{$_->{id}},
+       $articles->all()
+        unless @possibles;
+     @possibles;
+   },
   );
 
 if ($imageEditor->action($CGI::Q)) {
@@ -508,6 +579,13 @@ sub remove {
       unlink("$IMAGEDIR/$image->{image}");
       $image->remove();
     }
+
+    # remove any step(child|parent) links
+    require 'OtherParents.pm';
+    my @steprels = OtherParents->anylinks($deleteid);
+    for my $link (@steprels) {
+      $link->remove();
+    }
     
     $delart->remove();
     $articles = Articles->new(1);
@@ -518,6 +596,105 @@ sub remove {
   }
 }
 
+sub add_stepkid {
+  require 'BSE/Admin/StepParents.pm';
+  eval {
+    my $childId = param('stepkid');
+    defined $childId
+      or die "No stepkid supplied to add_stepkid";
+    int($childId) eq $childId
+      or die "Invalid stepkid supplied to add_stepkid";
+    require 'Products.pm';
+    my $child = Products->getByPkey($childId)
+      or die "Product $childId not found";
+    
+    my $release = param('release');
+    defined $release
+      or $release = "01/01/2000";
+    use BSE::Util::Valid qw/valid_date/;
+    $release eq '' or valid_date($release)
+      or die "Invalid release date";
+    my $expire = param('expire');
+    defined $expire
+      or $expire = '31/12/2999';
+    $expire eq '' or valid_date($expire)
+      or die "Invalid expire data";
+  
+    my $newentry = 
+      BSE::Admin::StepParents->add($article, $child, $release, $expire);
+  };
+  if ($@) {
+    $message = $@;
+    return start();
+  }
+  print "Refresh: 0; url=\"$URLBASE$ENV{SCRIPT_NAME}?id=$article->{id}#step\"\n";
+  print "Content-type: text/html\n\n<HTML></HTML>\n";
+}
+
+sub del_stepkid {
+  require 'BSE/Admin/StepParents.pm';
+
+  my $childId = param('stepkid');
+  defined $childId
+    or die "No stepkid supplied to add_stepkid";
+  int($childId) eq $childId
+    or die "Invalid stepkid supplied to add_stepkid";
+  require 'Products.pm';
+  my $child = Products->getByPkey($childId)
+    or die "Product $childId not found";
+    
+  eval {
+    BSE::Admin::StepParents->del($article, $child);
+  };
+  
+  if ($@) {
+    $message = $@;
+    return start();
+  }
+  refresh('step');
+}
+
+sub save_stepkids {
+  require 'BSE/Admin/StepParents.pm';
+  my @stepcats = OtherParents->getBy(parentId=>$article->{id});
+  my %stepcats = map { $_->{parentId}, $_ } @stepcats;
+  my %datedefs = ( release => '2000-01-01', expire=>'2999-12-31' );
+  for my $stepcat (@stepcats) {
+    for my $name (qw/release expire/) {
+      my $date = param($name.'_'.$stepcat->{childId});
+      if (defined $date) {
+       if ($date eq '') {
+         $date = $datedefs{$name};
+       }
+       elsif (valid_date($date)) {
+         use BSE::Util::SQL qw/date_to_sql/;
+         $date = date_to_sql($date);
+       }
+       else {
+         return refresh('', "Invalid date '$date'");
+       }
+       $stepcat->{$name} = $date;
+      }
+    }
+    eval {
+      $stepcat->save();
+    };
+    $@ and return refresh('', $@);
+  }
+  refresh('step');
+}
+
+sub refresh {
+  my ($name, $message) = @_;
+
+  my $url = "$URLBASE$ENV{SCRIPT_NAME}?id=$article->{id}";
+  $url .= "&message=" . CGI::escape($message) if $message;
+  $url .= "#$name" if $name;
+
+  print "Refresh: 0; url=\"$url\"\n";
+  print "Content-type: text/html\n\n<HTML></HTML>\n";
+}
+
 sub page {
   my ($page) = @_;
   print header, Squirrel::Template->new->show_page($TMPLDIR, $page, \%acts);
index b3f9aba..1517d47 100755 (executable)
@@ -15,62 +15,110 @@ my $id = param('id');
 my $direction = param('d');
 
 my $articles = Articles->new;
+  
+my $article;
+if (defined param('stepchild')) {
+  # we always need a swap for this one
+  my $stepchild = param('stepchild');
 
-my $article = $articles->getByPkey($id)
-  or die "Could not find article $id";
+  my $article = Articles->getByPkey($stepchild)
+    or die "Cannot find child $stepchild";
 
-# get our siblings, in order
-my @siblings;
-if (param('all')) {
-  @siblings = sort { $b->{displayOrder} <=> $a->{displayOrder} }
-                      $articles->children($article->{parentid});
-}
-else {
-  @siblings = $articles->listedChildren($article->{parentid});
-}
+  my $other = param('other');
 
-# find our article
-my $index;
-for ($index = 0; $index < @siblings; ++$index) {
-  last if $siblings[$index]{id} == $id;
+  require 'OtherParents.pm';
+  my $one = OtherParents->getBy(parentId=>$id, childId=>$stepchild)
+    or die "Cannot find link between child $stepchild and parent $id";
+  my $two = OtherParents->getBy(parentId=>$other, childId=>$stepchild)
+    or die "Cannot find link between child $stepchild and parent $other";
+  ($one->{childDisplayOrder}, $two->{childDisplayOrder}) =
+    ($two->{childDisplayOrder}, $one->{childDisplayOrder});
+  $one->save;
+  $two->save;
+  use Util 'generate_article';
+  generate_article('Articles', $article);
 }
+elsif (defined param('stepparent')) {
+  require 'OtherParents.pm';
 
-die "This program is broken - couldn't find self in list of parents children"
-  if $index == @siblings;
-
-if ($direction eq 'down') {
-  die "There is no next article to swap with"
-    if $index == $#siblings;
-  ($article->{displayOrder}, $siblings[$index+1]{displayOrder})
-    = ($siblings[$index+1]{displayOrder}, $article->{displayOrder});
-  $siblings[$index+1]->save();
+  my $stepparent = param('stepparent');
+  my $other = param('other');
+  my $onename = 'parentDisplayOrder';
+  my $one = OtherParents->getBy(parentId=>$stepparent, childId=>$id);
+  unless ($one) {
+    $onename = 'displayOrder';
+    $one = Articles->getByPkey($id)
+      or die "Could not find article $id";
+  }
+  my $twoname = 'parentDisplayOrder';
+  my $two = OtherParents->getBy(parentId=>$stepparent, childId=>$other);
+  unless ($two) {
+    $twoname = 'displayOrder';
+    $two = Articles->getByPkey($other)
+      or die "Could not find article $other";
+  }
+  ($one->{$onename}, $two->{$twoname}) = ($two->{$twoname}, $one->{$onename});
+  $one->save;
+  $two->save;
+  use Util 'generate_article';
+  generate_article('Articles', $article);
 }
-elsif ($direction eq 'up') {
-  die "There is no previous article to swap with"
-    if $index == 0;
-  ($article->{displayOrder}, $siblings[$index-1]{displayOrder})
-    = ($siblings[$index-1]{displayOrder}, $article->{displayOrder});
-  $siblings[$index-1]->save();
+else {
+  $article = $articles->getByPkey($id)
+    or die "Could not find article $id";
   
-}
-elsif ($direction eq 'swap') {
-  my $other = param('other')
-    or die "Need to specify an 'other' article to swap with";
-  my ($other_index) = grep $siblings[$_]{id} == $other, 0..$#siblings;
-  defined $other_index or die "No such such sibling";
+  # get our siblings, in order
+  my @siblings;
+  if (param('all')) {
+    @siblings = sort { $b->{displayOrder} <=> $a->{displayOrder} }
+      $articles->children($article->{parentid});
+  }
+  else {
+    @siblings = $articles->listedChildren($article->{parentid});
+  }
   
-  ($article->{displayOrder}, $siblings[$other_index]{displayOrder})
-    = ($siblings[$other_index]{displayOrder}, $article->{displayOrder});
-  $siblings[$other_index]->save();
-}
-else {
-  die "Sorry, can't move articles sideways";
-}
-
-$article->save();
-use Util 'generate_article';
-generate_article('Articles', $article);
+  # find our article
+  my $index;
+  for ($index = 0; $index < @siblings; ++$index) {
+    last if $siblings[$index]{id} == $id;
+  }
+  
+  die "This program is broken - couldn't find self in list of parents children"
+    if $index == @siblings;
+  
+  if ($direction eq 'down') {
+    die "There is no next article to swap with"
+      if $index == $#siblings;
+    ($article->{displayOrder}, $siblings[$index+1]{displayOrder})
+      = ($siblings[$index+1]{displayOrder}, $article->{displayOrder});
+    $siblings[$index+1]->save();
+  }
+  elsif ($direction eq 'up') {
+    die "There is no previous article to swap with"
+      if $index == 0;
+    ($article->{displayOrder}, $siblings[$index-1]{displayOrder})
+      = ($siblings[$index-1]{displayOrder}, $article->{displayOrder});
+    $siblings[$index-1]->save();
+    
+  }
+  elsif ($direction eq 'swap') {
+    my $other = param('other')
+      or die "Need to specify an 'other' article to swap with";
+    my ($other_index) = grep $siblings[$_]{id} == $other, 0..$#siblings;
+    defined $other_index or die "No such such sibling";
+    
+    ($article->{displayOrder}, $siblings[$other_index]{displayOrder})
+      = ($siblings[$other_index]{displayOrder}, $article->{displayOrder});
+    $siblings[$other_index]->save();
+  }
+  else {
+    die "Sorry, can't move articles sideways";
+  }
 
+  $article->save();
+  use Util 'generate_article';
+  generate_article('Articles', $article);
+}
 
 if (param('refreshto')) {
   print "Refresh: 0; url=\"$URLBASE",param('refreshto'),"\"\n";
index a0c6c21..305dcf4 100755 (executable)
@@ -1,4 +1,6 @@
-#!/usr/bin/perl -w
+#!/usr/bin/perl -w 
+#-d:ptkdb
+#BEGIN { $ENV{DISPLAY}="192.168.32.97:0.0"; };
 use strict;
 use FindBin;
 use lib "$FindBin::Bin/../modules";
index a7c8159..48068ff 100755 (executable)
@@ -78,6 +78,9 @@ my %what_to_do =
    delete_product=>\&delete_product,
    undelete_product=>\&undelete_product,
    product_detail=>\&product_detail,
+   add_stepcat=>\&add_stepcat,
+   del_stepcat=>\&del_stepcat,
+   save_stepcats => \&save_stepcats,
    back=>\&img_return,
   );
 
@@ -187,7 +190,7 @@ sub product_list {
   my @catalogs = sort { $b->{displayOrder} <=> $a->{displayOrder} }
     Articles->children($SHOPID);
   my $catalog_index = -1;
-  my $message = param('message') || '';
+  my $message = param('message') || shift || '';
   my %acts =
     (
      catalog=> sub { CGI::escapeHTML($catalogs[$catalog_index]{$_[0]}) },
@@ -435,7 +438,7 @@ sub product_detail {
 sub product_form {
   my ($product, $action, $message, $template) = @_;
 
-  defined($message) or $message = '';
+  $message ||= param('message') || '';
   $template ||= 'add_product';
   my @catalogs;
   my @work = [ $SHOPID, '' ];
@@ -458,6 +461,13 @@ sub product_form {
       grep -f "$TMPLDIR/products/$_" && /\.tmpl$/i, readdir PROD_TEMPL;
     closedir PROD_TEMPL;
   }
+  my $stepcat_index;
+  use OtherParents;
+  my @stepcats = OtherParents->getBy(childId=>$product->{id}) 
+    if $product->{id};
+  my @stepcat_targets = $product->step_parents if $product->{id};
+  my %stepcat_targets = map { $_->{id}, $_ } @stepcat_targets;
+  my @stepcat_possibles = grep !$stepcat_targets{$_->{id}}, @catalogs;
 
   my %acts;
   %acts =
@@ -471,7 +481,7 @@ sub product_form {
                          -override=>1);
      },
      product => sub { CGI::escapeHTML($product->{$_[0]}) },
-     date => sub { display_date($product->{$_[0]}) },
+     #date => sub { display_date($product->{$_[0]}) },
      money => sub { sprintf("%.2f", $product->{$_[0]}/100.0) },
      action => sub { $action },
      message => sub { $message },
@@ -486,6 +496,44 @@ sub product_form {
                               -default=>$product->{id} ? $product->{template} :
                               $templates[0]);
      },
+     ifStepcats => sub { @stepcats },
+     iterate_stepcats_reset => sub { $stepcat_index = -1; },
+     iterate_stepcats => sub { ++$stepcat_index < @stepcats },
+     stepcat => sub { CGI::escapeHTML($stepcats[$stepcat_index]{$_[0]}) },
+     stepcat_targ =>
+     sub {
+       CGI::escapeHTML($stepcat_targets[$stepcat_index]{$_[0]});
+     },
+     movestepcat =>
+     sub {
+       my $html = '';
+       my $refreshto = CGI::escape($ENV{SCRIPT_NAME}
+                                  ."?id=$product->{id}&$template=1#step");
+       if ($stepcat_index < $#stepcats) {
+        $html .= <<HTML;
+<a href="$CGI_URI/admin/move.pl?stepchild=$product->{id}&id=$stepcats[$stepcat_index]{parentId}&d=swap&other=$stepcats[$stepcat_index+1]{parentId}&refreshto=$refreshto&all=1"><img src="$IMAGES_URI/admin/move_down.gif" width="17" height="13" border="0" alt="Move Down" align="absbottom"></a>
+HTML
+       }
+       if ($stepcat_index > 0) {
+        $html .= <<HTML;
+<a href="$CGI_URI/admin/move.pl?stepchild=$product->{id}&id=$stepcats[$stepcat_index]{parentId}&d=swap&other=$stepcats[$stepcat_index-1]{parentId}&refreshto=$refreshto&all=1"><img src="$IMAGES_URI/admin/move_up.gif" width="17" height="13" border="0" alt="Move Up" align="absbottom"></a>
+HTML
+       }
+       return $html;
+     },
+     ifStepcatPossibles => sub { @stepcat_possibles },
+     stepcat_possibles => sub {
+       popup_menu(-name=>'stepcat',
+                 -values=>[ map $_->{id}, @stepcat_possibles ],
+                 -labels=>{ map { $_->{id}, $_->{display}} @catalogs });
+     },
+     date =>
+     sub {
+       use BSE::Util::SQL qw/sql_to_date/;
+       my ($func, $args) = split ' ', $_[0], 2;
+       $acts{$func} or return "** unknown function '$func' $args **";
+       display_date($acts{$func}->($args));
+     },
     );
 
   page($template, \%acts);
@@ -687,10 +735,126 @@ sub order_filled {
   }
 }
 
+#####################
+# Step parents
+
+sub add_stepcat {
+  require 'BSE/Admin/StepParents.pm';
+  my $productid = param('id');
+  defined($productid)
+    or return product_list("No id supplied to add_stepcat");
+  int($productid) eq $productid+0
+    or return product_list("Invalid product id supplied to add_stepcat");
+  my $product = Products->getByPkey($productid)
+    or return product_list("Cannot find product id $productid");
+  
+  eval {
+    my $catid = param('stepcat');
+    defined($catid)
+      or die "No stepcat supplied to add_stepcat";
+    int($catid) eq $catid
+      or die "Invalid stepcat supplied to add_stepcat";
+    my $catalog = Articles->getByPkey($catid)
+      or die "Catalog $catid not found";
+
+    my $release = param('release');
+    defined $release
+      or $release = "01/01/2000";
+    use BSE::Util::Valid qw/valid_date/;
+    $release eq '' or valid_date($release)
+      or die "Invalid release date";
+    my $expire = param('expire');
+    defined $expire
+      or $expire = '31/12/2999';
+    $expire eq '' or valid_date($expire)
+      or die "Invalid expire data";
+  
+    my $newentry = 
+      BSE::Admin::StepParents->add($catalog, $product, $release, $expire);
+  };
+  $@ and product_edit_refresh($productid, $@, 'step');
+
+  return product_edit_refresh($productid, '', 'step');
+}
+
+sub del_stepcat {
+  require 'BSE/Admin/StepParents.pm';
+  my $productid = param('id');
+  defined $productid
+    or return product_list("No id supplied to del_stepcat");
+  int($productid) eq $productid+0
+    or return product_list("Invalid product id supplied to del_stepcat");
+  my $product = Products->getByPkey($productid)
+    or return product_list("Cannot find product id $productid");
+
+  my $catid = param('stepcat');
+  defined($catid)
+    or return shop_redirect("?id=$productid&edit_product=1&message=No+stepcat+supplied+to+add_stepcat#step");
+  int($catid) eq $catid
+    or return shop_redirect("?id=$productid&edit_product=1&message=Invalid+stepcat+supplied+to+add_stepcat#step");
+  my $catalog = Articles->getByPkey($catid)
+    or return shop_redirect("?id=$productid&edit_product=1&message=".CGI::escape("Catalog+$catid+not+found")."#step");
+
+  eval {
+    BSE::Admin::StepParents->del($catalog, $product);
+  };
+  $@ and return shop_redirect("?id=$productid&edit_product=1&message=".CGI::escape($@)."#step");
+
+  return shop_redirect("?id=$productid&edit_product=1#step");
+}
+
+sub save_stepcats {
+  require 'BSE/Admin/StepParents.pm';
+  my $productid = param('id');
+  defined $productid
+    or return product_list("No id supplied to del_stepcat");
+  int($productid) eq $productid+0
+    or return product_list("Invalid product id supplied to del_stepcat");
+  my $product = Products->getByPkey($productid)
+    or return product_list("Cannot find product id $productid");
+
+  my @stepcats = OtherParents->getBy(childId=>$product->{id});
+  my %stepcats = map { $_->{parentId}, $_ } @stepcats;
+  my %datedefs = ( release => '2000-01-01', expire=>'2999-12-31' );
+  for my $stepcat (@stepcats) {
+    for my $name (qw/release expire/) {
+      my $date = param($name.'_'.$stepcat->{parentId});
+      if (defined $date) {
+       if ($date eq '') {
+         $date = $datedefs{$name};
+       }
+       elsif (valid_date($date)) {
+         use BSE::Util::SQL qw/date_to_sql/;
+         $date = date_to_sql($date);
+       }
+       else {
+         product_edit_refresh($productid, "Invalid date '$date'");
+       }
+       $stepcat->{$name} = $date;
+      }
+    }
+    eval {
+      $stepcat->save();
+    };
+    $@ and product_edit_refresh($productid, $@);
+  }
+  product_edit_refresh($productid, $@);
+}
+
 #####################
 # utilities
 # perhaps some of these belong in a class...
 
+sub product_edit_refresh {
+  my ($productid, $message, $name) = @_;
+
+  my $url = '?edit_product=1&id='.$productid;
+  $url .= '&message='.CGI::escape($message) if $message;
+  $url .= "#$name" if $name;
+
+  shop_redirect($url);
+}
+
 sub page {
   my ($which, $acts, $iter) = @_;
 
index 3b7ca32..5471fd6 100644 (file)
@@ -18,4 +18,74 @@ sub step_parents {
   Articles->getSpecial('stepParents', $self->{id});
 }
 
+sub visible_step_parents {
+  my ($self) = @_;
+
+  use BSE::Util::SQL qw/now_datetime/;
+  my $now = now_datetime();
+  grep $_->{release} le $now && $now le $_->{expire}, $self->step_parents;
+}
+
+sub stepkids {
+  my ($self) = @_;
+
+  if ($self->{generator} eq 'Generate::Catalog') {
+    require 'Products.pm';
+    return Products->getSpecial('stepProducts', $self->{id});
+  }
+  return ();
+}
+
+sub visible_stepkids {
+  my ($self) = @_;
+
+  if ($self->{generator} eq 'Generate::Catalog') {
+    use BSE::Util::SQL qw/now_sqldate/;
+    require 'Products.pm';
+    my $today = now_sqldate();
+
+    return Products->getSpecial('visibleStep', $self->{id}, $today);
+  }
+  
+  return ();
+}
+
+# returns a list of all children in the correct sort order
+# this is a bit messy
+sub allkids {
+  my ($self) = @_;
+
+  require 'OtherParents.pm';
+
+  my @otherlinks = OtherParents->getBy(parentId=>$self->{id});
+  my @normalkids = Articles->children;
+  my %order = (
+              (map { $_->{id}, $_->{displayOrder} } @normalkids ),
+              (map { $_->{childId}, $_->{parentDisplayOrder} } @otherlinks),
+             );
+  my @stepkids = $self->stepkids;
+  my %kids = map { $_->{id}, $_ } @stepkids, @normalkids;
+
+  return @kids{ sort { $order{$b} <=> $order{$a} } keys %kids };
+}
+
+# returns a list of all visible children in the correct sort order
+# this is a bit messy
+sub all_visible_kids {
+  my ($self) = @_;
+
+  require 'OtherParents.pm';
+
+  my @otherlinks = OtherParents->getBy(parentId=>$self->{id});
+  my @normalkids = Articles->listedChildren;
+  my %order = (
+              (map { $_->{id}, $_->{displayOrder} } @normalkids ),
+              (map { $_->{id}, $_->{parentDisplayOrder} } @otherlinks),
+             );
+  my @stepkids = $self->visible_stepkids;
+  my %kids = map { $_->{id}, $_ } @stepkids, @normalkids;
+
+  return @kids{ sort { $order{$b} <=> $order{$a} } keys %kids };
+}
+
 1;
diff --git a/site/cgi-bin/modules/BSE/Admin/StepParents.pm b/site/cgi-bin/modules/BSE/Admin/StepParents.pm
new file mode 100644 (file)
index 0000000..13df6a3
--- /dev/null
@@ -0,0 +1,40 @@
+package BSE::Admin::StepParents;
+use strict;
+use Articles;
+use OtherParents;
+use BSE::Util::SQL qw/date_to_sql/;
+
+sub add {
+  my ($class, $parent, $child, $release, $expire) = @_;
+
+  my %data;
+  $data{parentId} = $parent->{id};
+  $data{childId} = $child->{id};
+  $data{parentDisplayOrder} = $data{childDisplayOrder} = time;
+  $data{expire} = ($expire && date_to_sql($expire)) || '2999-12-31';
+  $data{release} = ($release && date_to_sql($release)) || '2000-01-01';
+  my @cols = OtherParent->columns;
+  shift @cols;
+
+  # check for an existing entry
+  my $existing = 
+    OtherParents->getBy(parentId=>$parent->{id}, childId=>$child->{id})
+    and die "Entry already exists";
+
+  my $otherprod = OtherParents->add(@data{@cols})
+    or die "Cannot add";
+
+  return $otherprod;
+}
+
+sub del {
+  my ($class, $parent, $child) = @_;
+
+  my $existing = 
+    OtherParents->getBy(parentId=>$parent->{id}, childId=>$child->{id})
+    or die "Entry doesn't exit";
+
+  $existing->remove();
+}
+
+1;
index ed48d0c..b3bb492 100644 (file)
@@ -5,153 +5,6 @@ use strict;
 use vars qw(@ISA);
 @ISA = qw(BSE::CustomBase);
 
-# these values are all in cents
-# flagfall, per item and minimum for overseas deliveries
-my $FREIGHT_OS_FLAG = 500;
-my $FREIGHT_OS_PER = 450;
-my $FREIGHT_OS_MIN = 0;
-
-# flagfall, per item and minimum for australian deliveries
-my $FREIGHT_AUST_FLAG = 300;
-my $FREIGHT_AUST_PER = 100;
-my $FREIGHT_AUST_MIN = 0;
-
-# 
-my $FREIGHT_AUST_PASS = 100;
-my $FREIGHT_OS_PASS = 100;
-
-sub _is_fringe_pass {
-  my ($product) = @_;
-
-  $product->{title} =~ /fringepass/i;
-}
-
-sub _have_fringe_pass {
-  my ($products) = @_;
-
-  scalar(grep _is_fringe_pass($_), @$products);
-}
-
-sub _only_fringe_pass {
-  my ($products) = @_;
-
-  !grep !_is_fringe_pass($_), @$products;
-}
-
-sub _freight {
-  my ($items, $products, $overseas) = @_;
-
-  return 0 unless @$items;
-  if (!_only_fringe_pass($products)) {
-    my $total = $overseas ? $FREIGHT_OS_FLAG : $FREIGHT_AUST_FLAG;
-    my $per = $overseas ? $FREIGHT_OS_PER : $FREIGHT_AUST_PER;
-    my $min = $overseas ? $FREIGHT_OS_MIN : $FREIGHT_AUST_MIN;
-    my $pass = 0;
-    for my $index (0..$#{$items}) {
-      if (_is_fringe_pass($products->[$index])) {
-       # assume this is absorbed
-       #$pass = $overseas ? $FREIGHT_OS_PASS : $FREIGHT_AUST_PASS
-      }
-      else {
-       $total += $items->[$index]{units} * $per;
-      }
-    }
-    $total += $pass;
-    if ($total < $min) {
-      $total = $min;
-    }
-
-    return $total;
-  }
-  else {
-    # only fringe passes
-    return $overseas ? $FREIGHT_OS_PASS : $FREIGHT_AUST_PASS;
-  }
-}
-
-sub checkout_actions {
-  my ($class, $acts, $items, $products, $state) = @_;
-
-  my $want_password = _have_fringe_pass($products);
-
-  return
-    (
-     ifFringePass => sub { $want_password },
-     freight => sub { _freight($items, $products, $state->{overseas}) },
-     freight_aust => sub { _freight($items, $products, 0) },
-     freight_overseas => sub { _freight($items, $products, 1) },
-     ifOverseas => sub { $state->{overseas} },
-    );
-}
-
-sub order_save {
-  my ($class, $cgi, $order, $items, $products, $state) = @_;
-
-  if (_have_fringe_pass($products)) {
-    # the user should have entered as password into the "fringepassword"
-    # field
-    my $password = $cgi->param('fringepassword');
-    my $confirm = $cgi->param('fringepassconfirm');
-    unless (defined $password && $password ne '') {
-      die "Please enter a password to be used with your Fringe Pass\n";
-    }
-    # we only check for confirmation if there was a confirm field
-    # on the form
-    if (defined($confirm) && $confirm ne $password) {
-      die "Your Fringe Pass password does not match the Confirm field\n";
-    }
-
-    use Digest::MD5 qw(md5_hex);
-    $order->{billFirstName} = md5_hex($password.$order->{randomId});
-  }
-  $state->{overseas} = $cgi->param('overseas');
-  if (!$state->{overseas} && $order->{delivCountry} !~ /^\s*$/i) {
-    die "Please only enter a country if you are overseas\n";
-  }
-  if ($state->{overseas} && $order->{delivCountry} =~ /^\s*$/i) {
-    die "Please enter a country if you are overseas\n";
-  }
-}
-
-sub total_extras {
-  my ($class, $items, $products, $state) = @_;
-
-  _freight($items, $products, $state->{overseas});
-}
-
-sub recalc {
-  my ($class, $q, $item, $products, $state) = @_;
-
-  $state->{overseas} = $q->param('overseas');
-}
-
-sub cart_actions {
-  my ($class, $acts, $items, $products, $state) = @_;
-
-  return
-    (
-     freight => sub { _freight($items, $products, $state->{overseas}) },
-     freight_aust => sub { _freight($items, $products, 0) },
-     freight_overseas => sub { _freight($items, $products, 1) },
-     ifOverseas => sub { $state->{overseas} },
-    );
-}
-
-sub required_fields {
-  my ($class, $q, $state) = @_;
-
-  grep $_ ne 'country', $class->SUPER::required_fields($q, $state);
-}
-
-sub purchase_actions {
-  my ($class, $acts, $items, $products, $state) = @_;
-
-  return
-    (
-     freight => sub { _freight($items, $products, $state->{overseas}) },
-    );
-}
-
 1;
 
 =head1 NAME
index 774f112..765626f 100644 (file)
@@ -43,6 +43,8 @@ sub required_fields {
 
 sub purchase_actions {
   my ($class, $acts, $items, $products, $state) = @_;
+
+  return;
 }
 
 1;
index 2d96b22..281581b 100644 (file)
@@ -33,6 +33,12 @@ my %statements =
    
    getArticleByLevel => 'select * from article where level = ?',
    getArticleByParentid => 'select * from article where parentid = ?',
+   'Articles.stepParents' => <<EOS,
+select ar.* from article ar, other_parents op
+  where ar.id = op.parentId and op.childId = ?
+order by op.childDisplayOrder desc
+EOS
+
    dropIndex => 'delete from searchindex',
    insertIndex => 'insert searchindex values(?, ?, ?, ?)',
    searchIndex => 'select * from searchindex where id = ?',
@@ -42,13 +48,36 @@ my %statements =
    addProduct => 'insert product values(?,?,?,?,?,?,?)',
    getProductByPkey => 'select article.*, product.* from article, product where id=? and articleId = id',
    replaceProduct => 'replace product values(?,?,?,?,?,?,?)',
-   
+   'Products.stepProducts' => <<EOS,
+select ar.*, pr.* from article ar, product pr, other_parents op
+   where ar.id = pr.articleId and op.childId = ar.id and op.parentId = ?
+EOS
+   'Products.visibleStep' => <<EOS,
+select ar.*, pr.* from article ar, product pr, other_parents op
+   where ar.id = pr.articleId and op.childId = ar.id 
+     and op.parentId = ? and ? between op.release and op.expire
+EOS
    Orders => 'select * from orders',
    getOrderByPkey => 'select * from orders where id = ?',
    getOrderItemByOrderId => 'select * from order_item where orderId = ?',
    addOrder => 'insert orders values(null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
    replaceOrder => 'replace orders values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
    addOrderItem => 'insert order_item values(null,?,?,?,?,?,?,?)',
+
+   OtherParents => 'select * from other_parents',
+   getOtherParentByChildId => <<EOS,
+select * from other_parents where childId = ? order by childDisplayOrder desc
+EOS
+   getOtherParentByParentId => <<EOS,
+select * from other_parents where parentId = ? order by parentDisplayOrder desc
+EOS
+   getOtherParentByParentIdAndChildId =>
+   'select * from other_parents where parentId = ? and childId = ?',
+   addOtherParent=>'insert other_parents values(null,?,?,?,?,?,?)',
+   deleteOtherParent => 'delete from other_parents where id = ?',
+   replaceOtherParent=>'replace other_parents values(?,?,?,?,?,?,?)',
+   'OtherParents.anylinks' => 
+   'select * from other_parents where childId = ? or parentId = ?',
   );
 
 sub _single
@@ -78,7 +107,9 @@ sub stmt {
 sub insert_id {
   my ($self, $sth) = @_;
 
-  return $self->{dbh}->{'mysql_insertid'};
+  my $id = $sth->{"mysql_insertid"};
+
+  return $id;
 }
 
 # gotta love this
diff --git a/site/cgi-bin/modules/BSE/Util/SQL.pm b/site/cgi-bin/modules/BSE/Util/SQL.pm
new file mode 100644 (file)
index 0000000..fd562bb
--- /dev/null
@@ -0,0 +1,64 @@
+package BSE::Util::SQL;
+use strict;
+use vars qw(@EXPORT_OK @ISA);
+require 'Exporter.pm';
+@EXPORT_OK = qw/now_datetime sql_datetime date_to_sql sql_to_date sql_date now_sqldate/;
+@ISA = qw/Exporter/;
+
+=head1 NAME
+
+  BSE::Util::SQL - very basic tools for working with databases.
+
+=head1 SYNOPSIS
+
+  my $sqlnow = now_sqldatetime();
+  my $sqlthen = sql_datetime($when);
+  my $sqldate = date_to_sql($date);
+  my $date = sql_to_date($sqldate);
+
+=head1 DESCRIPTION
+
+Some basic tools for working with the database, including things like
+formatting and extracting dates.
+
+=over
+
+=item sql_datetime($time_t)
+
+=cut
+
+sub sql_datetime {
+  use POSIX qw/strftime/;
+  return strftime('%Y-%m-%d %H:%M:%S', localtime shift);
+}
+
+sub now_datetime {
+  return sql_datetime(time);
+}
+
+sub sql_date {
+  use POSIX qw/strftime/;
+  return strftime('%Y-%m-%d', localtime shift);
+}
+
+sub now_sqldate {
+  return sql_date(time);
+}
+
+sub date_to_sql {
+  my $date = shift;
+
+  my ($day, $month, $year) = $date =~ /(\d+)\D+(\d+)\D+(\d+)/;
+
+  return "$year-$month-$day";
+}
+
+sub sql_to_date {
+  my $sqldate = shift;
+
+  my ($year, $month, $day) = $sqldate =~ /^(\d+)\D+(\d+)\D+(\d+)/;
+
+  return "$day/$month/$year";
+}
+
+1;
diff --git a/site/cgi-bin/modules/BSE/Util/Valid.pm b/site/cgi-bin/modules/BSE/Util/Valid.pm
new file mode 100644 (file)
index 0000000..dcc844b
--- /dev/null
@@ -0,0 +1,13 @@
+package BSE::Util::Valid;
+use strict;
+use vars qw(@EXPORT_OK @ISA);
+require 'Exporter.pm';
+@EXPORT_OK = qw/valid_date/;
+@ISA = qw/Exporter/;
+
+sub valid_date {
+  $_[0] =~ m!^\d+[/-]\d+[/-]\d+$!;
+}
+
+1;
+
index ab01dbc..0e45b3c 100644 (file)
@@ -240,7 +240,7 @@ $HAVE_HTML_PARSER = 1;
 # Mail configuration
 
 # the hostname or IP address of an SMTP server
-$SMTP_SERVER = 'develop-help.com';
+#$SMTP_SERVER = 'develop-help.com';
 
 # the HELO (EHLO) text passed to the SMTP server
 $SMTP_HELO = 'develop-help.com';
index a4dbab6..70b4b6d 100644 (file)
@@ -188,9 +188,9 @@ sub _embed_low {
 }
 
 sub _body_embed {
-  my ($self, $acts, $articles, $which, $template) = @_;
+  my ($self, $acts, $articles, $which, $template, $maxdepth) = @_;
 
-  my $text = $self->_embed_low($acts, $articles, $which, $template);
+  my $text = $self->_embed_low($acts, $articles, $which, $template, $maxdepth);
 
   return $text;
 }
@@ -244,11 +244,14 @@ sub format_body {
 
   my $out = '';
   for my $part (split /((?:html\[(?:[^\[\]]*(?:(?:\[[^\[\]]*\])[^\[\]]*)*)\])
-                       |embed\[(?:[^,\[\]]*)(?:,(?:[^,\[\]]*))?\])/ix, $body) {
+                       |embed\[(?:[^,\[\]]*)(?:,(?:[^,\[\]]*)){0,2}\])/ix, $body) {
     #print STDERR "Part is $part\n";
     if ($part =~ /^html\[([^\[\]]*(?:(?:\[[^\[\]]*\])[^\[\]]*)*)\]$/i) {
       $out .= _make_html($1);
     }
+    elsif ($part =~ /^embed\[([^,\[\]]*),([^,\[\]]*),([^,\[\]]*)\]$/i) {
+      $out .= $self->_body_embed($acts, $articles, $1, $2, $3);
+    }
     elsif ($part =~ /^embed\[([^,\[\]]*),([^,\[\]]*)\]$/i) {
       $out .= $self->_body_embed($acts, $articles, $1, $2);
     }
index b19b4b5..56c156d 100644 (file)
@@ -8,6 +8,7 @@ use Squirrel::Template;
 use Constants qw($TMPLDIR $URLBASE %TEMPLATE_OPTS $CGI_URI $IMAGES_URI
                  $ADMIN_URI);
 use Util qw(generate_button);
+use OtherParents;
 
 sub generate_low {
   my ($self, $template, $article, $articles, $embedded) = @_;
@@ -19,6 +20,13 @@ sub generate_low {
   my @subcats = sort { $b->{displayOrder} <=> $a->{displayOrder} }
     grep $_->{listed} && UNIVERSAL::isa($_->{generator}, 'Generate::Catalog'),
     $articles->getBy(parentid => $article->{id});
+  my $other_parents = OtherParents->new;
+  my ($year, $month, $day) = (localtime)[5,4,3];
+  my $today = sprintf("%04d-%02d-%02d 00:00:00ZZZ", $year+1900, $month+1, $day);
+  my @stepprods = $article->visible_stepkids;
+  my $stepprod_index;
+  my @allprods = $article->all_visible_kids;
+  my $allprod_index;
   my $category_index = -1;
   my %acts;
   %acts =
@@ -100,6 +108,15 @@ HTML
      catalog => 
      sub { CGI::escapeHTML($subcats[$category_index]{$_[0]}) },
      ifSubcats => sub { @subcats },
+     iterate_stepprods_reset => sub { $stepprod_index = -1 },
+     iterate_stepprods =>
+     sub {
+       ++$stepprod_index < @stepprods;
+     },
+     stepprod => sub { CGI::escapeHTML($stepprods[$stepprod_index]{$_[0]}) },
+     iterate_allprods_reset => sub { $allprod_index = -1 },
+     iterate_allprods => sub { ++$allprod_index < @allprods },
+     allprod => sub { CGI::escapeHTML($allprods[$allprod_index]{$_[0]}) },
     );
   my $oldurl = $acts{url};
   $acts{url} =
index 24116ae..a60ca06 100644 (file)
@@ -16,6 +16,8 @@ sub generate {
   my ($self, $article, $articles) = @_;
 
   my $product = Products->getByPkey($article->{id});
+  my @stepcats = $product->step_parents();
+  my $stepcat_index;
   my @options = 
     map { +{ id=>$_, %{$SHOP_PRODUCT_OPTS{$_}} } } 
       split /,/, $product->{options};
@@ -67,6 +69,9 @@ HTML
        }
      },
      ifOptions => sub { @options },
+     iterate_stepcats_reset => sub { $stepcat_index = -1 },
+     iterate_stepcats => sub { ++$stepcat_index < @stepcats },
+     stepcat => sub { CGI::escapeHTML($stepcats[$stepcat_index]{$_[0]}) },
     );
   return Squirrel::Template->new(%TEMPLATE_OPTS)
     ->show_page($TMPLDIR, $article->{template}, \%acts);
diff --git a/site/cgi-bin/modules/OtherParent.pm b/site/cgi-bin/modules/OtherParent.pm
new file mode 100644 (file)
index 0000000..f860be8
--- /dev/null
@@ -0,0 +1,12 @@
+package OtherParent;
+use strict;
+use Squirrel::Row;
+use vars qw/@ISA/;
+@ISA = qw/Squirrel::Row/;
+
+# id is only needed due to limitations in BSE's Squirrel::Row
+sub columns {
+  qw/id parentId childId parentDisplayOrder childDisplayOrder release expire/;
+}
+
+1;
diff --git a/site/cgi-bin/modules/OtherParents.pm b/site/cgi-bin/modules/OtherParents.pm
new file mode 100644 (file)
index 0000000..89889e3
--- /dev/null
@@ -0,0 +1,17 @@
+package OtherParents;
+use Squirrel::Table;
+use vars qw(@ISA $VERSION);
+@ISA = qw(Squirrel::Table);
+use OtherParent;
+
+sub rowClass {
+  return 'OtherParent';
+}
+
+sub anylinks {
+  my ($class, $id) = @_;
+
+  $class->getSpecial('anylinks', $id, $id);
+}
+
+1;
index 5617e41..7d8f781 100644 (file)
@@ -120,24 +120,36 @@ sub getAll {
 
 # column grep
 sub getBy {
-  my ($self, $column, $value) = @_;
+  my ($self, @query) = @_;
+  my @cols;
+  my %vals;
+  
+  @query % 2 == 0
+    or confess "Odd number of arguments supplied to getBy()";
+
+  while (my ($col, $val) = splice(@query, 0, 2)) {
+    push(@cols, $col);
+    $vals{$col} = $val;
+  }
 
   my @results;
   if (ref($self) && UNIVERSAL::isa($self, __PACKAGE__)) {
     # this is an object with the rows already loaded
     for my $row (@{$self->{order}}) {
-      my $comp = ref $row->{$column} ? $row->{$column}->getPkey : $row->{$column};
-      push @results, $row if $comp eq $value;
+      my %comp;
+      @comp{@cols} = 
+       map ref $row->{$_} ? $row->{$_}->getPkey : $row->{$_}, @cols;
+      push @results, $row if @cols == grep $comp{$_} eq $vals{$_}, @cols;
     }
   }
   else {
     # ask the database directly
     my $rowClass = $self->rowClass;
     require $rowClass . ".pm";
-    my $member = "get${rowClass}By\u$column";
+    my $member = "get${rowClass}By".join("And", map "\u$_", @cols);
     my $sth = $dh->stmt($member)
       or confess "No $member in BSE::DB";
-    $sth->execute($value)
+    $sth->execute(@vals{@cols})
       or confess "Cannot execute $member from BSE::DB: ",DBI->errstr;
     while (my $row = $sth->fetchrow_arrayref) {
       push(@results, $rowClass->new(@$row));
index a384417..5418178 100644 (file)
@@ -6,11 +6,25 @@ TODO - possible changes for BSE
 
 This is a simple list of possible changes to BSE.
 
+Some of these I'll do myself.
+
 =over
 
 =item *
 
-all some sort of id to be used to identify articles (rather than numbers)
+add some sort of id to be used to identify articles (rather than
+numbers) for use in templates.  Possibly they could automatically be
+added as tag names too.  So if shop were defined as article 3, then
+you could do:
+
+  <a href="<:url shop:>"><:shop title:></a>
+
+to get a shop link instead of:
+
+  <a href="/shop/">The blah blah Shop</a>
+
+since the first would be more maintainable.  This could be useful for
+other special articles.
 
 =item *
 
@@ -26,11 +40,32 @@ template
 
 =item *
 
-move the distribution into my local CVS repository, RCS is annoying
+use a proper config file - this is getting more important
+
+=item *
+
+automated way of updating the links for articles that include $SECURLBASE
+
+=item *
+
+move RSS template out of common (this has some other issues though)
+
+=item *
+
+some way of showing expired/hidden articles in browse mode
+
+=item *
+
+support for other embedable 'image' types such as flash and quicktime.
+
+Preferably this would be extendable.  We need some way to get size
+information too (entry from the user I suppose, this could also be
+used to override image sizes.)
 
 =item *
 
-use a proper config file
+move most of the shop.pl code into modules to make it more accessible
+from other scripts (especially for custom card payment.)
 
 =back
 
index fd62c3c..732a188 100644 (file)
@@ -10,8 +10,38 @@ Maybe I'll add some other bits here.
 
 =head1 CHANGES
 
+=head2 0.10_07
+
+Another test release:
+
+=over
+
+=item *
+
+initial step kids|parents for the shop
+
+=item *
+
+new popup menu templates from Adrian
+
+=item *
+
+added acknowledgements to AUTHOR section
+
+=back
+
+=head2 0.10_06
+
+Test release for Adrian, with his new templates.
+
+=head2 0.10_05
+
+Test release for Adrian.
+
 =head2 0.10_04
 
+Don't use this version.
+
 =over
 
 =item *
@@ -481,4 +511,19 @@ article objects available in the template.
 
 =back
 
+=head1 AUTHOR
+
+Tony Cook <tony@develop-help.com>
+
+I originally wrote BSE while an employee at SquirrelWeb
+http://www.squirrelweb.com.au/ for http://www.bodyscoop.com.au/
+
+Most of the BSE templates were created by Adrian Oldham
+<adriann@visualthought.com.au>.  He also funded and suggested many
+improvements.
+
+Realware Systems http://www.realware.com.au/ funded the nested
+catalogs, IIS support, the image access tags, and many other shop
+improvements, including most of the BSE::Custom hooks.
+
 =cut
index 43c3cfd..ec82b20 100644 (file)
           <tr> 
             <th nowrap align="left">Release date:</th>
             <td nowrap bgcolor="#FFFFFF"> 
-              <input type="text" name="release" value="<:date release:>" size=11>
+              <input type="text" name="release" value="<:date product release:>" size=11>
               (dd/mm/yyyy)</td>
           </tr>
           <tr> 
             <th nowrap align="left">Expiry date:</th>
             <td nowrap bgcolor="#FFFFFF"> 
-              <input type="text" name="expire" value="<:date expire:>" size=11>
+              <input type="text" name="expire" value="<:date product expire:>" size=11>
               (dd/mm/yyyy)</td>
           </tr>
           <tr> 
index 0563dc2..de6394a 100644 (file)
       </td>
     </tr>
   </table>
+</form>
+
+
+<form method="POST" action="<:script:>" enctype="multipart/form-data">
+<input type="hidden" name="level" value="<: level :>">
+<input type="hidden" name="id" value="<: article id :>">
+<input type="hidden" name="parentid" value="<: article parentid :>">
+<input type="hidden" name="imgtype" value="<: articleType :>">
   <h2>Manage Images</h2>
 
 <table border="0" cellspacing="0" cellpadding="0" bgcolor="#000000">
index 8e4d743..e41845b 100644 (file)
       <td>
 <table border=0 cellpadding="6" cellspacing="1">
   <tr><th>Title</th><th>Summary</th><th>Listed</th><th>&nbsp;</th></tr>
+  <tr> 
+      <td colspan="4" bgcolor="#FFFFFF">Reorder child articles: <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&sort=title&refreshto=/cgi-bin/admin/add.pl?id=<:article id:>">by 
+       title</a> | <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&sort=date&refreshto=/cgi-bin/admin/add.pl?id=<:article id:>">by 
+       date</a> | <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&reverse=1&refreshto=/cgi-bin/admin/add.pl?id=<:article id:>">reverse 
+       order</a></td>
+  </tr>
 <:iterator begin children:>
   <tr bgcolor="#FFFFFF"> 
     <td><a href="<:child admin:>"><:child title:></a></td>
index 88d6afe..bd49b26 100644 (file)
             <:or NextChild:> <:eif NextChild:> <:if PrevChild:> <a href="/cgi-bin/admin/move.pl?id=<:child id:>&d=up&edit=1&all=1"> 
             <img src="/images/admin/move_up.gif" width="17" height="13" alt="Move Up" border="0"></a> 
             <:or PrevChild:> <:eif PrevChild:> 
-<form action="<:script:>" onSubmit="return window.confirm('Are you sure you want to delete this article')" method=POST><input type=hidden name=id value="<:article id:>"><input type=hidden name="deleteid" value="<:child id:>"><input type=submit name=remove value="Delete"></form></td>
-</tr>
-<:iterator separator children:>
-<:iterator end children:>
-</table>
+            <form action="<:script:>" onSubmit="return window.confirm('Are you sure you want to delete this article')" method=POST>
+              <input type=hidden name=id value="<:article id:>">
+              <input type=hidden name="deleteid" value="<:child id:>">
+              <input type=submit name=remove value="Delete">
+            </form>
+          </td>
+        </tr>
+        <:iterator separator children:> <:iterator end children:> 
+      </table>
 </td>
 </tr>
 </table>
index 764b73c..276bce1 100644 (file)
@@ -75,8 +75,7 @@
             <th> Expire Date: </th>
             <td bgcolor="#FFFFFF"> 
               <input type="text" name="expire" value="<: article expire :>" size="10" maxlength="10">
-              (dd/mm/yyyy - <: ifnew :>default is two weeks from now, <: or :><: eif :>blank 
-              for never expires)</td>
+              (dd/mm/yyyy - <: ifnew :>default is never, <: or :><: eif :>)</td>
           </tr>
           <tr> 
             <th> Summary Length: </th>
             <:or NextChild:> <:eif NextChild:> <:if PrevChild:> <a href="/cgi-bin/admin/move.pl?id=<:child id:>&d=up&edit=1&all=1"> 
             <img src="/images/admin/move_up.gif" width="17" height="13" alt="Move Up" border="0"></a> 
             <:or PrevChild:> <:eif PrevChild:> 
-<form action="<:script:>" onSubmit="return window.confirm('Are you sure you want to delete this article')" method=POST><input type=hidden name=id value="<:article id:>"><input type=hidden name="deleteid" value="<:child id:>"><input type=submit name=remove value="Delete"></form></td>
-</tr>
-<:iterator separator children:>
-<:iterator end children:>
-</table>
+            <form action="<:script:>" onSubmit="return window.confirm('Are you sure you want to delete this article')" method=POST>
+              <input type=hidden name=id value="<:article id:>">
+              <input type=hidden name="deleteid" value="<:child id:>">
+              <input type=submit name=remove value="Delete">
+            </form>
+          </td>
+        </tr>
+        <:iterator separator children:> <:iterator end children:> 
+      </table>
 </td>
 </tr>
 </table>
index 6ecf2fa..2e85626 100644 (file)
 <p><input type=submit value="Add <:childtype:>"></p>
 </form>
 <p><:eif new:> <:or HaveChildType:> <:eif HaveChildType:> </p>
+
+<h2><a name="step"></a>Step Products</h2>
+<table border="0" cellspacing="0" cellpadding="0" bgcolor='#000000'>
+<tr><td><table border="0" cellpadding="6" cellspacing="1" bgcolor='#FFFFFF'>
+<tr>
+  <th>Id</th>
+  <th>Title</th>
+  <th>Release</th>
+  <th>Expire</th>
+  <th>&nbsp</th>
+</tr>
+<:if Kids:>
+<form action="<:script:>" method="POST"><input type="hidden" name="id" value="<:article id:>">
+<:iterator begin kids:>
+<tr>
+  <td><:kid id:></td>
+  <td><:kid title:></td>
+  <td><:ifStepKid:><input type="text" name="release_<:stepkid childId:>" value="<:date stepkid release:>" size=10><:or:>&nbsp;<:eif:></td>
+  <td><:ifStepKid:><input type="text" name="expire_<:stepkid childId:>" value="<:date stepkid expire:>" size=10><:or:>&nbsp;<:eif:></td>
+  <td><:movestepkid:> <b><:ifStepKid:><a href="<:script:>?del_stepkid=1&id=<:stepkid parentId:>&stepkid=<:stepkid childId:>">Delete</a><:or:><:eif:> <:edit kid Edit:></b></td>
+</tr>
+<:iterator end kids:>
+<tr>
+  <td colspan="5" align="center"><input type="submit" name="save_stepkids" value="Save Changes"></td>
+</tr>
+<:or Kids:>
+<tr>
+  <td colspan="5" align="center">No children</td>
+</tr>
+<:eif Kids:>
+<:if Possibles:>
+<form action="<:script:>"><input type="hidden" name="id" value="<:article id:>">
+<tr>
+  <td colspan="2"><:possible_stepkids:></td>
+  <td><input type="text" name="release" value="01/01/2000" size="10"></td>
+  <td><input type="text" name="expire" value="31/12/2999" size="10"></td>
+  <td><input type="submit" name="add_stepkid" value="Add Stepkid"></td>
+</tr>
+</form>
+<:or Possibles:><:eif Possibles:>
+</form>
+</table>
+</td></tr></table>
 </body
 ></html>
index a541a5c..d15c59c 100644 (file)
           <tr> 
             <th align="left">Release date:</th>
             <td bgcolor="#FFFFFF"> 
-              <input type="text" name="release" value="<:date release:>" size=11>
+              <input type="text" name="release" value="<:date product release:>" size=11>
               (dd/mm/yyyy)</td>
           </tr>
           <tr> 
             <th align="left">Expiry date:</th>
             <td bgcolor="#FFFFFF"> 
-              <input type="text" name="expire" value="<:date expire:>" size=11>
+              <input type="text" name="expire" value="<:date product expire:>" size=11>
               (dd/mm/yyyy)</td>
           </tr>
           <tr> 
   <p><input type=submit name="save_product" value="Save"></p>
 </form>
 
+<a name="step"></a><h3>Step parents</h3>
+<table border="0" cellspacing="0" cellpadding="0" bgcolor='#000000'>
+<tr><td>
+<table border=0 cellpadding="6" cellspacing="1" bgcolor='#FFFFFF'>
+  <tr>
+    <th>Id</th>
+    <th>Title</th>
+    <th>Release</th>
+    <th>Expire</th>
+    <td>&nbsp;</td>
+</tr>
+  <:if Stepcats:>
+<tr>
+      <td colspan="5" align="center">Note: Delete only removes the stepchild relationship.  It does not delete the catalog.</td>
+</tr>
+<form action="<:script:>"><input type="hidden" name="id" value="<:product id:>">
+  <:iterator begin stepcats:>
+    <tr>
+      <td align="center"><a href="<:stepcat_targ admin:>"><:stepcat parentId:></a></td>
+      <td><:stepcat_targ title:></td>
+      <td><input type="text" name="release_<:stepcat parentId:>" value="<:date stepcat release:>" size="10"></td>
+      <td><input type="text" name="expire_<:stepcat parentId:>" value="<:date stepcat expire:>" size="10"></td>
+      <td><:movestepcat:> <b><a href="<:script:>?del_stepcat=1&id=<:stepcat childId:>&stepcat=<:stepcat parentId:>">Delete</a> <a href="/cgi-bin/admin/add.pl?id=<:stepcat parentId:>">Edit</a></b></td>
+    </tr>
+  <:iterator end stepcats:>
+    <tr>
+      <td colspan="5" align="center"><input type="submit" name="save_stepcats" value="Save Changes"></td>
+    </tr>
+</form>
+  <:or Stepcats:>
+  <tr>
+    <td colspan="5" align="center">No step parents</td>
+  </tr>
+  <:eif Stepcats:>
+<:if StepcatPossibles:>
+<form action="<:script:>"><input type="hidden" name="id" value="<:product id:>">
+<tr>
+  <td colspan=2><:stepcat_possibles:></td>
+      <td><input type="text" name="release" value="01/01/2000" size="10"></td>
+      <td><input type="text" name="expire" value="31/12/2999" size="10"></td>
+  <td><input type="submit" name="add_stepcat" value="Add!"></td>
+</tr>
+</form>
+<:or StepcatPossibles:>
+  <tr>
+    <td colspan="5" align="center">No more possible catalogs to add.</td>
+  </tr>
+<:eif StepcatPossibles:>
+</table>
+</td></tr>
+</table>
+
 </body>
 </html>
index 4c5d305..31581a5 100644 (file)
@@ -2,7 +2,8 @@
 <table width="100%" border="0" cellspacing="0" cellpadding="0">
   <tr> 
     <td bgcolor="#CCCCFF" width="80%" height="24">&nbsp;&nbsp;<font face="Verdana, Arial, Helvetica, sans-serif" size="4"><b><:title:></b></font></td>
-    <td height="24">&nbsp;</td>
+    <td height="24">&nbsp;<a href="/cgi-bin/printable.pl?id=<:article id:>"><font face="Verdana, Arial, Helvetica, sans-serif" size="-2" color="#999999">printable 
+      version</font></a></td>
   </tr>
   <tr> 
     <td bgcolor="#999999" colspan="2" height="1"><img src="/images/trans_pixel.gif" width="24" height="1" border="0"></td>
   </tr>
 </table>
 <p><font face="Verdana, Arial, Helvetica, sans-serif" size="2"><:body:></font></p>
-<:embed end:><:if UnderThreshold:><:iterator begin children:><:ifAdmin:>
+<:embed end:><:ifAdmin:><:if Children:> 
+<p><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Reorder child articles: 
+  <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&sort=title&refreshto=/cgi-bin/admin/admin.pl?id=<:article id:>">by 
+  title</a> | <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&sort=date&refreshto=/cgi-bin/admin/admin.pl?id=<:article id:>">by 
+  date</a> | <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&reverse=1&refreshto=/cgi-bin/admin/admin.pl?id=<:article id:>">reverse 
+  order</a></font></p>
+<:or Children:><:eif Children:><:or:><:eif:><:if UnderThreshold:><:iterator begin 
+children:><:ifAdmin:> 
 <hr noshade size="1">
 <:or:><:eif:><:moveDown:><:moveUp:><:embed child:><:iterator separator children:><br>
 <:iterator end children:> <:or UnderThreshold:> <:iterator begin children:> 
index 24df2a7..8e4d396 100644 (file)
@@ -2,7 +2,8 @@
 <table width="100%" border="0" cellspacing="0" cellpadding="0">
   <tr> 
     <td bgcolor="#CCCCFF" width="80%" height="24">&nbsp;&nbsp;<font face="Verdana, Arial, Helvetica, sans-serif" size="4"><b><:title:></b></font></td>
-    <td height="24">&nbsp;</td>
+    <td height="24">&nbsp;<a href="/cgi-bin/printable.pl?id=<:article id:>"><font face="Verdana, Arial, Helvetica, sans-serif" size="-2" color="#999999">printable 
+      version</font></a></td>
   </tr>
   <tr> 
     <td bgcolor="#999999" colspan="2" height="1"><img src="/images/trans_pixel.gif" width="24" height="1" border="0"></td>
     </td>
   </tr>
 </table>
+<p><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Reorder child articles: 
+  <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&sort=title&refreshto=/cgi-bin/admin/admin.pl?id=<:article id:>">by 
+  title</a> | <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&sort=date&refreshto=/cgi-bin/admin/admin.pl?id=<:article id:>">by 
+  date</a> | <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&reverse=1&refreshto=/cgi-bin/admin/admin.pl?id=<:article id:>">reverse 
+  order</a></font></p>
 <:or Admin:><:eif Admin:> 
 <p><b><font face="Verdana, Arial, Helvetica, sans-serif" size="2"><:title:></font></b><:or:><:eif:></p>
 <:ifEmbedded:>
index 9da7986..e9b385a 100644 (file)
             </table>
             <table width="100%" border="0" cellspacing="0" cellpadding="10">
               <tr> 
-                <td> <font face="Verdana, Arial, Helvetica, sans-serif" size="2"><:body:></font>
-<:if UnderThreshold:><:iterator begin children:><:ifAdmin:> 
-                        <br>
+                <td> <font face="Verdana, Arial, Helvetica, sans-serif" size="2"><:body:></font> 
+                  <:ifAdmin:><:if Children:> 
+                  <p><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Reorder 
+                    child articles: <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&sort=title&refreshto=/cgi-bin/admin/admin.pl?id=<:article id:>">by 
+                    title</a> | <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&sort=date&refreshto=/cgi-bin/admin/admin.pl?id=<:article id:>">by 
+                    date</a> | <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&reverse=1&refreshto=/cgi-bin/admin/admin.pl?id=<:article id:>">reverse 
+                    order</a></font></p>
+                  <:or Children:><:eif Children:><:or:><:eif:><:if UnderThreshold:><:iterator 
+                  begin children:><:ifAdmin:> <br>
                         <:or:><:eif:><:moveDown:><:moveUp:><:embed 
 child:><:iterator separator children:><:iterator end children:> <:or UnderThreshold:> 
 <:iterator begin children:> 
@@ -54,7 +60,8 @@ child:><:iterator separator children:><:iterator end children:> <:or UnderThresh
 <table width="100%" border="0" cellspacing="0" cellpadding="0">
   <tr> 
     <td bgcolor="#CCCCFF" width="80%" height="24">&nbsp;&nbsp;<font face="Verdana, Arial, Helvetica, sans-serif" size="4"><b><:title:></b></font></td>
-    <td height="24">&nbsp;</td>
+    <td height="24">&nbsp;<a href="/cgi-bin/printable.pl?id=<:article id:>"><font face="Verdana, Arial, Helvetica, sans-serif" size="-2" color="#999999">printable 
+      version</font></a></td>
   </tr>
   <tr> 
     <td bgcolor="#999999" colspan="2" height="1"><img src="/images/trans_pixel.gif" width="24" height="1" border="0"></td>
@@ -74,7 +81,14 @@ child:><:iterator separator children:><:iterator end children:> <:or UnderThresh
   </tr>
 </table>
 <p><font face="Verdana, Arial, Helvetica, sans-serif" size="2"><:body:></font></p>
-<:if UnderThreshold:><:iterator begin children:><:ifAdmin:> 
+<:ifAdmin:><:if Children:> 
+<p><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Reorder child articles: 
+  <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&sort=title&refreshto=/cgi-bin/admin/admin.pl?id=<:article id:>">by 
+  title</a> | <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&sort=date&refreshto=/cgi-bin/admin/admin.pl?id=<:article id:>">by 
+  date</a> | <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&reverse=1&refreshto=/cgi-bin/admin/admin.pl?id=<:article id:>">reverse 
+  order</a></font></p>
+<:or Children:><:eif Children:><:or:><:eif:><:if UnderThreshold:><:iterator begin 
+children:><:ifAdmin:> 
 <hr noshade size="1">
 <:or:><:eif:><:moveDown:><:moveUp:><:embed child:><:iterator separator children:><br>
 <:iterator end children:> <:or UnderThreshold:> <:iterator begin children:> 
index 5d5f369..b41a7a2 100644 (file)
                   <table width="100%" border="0" cellspacing="0" cellpadding="10">
                     <tr> 
                       <td><font face="Verdana, Arial, Helvetica, sans-serif" size="2"><:body:></font> 
-                        <:if UnderThreshold:><:iterator begin children:><:ifAdmin:> 
-                        <br>
+                        <:ifAdmin:><:if Children:> 
+                        <p><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Reorder 
+                          child articles: <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&sort=title&refreshto=/cgi-bin/admin/admin.pl?id=<:article id:>">by 
+                          title</a> | <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&sort=date&refreshto=/cgi-bin/admin/admin.pl?id=<:article id:>">by 
+                          date</a> | <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&reverse=1&refreshto=/cgi-bin/admin/admin.pl?id=<:article id:>">reverse 
+                          order</a></font></p>
+                        <:or Children:><:eif Children:><:or:><:eif:><:if UnderThreshold:><:iterator 
+                        begin children:><:ifAdmin:> <br>
                         <:or:><:eif:><:moveDown:><:moveUp:><:embed 
 child:><:iterator separator children:><:iterator end children:> <:or UnderThreshold:> 
 <:iterator begin children:> 
@@ -60,7 +66,8 @@ child:><:iterator separator children:><:iterator end children:> <:or UnderThresh
 <table width="100%" border="0" cellspacing="0" cellpadding="0">
   <tr> 
     <td bgcolor="#CCCCFF" width="80%" height="24">&nbsp;&nbsp;<font face="Verdana, Arial, Helvetica, sans-serif" size="4"><b><:title:></b></font></td>
-    <td height="24">&nbsp;</td>
+    <td height="24">&nbsp;<a href="/cgi-bin/printable.pl?id=<:article id:>"><font face="Verdana, Arial, Helvetica, sans-serif" size="-2" color="#999999">printable 
+      version</font></a></td>
   </tr>
   <tr> 
     <td bgcolor="#999999" colspan="2" height="1"><img src="/images/trans_pixel.gif" width="24" height="1" border="0"></td>
@@ -80,7 +87,14 @@ child:><:iterator separator children:><:iterator end children:> <:or UnderThresh
   </tr>
 </table>
 <p><font face="Verdana, Arial, Helvetica, sans-serif" size="2"><:body:></font></p>
-<:if UnderThreshold:><:iterator begin children:><:ifAdmin:> 
+<:ifAdmin:><:if Children:> 
+<p><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Reorder child articles: 
+  <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&sort=title&refreshto=/cgi-bin/admin/admin.pl?id=<:article id:>">by 
+  title</a> | <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&sort=date&refreshto=/cgi-bin/admin/admin.pl?id=<:article id:>">by 
+  date</a> | <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&reverse=1&refreshto=/cgi-bin/admin/admin.pl?id=<:article id:>">reverse 
+  order</a></font></p>
+<:or Children:><:eif Children:><:or:><:eif:><:if UnderThreshold:><:iterator begin 
+children:><:ifAdmin:> 
 <hr noshade size="1">
 <:or:><:eif:><:moveDown:><:moveUp:><:embed child:><:iterator separator children:><br>
 <:iterator end children:> <:or UnderThreshold:> <:iterator begin children:> 
index 3a30676..34549f6 100644 (file)
@@ -1,3 +1,28 @@
+<:wrap base.tmpl:> <:admin:> 
+<table width="100%" border="0" cellspacing="0" cellpadding="0">
+  <tr> 
+    <td bgcolor="#CCCCFF" width="80%" height="24">&nbsp;&nbsp;<font face="Verdana, Arial, Helvetica, sans-serif" size="4"><b><:title:></b></font></td>
+    <td height="24">&nbsp;<a href="/cgi-bin/printable.pl?id=<:article id:>"><font face="Verdana, Arial, Helvetica, sans-serif" size="-2" color="#999999">printable 
+      version</font></a></td>
+  </tr>
+  <tr> 
+    <td bgcolor="#999999" colspan="2" height="1"><img src="/images/trans_pixel.gif" width="24" height="1" border="0"></td>
+  </tr>
+  <tr> 
+    <td colspan="2"> 
+      <table width="100%" border="0" cellspacing="0" cellpadding="0">
+        <tr> 
+          <td width="100"><img src="/images/trans_pixel.gif" width="100" height="10" border="0"></td>
+          <td bgcolor="#333399" width="100%">&nbsp;<font face="Verdana, Arial, Helvetica, sans-serif" size="-2">/ 
+            <a href="<:ifAdmin:>/cgi-bin/admin/admin.pl?id=1<:or:>/<:eif:>"><font color="#FFFFFF">Home</font></a> 
+            / <:iterator begin crumbs:> <a href="<:url crumbs:>"><font color="#FFFFFF"><:crumbs 
+            title:></font></a> / <:iterator end crumbs:></font></td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+</table>
+<p><font face="Verdana, Arial, Helvetica, sans-serif" size="2"><:body:></font></p>
 <:embed start:><:ifAdmin:> 
 <table cellpadding="4" cellspacing="0" border="0">
   <tr> 
index 061b890..d1f5eef 100644 (file)
@@ -1,4 +1,10 @@
-<:embed start:><:admin:> <:iterator begin children:><:moveDown:><:moveUp:><:embed 
+<:embed start:><:admin:> <:ifAdmin:><:if Children:> 
+<p><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Reorder child articles: 
+  <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&sort=title&refreshto=/cgi-bin/admin/admin.pl?id=1">by 
+  title</a> | <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&sort=date&refreshto=/cgi-bin/admin/admin.pl?id=1">by 
+  date</a> | <a href="/cgi-bin/admin/reorder.pl?parentid=<:article id:>&reverse=1&refreshto=/cgi-bin/admin/admin.pl?id=1">reverse 
+  order</a></font></p>
+<:or Children:><:eif Children:><:or:><:eif:><:iterator begin children:><:moveDown:><:moveUp:><:embed 
 child:> <:iterator separator children:> <br clear="all">
 <:iterator end children:>
 <:embed end:>
diff --git a/site/templates/menu/menu.tmpl b/site/templates/menu/menu.tmpl
new file mode 100644 (file)
index 0000000..aa29df0
--- /dev/null
@@ -0,0 +1,16 @@
+<:embed start:>
+<script language="JavaScript">
+<!--
+function MM_jumpMenu(targ,selObj,restore){ //v3.0
+  eval(targ+".location='"+selObj.options[selObj.selectedIndex].value+"'");
+  if (restore) selObj.selectedIndex=0;
+}
+//-->
+</script>
+<form name="articleJump">
+  <select name="Articles" onChange="MM_jumpMenu('parent',this,0)">
+<option value="<:url article:>"><:article title:></option><:iterator begin children:>
+<:embed child menu/menu1.tmpl:><:iterator separator children:><:iterator end children:>
+  </select>
+</form>
+<:embed end:>
\ No newline at end of file
diff --git a/site/templates/menu/menu1.tmpl b/site/templates/menu/menu1.tmpl
new file mode 100644 (file)
index 0000000..f1b4324
--- /dev/null
@@ -0,0 +1,5 @@
+This template is used for generating a drop menu.
+<:embed start:>
+<option value="<:url article:>">-- <:article title:></option><:if Children:> <:iterator begin children:>
+<:embed child menu/menu2.tmpl:><:iterator end children:> <:or Children:><:eif Children:> 
+<:embed end:> 
\ No newline at end of file
diff --git a/site/templates/menu/menu2.tmpl b/site/templates/menu/menu2.tmpl
new file mode 100644 (file)
index 0000000..288b8ca
--- /dev/null
@@ -0,0 +1,5 @@
+This template is used for generating a drop menu.
+<:embed start:>
+<option value="<:url article:>">---- <:article title:></option><:if Children:> <:iterator begin children:>
+<:embed child menu/menu3.tmpl:><:iterator end children:> <:or Children:><:eif Children:> 
+<:embed end:> 
\ No newline at end of file
diff --git a/site/templates/menu/menu3.tmpl b/site/templates/menu/menu3.tmpl
new file mode 100644 (file)
index 0000000..062b6a3
--- /dev/null
@@ -0,0 +1,5 @@
+This template is used for generating a drop menu.
+<:embed start:>
+<option value="<:url article:>">------ <:article title:></option><:if Children:> <:iterator begin children:>
+<:embed child menu/menu4.tmpl:><:iterator end children:> <:or Children:><:eif Children:> 
+<:embed end:> 
\ No newline at end of file
diff --git a/site/templates/menu/menu4.tmpl b/site/templates/menu/menu4.tmpl
new file mode 100644 (file)
index 0000000..91b050e
--- /dev/null
@@ -0,0 +1,5 @@
+This template is used for generating a drop menu.
+<:embed start:>
+<option value="<:url article:>">-------- <:article title:></option><:if Children:> <:iterator begin children:>
+<:embed child menu/menu5.tmpl:><:iterator end children:> <:or Children:><:eif Children:> 
+<:embed end:> 
\ No newline at end of file
diff --git a/site/templates/menu/menu5.tmpl b/site/templates/menu/menu5.tmpl
new file mode 100644 (file)
index 0000000..c766341
--- /dev/null
@@ -0,0 +1,5 @@
+This template is used for generating a drop menu.
+<:embed start:>
+<option value="<:url article:>">---------- <:article title:></option><:if Children:> <:iterator begin children:>
+<:embed child menu/menu6.tmpl:><:iterator end children:> <:or Children:><:eif Children:> 
+<:embed end:> 
\ No newline at end of file
index 3540ef6..f9048da 100644 (file)
@@ -122,7 +122,7 @@ my @prebuilt =
     keyword=>'',
     template=>'common/sidebar_section.tmpl',
     link=>'',
-    admin=>$CGI_URI.'/admin/add.pl?id=5',
+    admin=>$CGI_URI.'/admin/admin.pl?id=5',
     threshold=>1000, # ignored
     summaryLength=>1000, #ignored
     generator=>'Generate::Article',
@@ -374,9 +374,9 @@ EOS
     expire=>'9999-12-31 23:59:59',
     lastModified=>'2000-11-27 14:00:00',
     keyword=>'',
-    template=>'common/sidebar_section.tmpl',
+    template=>'common/default.tmpl',
     link=>'/a/format_guide.html',
-    admin=>$CGI_URI.'/admin/add.pl?id=6',
+    admin=>$CGI_URI.'/admin/admin.pl?id=6',
     threshold=>1000, # ignored
     summaryLength=>1000, #ignored
     generator=>'Generate::Article',
@@ -389,7 +389,7 @@ EOS
    {
     id=>7,
     parentid=>2,
-    displayOrder=>10000,
+    displayOrder=>20000,
     title=>'[rss generation]',
     titleImage=>'',
     body=><<'EOS',
@@ -404,7 +404,7 @@ EOS
     keyword=>'',
     template=>'common/rssbase.tmpl',
     link=>'/a/site.rdf',
-    admin=>$CGI_URI.'/admin/add.pl?id=7',
+    admin=>$CGI_URI.'/admin/admin.pl?id=7',
     threshold=>1000, # ignored
     summaryLength=>1000, #ignored
     generator=>'Generate::Article',