Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#!/usr/bin/perl -wuse strict;use WebDB;use HTML::Tiny;use CGI qw/param header start_html url uploadInfo/;my $h = HTML::Tiny->new( mode => 'html' );my %F;my $pageTitle = "CC Manage Coffee";my $homeURL = "/";my $DBTable = "coffees";my %FIELDS = (roaster => [qw(Roaster 1 select required)],coffee => [qw(Coffee 2 text required)],region => [qw(Region 3 text required)],source => [qw(Source 4 select required)],rating => [qw(Rating 5 select)],note => [qw(Notes 6 textarea)],logo => [qw(Image 7 image)]);my %fieldDisplayName = map { $_ => $FIELDS{$_}->[0] } keys %FIELDS;my %fieldType = map { $_ => $FIELDS{$_}->[2] } keys %FIELDS;my @requiredFields = sort fieldOrder grep { defined $FIELDS{$_}->[3] } keys %FIELDS;my @DBFields = sort fieldOrder grep { $fieldType{$_} =~ /^(text|select)/ } keys %FIELDS;my $primary = $DBFields[0];my $secondary = $DBFields[1];sub fieldOrder {$FIELDS{$a}->[1] <=> $FIELDS{$b}->[1];}sub saveForm {my $FTS = shift;my $dbh = WebDB::connect ();if ($FTS->{logo}) {use Image::Magick;my $mime_type = uploadInfo ($FTS->{logo})->{'Content-Type'};my ($full, $thumb) = read_image_file ($FTS->{logo});$dbh->do ("INSERT INTO $DBTable(roaster,coffee,logo,thumbnail,region,note,mime_type,source,rating,date_added)VALUES(?,?,?,?,?,?,?,?,?,now())ON DUPLICATE KEY UPDATE logo = ?, thumbnail = ?, region = ?, note = ?, mime_type = ?, source = ?, rating = ?",undef,$FTS->{roaster}, $FTS->{coffee}, $full, $thumb, $FTS->{region}, $FTS->{note}, $mime_type, $FTS->{source}, $FTS->{rating},$full, $thumb, $FTS->{region}, $FTS->{note}, $mime_type, $FTS->{source}, $FTS->{rating});} else {$dbh->do ("INSERT INTO $DBTable(roaster,coffee,region,note,source,rating,date_added)VALUES(?,?,?,?,?,?,now())ON DUPLICATE KEY UPDATE region = ?, note = ?, source = ?, rating = ?",undef,$FTS->{roaster}, $FTS->{coffee}, $FTS->{region}, $FTS->{note}, $FTS->{source}, $FTS->{rating},$FTS->{region}, $FTS->{note}, $FTS->{source}, $FTS->{rating});}$dbh->disconnect (); # Image was stored into database successfully.}sub select_rating {my $value = shift // "";return $h->select ({ name=>"rating" },[ map { $value eq $_ ?$h->option ({ value=>$_, selected=>[] }, $_) :$h->option ({ value=>$_ }, $_)} "", 1..5]);}sub select_source {my $value = shift // "";return $h->select ({ name=>"source" },[ map { $value eq $_ ?$h->option ({ value=>$_, selected=>[] }, $_) :$h->option ({ value=>$_ }, $_)} "", qw(Direct Fellow Retail SCG) ]);}sub select_roaster {my $value = shift // "";my @roasters;my $dbh = WebDB::connect ();@roasters = map { @$_ } $dbh->selectall_array ("select distinct roaster from roasters order by roaster");$dbh->disconnect ();return $h->select ({ name=>"roaster" },[ map { $value eq $_ ?$h->option ({ value=>$_, selected=>[] }, $_) :$h->option ({ value=>$_ }, $_)} "", @roasters ]);}print header (),start_html (-title => "Add / Update Coffee", -style => {'src' => "style.css"} );print $h->div ({ class => "accent pageheader" }, [$h->h1 ($pageTitle),$h->div ({ class=>"sp0" }, [$h->div ({ class=>"spLeft" }, []),$h->div ({ class=>"spRight" }, [$h->input ({ type=>"button", value=>"Home", onClick=>"window.location.href='$homeURL'" }),]),]),]);my $choice = param ("choice") // "";if ($choice eq "Save") {process_form ();} elsif (defined (param ($primary)) and defined (param ($secondary))) {my $thing = param ($primary);my $thing2 = param ($secondary);display_form ({ $primary => $thing, $secondary => $thing2 }, $choice);} else {display_form (); # blank form}print $h->close ("html");sub display_form {my $R = shift;my $view = shift // "";my $actionbutton;my ($I, $logo);if ($R) {# we're dealing with an existing thing. Get the current values out of the DB...my $dbh = WebDB::connect ();@F{@DBFields} = $dbh->selectrow_array ("SELECT ". join (", ", @DBFields) ." FROM $DBTable WHERE $primary = ? and $secondary = ?",undef, $R->{$primary}, $R->{$secondary});$dbh->disconnect ();my $i = "serve_image.pl" . sprintf ("?roaster=%s", $h->url_encode ($R->{$primary}));$i .= sprintf ("&coffee=%s", $h->url_encode ($R->{$secondary}));$I = $h->img ({ src => "$i;thumbnail=1", class=>"show", alt => $R->{$primary} });$I .= $h->img ({ src => "$i", class=>"hide", alt => $R->{$primary} });# did we find a record?error ("Cannot find a database entry for '$R->{$primary}'") unless defined $F{$DBFields[0]};if ($view eq "Update") {# We'd like the update that thing, give the user a form...print $h->p ("Updating Coffee: $R->{$primary}, $R->{$secondary}...");foreach (@DBFields) {$F{$_} = formField ($_, $F{$_});}$logo = $I.' ' . formField ('logo');$actionbutton = formField ("choice", "Save");$actionbutton .= formField ("Cancel");} else {# We're just looking at it...print $h->p ("Viewing Coffee: $R->{$primary}, $R->{$secondary}...");$logo = $I;$F{$DBFields[0]} .= $h->input ({ type=>"hidden", name=>$DBFields[0], value=> $F{$DBFields[0]} });$F{$DBFields[0]} .= $h->input ({ type=>"hidden", name=>$DBFields[1], value=> $F{$DBFields[1]} });$actionbutton = formField ("choice", "Update");if ($view eq "POSTSAVE") {$actionbutton .= formField ("Cancel", "Back", "POSTSAVE");} else {$actionbutton .= formField ("Cancel", "Back");}}} else {print $h->p ("Adding a new Coffee...");foreach (@DBFields) {$F{$_} = formField ($_);}$logo = formField ('logo');$actionbutton = formField ("choice", "Save");$actionbutton .= formField ("Cancel");}print $h->open ("form", { action => url (), method=>"POST", enctype=>"multipart/form-data" });print $h->div ({ class=>"sp0" },$h->div ({ class=>"rTable" }, [ map ({$h->div ({ class=>"rTableRow" }, [$h->div ({ class=>"rTableCell right top" }, "$fieldDisplayName{$_}: "),$h->div ({ class=>"rTableCell" }, $F{$_})])} @DBFields),$h->div ({ class=>"rTableRow" }, [$h->div ({ class=>"rTableCell right top" }, "$fieldDisplayName{'logo'}: "),$h->div ({ class=>"rTableCell" }, $logo)]),]));print $actionbutton;print $h->close ("form");printJavascript ();}sub process_form {my %FORM;foreach (keys %FIELDS) {if ($fieldType{$_} =~ /^text/) {$FORM{$_} = WebDB::trim param ($_) // "";} else {$FORM{$_} = param ($_) // "";}}# check for required fieldsmy @errors = ();foreach (@requiredFields) {push @errors, "$fieldDisplayName{$_} is missing." if $FORM{$_} eq "";}if (@errors) {print $h->div ({ class=>"error" }, [$h->p ("The following errors occurred:"),$h->ul ($h->li (@errors)),$h->p ("Please click your Browser's Back button to\n". "return to the previous page and correct the problem.")]);return;} # Form was okay; get image type and contents and create new record.saveForm (\%FORM);print $h->p ({ class=>"success" }, "Coffee successfully saved.");display_form ({ roaster=>$FORM{roaster}, coffee=>$FORM{coffee} }, "POSTSAVE");}sub read_image_file {my $fh = shift; # filename/file handlemy $img = new Image::Magick;my $fullimg = new Image::Magick;my ($full, $thumb);my $err;# read full-size image directly from upload file(read ($fh, $full, (stat ($fh))[7]) == (stat ($fh))[7])or error ("Can't read image file: $!");# produce thumbnail from full-size image$err = $img->BlobToImage ($full);error ("Can't convert image data: $err") if $err;$err = $fullimg->BlobToImage ($full);error ("Can't convert image data: $err") if $err;if ($fullimg->Get("width") > 300 or $fullimg->Get("height") > 300) {$err = $fullimg->Scale (geometry => "300x300");error ("Can't scale image file: $err") if $err;}$err = $img->Scale (geometry => "64x64");error ("Can't scale image file: $err") if $err;$thumb = $img->ImageToBlob ();$full = $fullimg->ImageToBlob ();return ($full, $thumb);}sub error {my $msg = shift;print $h->p ({ class=>"error" }, "Error: $msg");print $h->close("html");exit (0);}sub formField {my $name = shift;my $value = shift // '';my $context = shift // '';my $type = $fieldType{$name} // "button";if ($type eq "image") {return $h->input ({name => $name,class => "inputfile",type => "file",id => "file",size => 60}) . $h->label ({ for=>"file", class=>"top" }, $h->span ("Choose File..."));} elsif ($type eq "button") {if ($name eq "Cancel") {if ($context eq "POSTSAVE") {return $h->input ({ type=>"button", value => $value ne '' ? $value : "Cancel" , onClick=>"window.location.href = \"coffees.pl\"; return false;" })} else {return $h->input ({ type=>"button", value => $value ne '' ? $value : "Cancel" , onClick=>"history.back(); return false;" })}} else {return $h->input ({ type=>"submit", value => $value, name=>$name })}} elsif ($type eq "textarea") {return $h->tag ("textarea", {name => $name,override => 1,cols => 30,rows => 4}, $value);} elsif ($type eq "select") {no strict;return &{"select_".$name} ($value);} else {return $h->input ({name => $name,type => $type,value => $value,required => [],override => 1,size => 30});}}sub printJavascript {print<<JSCRIPT;<SCRIPT language="JavaScript"><!--var inputs = document.querySelectorAll( '.inputfile' );Array.prototype.forEach.call( inputs, function( input ){var label = input.nextElementSibling,labelVal = label.innerHTML;input.addEventListener( 'change', function( e ){var fileName = e.target.value.split( '\\\\' ).pop();if( fileName )label.querySelector( 'span' ).innerHTML = fileName;elselabel.innerHTML = labelVal;});});//--></SCRIPT>JSCRIPT}