implement HTML5 file upload; fix is-public display bug
[scpubgit/stemmaweb.git] / lib / stemmaweb / Controller / Root.pm
index 9d18c67..abc1952 100644 (file)
@@ -1,4 +1,5 @@
 package stemmaweb::Controller::Root;
+use File::Temp;
 use Moose;
 use namespace::autoclean;
 use Text::Tradition::Analysis qw/ run_analysis /;
@@ -33,9 +34,24 @@ components will be loaded.
 sub index :Path :Args(0) {
     my ( $self, $c ) = @_;
 
+       # Are we being asked to load a text immediately? If so 
+       if( $c->req->param('withtradition') ) {
+               $c->stash->{'withtradition'} = $c->req->param('withtradition');
+       }
     $c->stash->{template} = 'index.tt';
 }
 
+=head2 about
+
+A general overview/documentation page for the site.
+
+=cut
+
+sub about :Local :Args(0) {
+       my( $self, $c ) = @_;
+       $c->stash->{template} = 'about.tt';
+}
+
 =head1 Elements of index page
 
 =head2 directory
@@ -74,7 +90,8 @@ sub directory :Local :Args(0) {
        { name: <name>,
          language: <language>,
          public: <is_public>,
-         file: <fileupload> }
+         filename: <filename>,
+         file: <filedata> }
  
 Creates a new tradition belonging to the logged-in user, with the given name
 and the collation given in the uploaded file. The file type is indicated via
@@ -83,6 +100,7 @@ name of the new tradition.
  
 =cut
 
+## TODO Figure out how to mimic old-style HTML file uploads in AJAX / HTML5
 sub newtradition :Local :Args(0) {
        my( $self, $c ) = @_;
        return _json_error( $c, 403, 'Cannot save a tradition without being logged in' )
@@ -91,16 +109,18 @@ sub newtradition :Local :Args(0) {
        my $user = $c->user->get_object;
        # Grab the file upload, check its name/extension, and call the
        # appropriate parser(s).
-       my $upload = $c->request->upload('file');
+       my $upload = File::Temp->new();
+       print $upload $c->request->param('file');
+       close $upload;
        my $name = $c->request->param('name') || 'Uploaded tradition';
        my $lang = $c->request->param( 'language' ) || 'Default';
        my $public = $c->request->param( 'public' ) ? 1 : undef;
-       my( $ext ) = $upload->filename =~ /\.(\w+)$/;
+       my( $ext ) = $c->request->param( 'filename' ) =~ /\.(\w+)$/;
        my %newopts = (
                'name' => $name,
                'language' => $lang,
                'public' => $public,
-               'file' => $upload->tempname
+               'file' => $upload->filename
                );
 
        my $tradition;
@@ -115,7 +135,10 @@ sub newtradition :Local :Args(0) {
                        } catch {
                                $errmsg = "Unexpected parsing error";
                        }
-                       last if $tradition;
+                       if( $tradition ) {
+                               $errmsg = undef;
+                               last;
+                       }
                }
        } elsif( $ext =~ /^(txt|csv|xls(x)?)$/ ) {
                # If it's Excel we need to pass excel => $ext;
@@ -137,7 +160,7 @@ sub newtradition :Local :Args(0) {
                }
        } else {
                # Error unless we have a recognized filename extension
-               return _json_error( $c, 500, "Unrecognized file type extension $ext" );
+               return _json_error( $c, 403, "Unrecognized file type extension $ext" );
        }
        
        # Save the tradition if we have it, and return its data or else the
