add download button for viewable traditions; fixes #8
[scpubgit/stemmaweb.git] / lib / stemmaweb / Controller / Root.pm
index abc1952..30cc644 100644 (file)
@@ -1,5 +1,4 @@
 package stemmaweb::Controller::Root;
-use File::Temp;
 use Moose;
 use namespace::autoclean;
 use Text::Tradition::Analysis qw/ run_analysis /;
@@ -52,6 +51,17 @@ sub about :Local :Args(0) {
        $c->stash->{template} = 'about.tt';
 }
 
+=head2 help/*
+
+A dispatcher for documentation of various aspects of the application.
+
+=cut
+
+sub help :Local :Args(1) {
+       my( $self, $c, $topic ) = @_;
+       $c->stash->{template} = "$topic.tt";
+}
+
 =head1 Elements of index page
 
 =head2 directory
@@ -90,8 +100,7 @@ sub directory :Local :Args(0) {
        { name: <name>,
          language: <language>,
          public: <is_public>,
-         filename: <filename>,
-         file: <filedata> }
+         file: <fileupload> }
  
 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
@@ -100,7 +109,6 @@ 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' )
@@ -109,18 +117,16 @@ 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 = File::Temp->new();
-       print $upload $c->request->param('file');
-       close $upload;
+       my $upload = $c->request->upload('file');
        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 ) = $c->request->param( 'filename' ) =~ /\.(\w+)$/;
+       my( $ext ) = $upload->filename =~ /\.(\w+)$/;
        my %newopts = (
                'name' => $name,
                'language' => $lang,
                'public' => $public,
-               'file' => $upload->filename
+               'file' => $upload->tempname
                );
 
        my $tradition;
@@ -195,6 +201,9 @@ Returns information about a particular text.
 sub textinfo :Local :Args(1) {
        my( $self, $c, $textid ) = @_;
        my $tradition = $c->model('Directory')->tradition( $textid );
+       ## Have to keep users in the same scope as tradition
+       my $newuser;
+       my $olduser;
        unless( $tradition ) {
                return _json_error( $c, 404, "No tradition with ID $textid" );
        }       
@@ -222,7 +231,8 @@ sub textinfo :Local :Args(1) {
                }
                # Handle language param, making Default => null
                my $langval = delete $params->{language} || 'Default';
-               unless( $tradition->language eq $langval ) {
+               
+               unless( $tradition->language eq $langval || !$tradition->can('language') ) {
                        try {
                                $tradition->language( $langval );
                                $changed = 1;
@@ -242,20 +252,23 @@ sub textinfo :Local :Args(1) {
                }
                
                # Handle ownership change
-               my $newuser;
                if( exists $params->{'owner'} ) {
                        # Only admins can update user / owner
                        my $newownerid = delete $params->{'owner'};
                        unless( !$newownerid || 
-                               ( $tradition->has_user && $tradition->user->id eq $newownerid ) ) {
+                               ( $tradition->has_user && $tradition->user->email eq $newownerid ) ) {
                                unless( $c->user->get_object->is_admin ) {
                                        return _json_error( $c, 403, 
                                                "Only admin users can change tradition ownership" );
                                }
-                               $newuser = $m->find_user({ username => $newownerid });
+                               $newuser = $m->find_user({ email => $newownerid });
                                unless( $newuser ) {
                                        return _json_error( $c, 500, "No such user " . $newownerid );
                                }
+                               if( $tradition->has_user ) {
+                                       $olduser = $tradition->user;
+                                       $olduser->remove_tradition( $tradition );
+                               }
                                $newuser->add_tradition( $tradition );
                                $changed = 1;
                        }
@@ -274,11 +287,14 @@ sub textinfo :Local :Args(1) {
        my $textinfo = {
                textid => $textid,
                name => $tradition->name,
-               language => $tradition->language,
+               #language => $tradition->language,
                public => $tradition->public || 0,
-               owner => $tradition->user ? $tradition->user->id : undef,
+               owner => $tradition->user ? $tradition->user->email : undef,
                witnesses => [ map { $_->sigil } $tradition->witnesses ],
        };
+       if( $tradition->can('language') ) {
+               $textinfo->{'language'} = $tradition->language;
+       }
        my @stemmasvg = map { $_->as_svg() } $tradition->stemmata;
        map { $_ =~ s/\n/ /mg } @stemmasvg;
        $textinfo->{stemmata} = \@stemmasvg;
@@ -417,6 +433,30 @@ sub stemmadot :Local :Args(2) {
        $c->forward('View::JSON');
 }
 
+=head2 download
+
+ GET /download/$textid
+Returns the full XML definition of the tradition and its stemmata, if any.
+=cut
+
+sub download :Local :Args(1) {
+       my( $self, $c, $textid ) = @_;
+       my $tradition = $c->model('Directory')->tradition( $textid );
+       unless( $tradition ) {
+               return _json_error( $c, 404, "No tradition with ID $textid" );
+       }
+       my $ok = _check_permission( $c, $tradition );
+       return unless $ok;
+       try {
+               $c->stash->{'result'} = $tradition->collation->as_graphml();
+       } catch( Text::Tradition::Error $e ) {
+               return _json_error( $c, 500, $e->message );
+       }
+       $c->forward('View::GraphML');
+}
+
 ####################
 ### Helper functions
 ####################