@@ -173,7 +196,7 @@ sub textinfo :Local :Args(1) {
        my( $self, $c, $textid ) = @_;
        my $tradition = $c->model('Directory')->tradition( $textid );
        unless( $tradition ) {
-               return _json_error( $c, 500, "No tradition with ID $textid" );
+               return _json_error( $c, 404, "No tradition with ID $textid" );
        }       
        my $ok = _check_permission( $c, $tradition );
        return unless $ok;
@@ -223,7 +246,8 @@ sub textinfo :Local :Args(1) {
                if( exists $params->{'owner'} ) {
                        # Only admins can update user / owner
                        my $newownerid = delete $params->{'owner'};
-                       unless( $tradition->has_user && $tradition->user->id eq $newownerid ) {
+                       unless( !$newownerid || 
+                               ( $tradition->has_user && $tradition->user->id eq $newownerid ) ) {
                                unless( $c->user->get_object->is_admin ) {
                                        return _json_error( $c, 403, 
                                                "Only admin users can change tradition ownership" );
@@ -251,11 +275,11 @@ sub textinfo :Local :Args(1) {
                textid => $textid,
                name => $tradition->name,
                language => $tradition->language,
-               public => $tradition->public,
+               public => $tradition->public || 0,
                owner => $tradition->user ? $tradition->user->id : undef,
                witnesses => [ map { $_->sigil } $tradition->witnesses ],
        };
-       my @stemmasvg = map { $_->as_svg({ size => [ 500, 375 ] }) } $tradition->stemmata;
+       my @stemmasvg = map { $_->as_svg() } $tradition->stemmata;
        map { $_ =~ s/\n/ /mg } @stemmasvg;
        $textinfo->{stemmata} = \@stemmasvg;
        $c->stash->{'result'} = $textinfo;
@@ -274,7 +298,7 @@ sub variantgraph :Local :Args(1) {
        my( $self, $c, $textid ) = @_;
        my $tradition = $c->model('Directory')->tradition( $textid );
        unless( $tradition ) {
-               return _json_error( $c, 500, "No tradition with ID $textid" );
+               return _json_error( $c, 404, "No tradition with ID $textid" );
        }       
        my $ok = _check_permission( $c, $tradition );
        return unless $ok;
@@ -301,7 +325,7 @@ sub stemma :Local :Args(2) {
        my $m = $c->model('Directory');
        my $tradition = $m->tradition( $textid );
        unless( $tradition ) {
-               return _json_error( $c, 500, "No tradition with ID $textid" );
+               return _json_error( $c, 404, "No tradition with ID $textid" );
        }       
        my $ok = _check_permission( $c, $tradition );
        return unless $ok;
@@ -314,15 +338,17 @@ sub stemma :Local :Args(2) {
                        try {
                                if( $stemmaid eq 'n' ) {
                                        # We are adding a new stemma.
+                                       $stemmaid = $tradition->stemma_count;
                                        $stemma = $tradition->add_stemma( 'dot' => $dot );
-                                       $stemmaid = $tradition->stemma_count - 1;
+                               } elsif( $stemmaid !~ /^\d+$/ ) {
+                                       return _json_error( $c, 403, "Invalid stemma ID specification $stemmaid" );
                                } elsif( $stemmaid < $tradition->stemma_count ) {
                                        # We are updating an existing stemma.
                                        $stemma = $tradition->stemma( $stemmaid );
                                        $stemma->alter_graph( $dot );
                                } else {
                                        # Unrecognized stemma ID
-                                       return _json_error( $c, 500, "No stemma at index $stemmaid, cannot update" );
+                                       return _json_error( $c, 404, "No stemma at index $stemmaid, cannot update" );
                                }
                        } catch ( Text::Tradition::Error $e ) {
                                return _json_error( $c, 500, $e->message );
@@ -340,7 +366,7 @@ sub stemma :Local :Args(2) {
        if( !$stemma && $tradition->stemma_count > $stemmaid ) {
                $stemma = $tradition->stemma( $stemmaid );
        }
-       my $stemma_xml = $stemma ? $stemma->as_svg( { size => [ 500, 375 ] } ) : '';
+       my $stemma_xml = $stemma ? $stemma->as_svg() : '';
        # What was requested, XML or JSON?
        my $return_view = 'SVG';
        if( my $accept_header = $c->req->header('Accept') ) {
@@ -378,13 +404,13 @@ sub stemmadot :Local :Args(2) {
        my $m = $c->model('Directory');
        my $tradition = $m->tradition( $textid );
        unless( $tradition ) {
-               return _json_error( $c, 500, "No tradition with ID $textid" );
+               return _json_error( $c, 404, "No tradition with ID $textid" );
        }       
        my $ok = _check_permission( $c, $tradition );
        return unless $ok;
        my $stemma = $tradition->stemma( $stemmaid );
        unless( $stemma ) {
-               return _json_error( $c, 500, "Tradition $textid has no stemma ID $stemmaid" );
+               return _json_error( $c, 404, "Tradition $textid has no stemma ID $stemmaid" );
        }
        # Get the dot and transmute its line breaks to literal '|n'
        $c->stash->{'result'} = { 'dot' =>  $stemma->editable( { linesep => '|n' } ) };